参考下面时间戳的命名方式代码 import logging from maix import camera, display, image, nn, app, uart, time import requests import json import os import threading from datetime import datetime # 日志配置 logging.basicConfig( level=logging.INFO, format='%(asctime)s [%(levelname)s] %(message)s', handlers=[ logging.FileHandler("/root/operation.log"), logging.StreamHandler() ] ) logger = logging.getLogger("MAIX_PRO") # 状态定义 class SystemState: NORMAL = 0 # 正常检测模式 OBJECT_DETECTED = 1 # 物体检测处理中 SPECIAL_HANDLING = 2# 特殊处理模式(标签19) WAIT_FOR_LABEL1 = 3 # 等待标签1状态 # 模型加载 try: detector = nn.YOLOv5(model="/root/models/mymodels/model_195130.mud", dual_buff=True) logger.info("YOLOv5 model loaded") except Exception as e: logger.critical(f"Model load failed: {str(e)}") exit(1) # 保存目录 # SAVE_DIR = "/root/models/mymodel/" SAVE_DIR = "/boot/Pictures/" os.makedirs(SAVE_DIR, exist_ok=True) # 硬件初始化(调整为硬件支持的分辨率) try: cam = camera.Camera(width=1080, height=640) # 使用标准VGA分辨率 logger.debug(f"Camera resolution: {cam.width()}x{cam.height()}") except RuntimeError as e: logger.critical(f"Camera init failed: {str(e)}") exit(1) disp = display.Display() # UART初始化 device = "/dev/ttyS0" serial0 = uart.UART(device, 38400) logger.info("UART initialized") # 登录获取token login_url = "http://111.230.114.23/api/user/login" headers_login = {'Content-Type': 'application/json'} login_data = {"userAccount": "lanyating", "userPassword": 12345678} json_data = json.dumps(login_data) try: login_response = requests.post(login_url, data=json_data, headers=headers_login) response_json = login_response.json() token = response_json.get('data') if token: logger.info(f"Login successful, token obtained: {token[:10]}...") # 只显示部分token以保护隐私 else: logger.error(f"Login failed: No token returned in response") exit(1) except Exception as e: logger.critical(f"Login failed: {str(e)}") exit(1) def send_uart(data): try: serial0.write_str(data + "\n") logger.info(f"UART sent: {data}") except Exception as e: logger.error(f"UART send failed: {str(e)}") class OperationController: def __init__(self): self.state = SystemState.NORMAL self.current_label = None self.last_detect_time = 0 self.upload_complete = False self.lock = threading.Lock() self.timers = [] # 初始发送forward self.send_uart("forward") # 初始化 photo_url 和 data_url self.photo_url = "http://111.230.114.23/api/file/upload" self.data_url = "http://111.230.114.23/api/data/add" # 确保 token 在整个类中可用 self.token = token def send_uart(self, command): try: serial0.write_str(command + "\n") logger.info(f"UART sent: {command}") except Exception as e: logger.error(f"UART send failed: {str(e)}") def save_and_upload(self, img, label): try: # 生成文件名 timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") filename = f"{SAVE_DIR}{label}_{timestamp}.jpg" # 保存图片 if img.save(filename, quality=90): logger.info(f"Image saved: {filename}") # 同步上传 with open(filename, 'rb') as file: files = { 'file': ('image.jpg', file, 'image/jpeg') } params = { 'biz': 'plant_picture', } headers = { "token": self.token } logger.info(f"Uploading {filename} with label {label}, Token: {self.token[:10]}...") response = requests.post( self.photo_url, files=files, headers=headers, params=params ) if response.json().get('code') == 0 : logger.info(f"Upload success: {filename}, Response: {response.text}") return response.json().get('data') else: logger.warning(f"Upload failed: {response.text}") else: logger.error("Image save failed") except Exception as e: logger.error(f"Capture failed: {str(e)}") return None def save_data(self, data): try: params = [{ "deviceName": 1, "plantId": 1, "growthStage": "flowering", "healthStage": "healthy", "height": "5", "crownWidth": "5", "humidity": '', "ph": '', "dan": '', "lin": '', "jia": '', "photoUrl": data, "notes": "" }] headers = { "token": self.token } response = requests.post( self.data_url, headers=headers, json=params ) logger.info(f"Response: {data}") if response.json().get('code') == 0 : logger.info(f"Data save success: {response.text}") else: logger.warning(f"Data save failed: {response.text}") except Exception as e: logger.error(f"Data upload error: {str(e)}") def handle_detection(self, objs, img): with self.lock: current_time = time.time() # 状态机逻辑 if self.state == SystemState.NORMAL: for obj in objs: if obj.class_id == 19: logger.info("Special label 19 detected") self.state = SystemState.SPECIAL_HANDLING self.send_uart("stop") # 1秒后保存并上传 def delayed_save(): print("开始上传") data = self.save_and_upload(img, 19) print("上传成功") if data: self.save_data(data) self.send_uart("back") self.add_timer(1.0, delayed_save) break elif 1 <= obj.class_id <= 18: logger.info(f"Label {obj.class_id} detected") self.state = SystemState.OBJECT_DETECTED self.send_uart("stop") # 1秒后保存并上传 def delayed_save(): print("开始上传") data = self.save_and_upload(img, obj.class_id) print("上传成功") if data: self.save_data(data) self.add_timer(1.0, delayed_save) # 2秒后发送forward def delayed_forward(): self.send_uart("forward") self.state = SystemState.NORMAL self.add_timer(2.0, delayed_forward) break elif self.state == SystemState.SPECIAL_HANDLING: # 等待上传完成 pass # 在同步上传的情况下不需要等待标志位 elif self.state == SystemState.WAIT_FOR_LABEL1: for obj in objs: if obj.class_id == 1: logger.info("Label1 after special handling") self.send_uart("stop") self.add_timer(1.0, lambda: self.send_uart("forward")) self.state = SystemState.NORMAL break def add_timer(self, delay, callback): timer = threading.Timer(delay, callback) timer.start() self.timers.append(timer) def cleanup(self): for timer in self.timers: timer.cancel() logger.info("System cleanup completed") # 主控制实例 controller = OperationController() # 创建 Color 对象 red_color = image.Color(255, 0, 0) # 定义标准红色 # 主循环 try: while not app.need_exit(): try: img = cam.read() except Exception as e: logger.error(f"摄像头读取失败: {str(e)}") continue # 执行检测 try: objs = detector.detect(img, conf_th=0.6) except Exception as e: logger.error(f"目标检测失败: {str(e)}") disp.show(img) continue # 处理结果 if len(objs) > 0: controller.handle_detection(objs, img) # 显示画面 for obj in objs: # 绘制检测框(使用位置参数) img.draw_rect( obj.x, obj.y, obj.w, obj.h, red_color, # 颜色参数位置 2 # 线宽参数位置 ) # 绘制标签文本 img.draw_string( obj.x, obj.y, f"{detector.labels[obj.class_id]} {obj.score:.2f}", scale=0.5, color=red_color ) disp.show(img) except KeyboardInterrupt: logger.info("用户中断") except Exception as e: logger.critical(f"致命错误: {str(e)}") finally: controller.cleanup() logger.info("系统关闭") ******************************************************************************** cvi_bin_isp message gerritId: 97347 commitId: fc6ce647 md5: d6db2297ddfd44e8252c1f3f888f47b2 sensorNum 1 sensorName0 5440577 PQBIN message gerritId: commitId: fc6ce647 md5: d6db2297ddfd44e8252c1f3f888f47b2 sensorNum 1 sensorName0 5440577 author: lxowalle desc: os04a10 createTime: 2024-08-30 11:00:43version: tool Version: v3.0.5.48 mode: ******************************************************************************** [SAMPLE_COMM_ISP_Thread]-95: ISP Dev 0 running! 0 R:1257 B:3920 CT:2788 1 R:1588 B:2858 CT:3968 2 R:2169 B:1819 CT:7154 Golden 1588 1024 2858 wdrLEOnly:1 time: 1 Traceback (most recent call last): File "/tmp/maixpy_run/main.py", line 59, in <module> timestamp = f"{str(now[0])[-2:]}_{str(now[1]).zfill(2)}{str(now[2]).zfill(2)}_{str(now[3]).zfill(2)}{str(now[4]).zfill(2)}" ~~~^^^ TypeError: 'maix._maix.time.DateTime' object is not subscriptable maix multi-media driver released. ISP Vipipe(0) Free pa(0x8a6ee000) va(0x0x3fbeaf7000) program exit failed. exit code: 1.
时间: 2025-07-25 07:30:47 浏览: 1
<think>我们遇到了一个错误:`TypeError: 'maix._maix.time.DateTime' object is not subscriptable`
这是因为在第一个代码中,我们使用了`time.localtime()`返回的是一个`DateTime`对象,而不是一个元组。因此不能通过下标访问。
在第二个参考代码中,我们使用了Python标准库的`datetime`模块,它返回的是可以下标访问的元组吗?实际上,在参考代码中,我们使用的是`datetime.now()`,它返回一个`datetime`对象,然后调用`strftime`方法格式化。
在MaixPy中,`time.localtime()`返回的是一个`DateTime`对象,它有自己的属性:year, month, day, hour, minute, second, weekday, yearday。
因此,我们需要修改时间戳生成的代码,使用属性访问而不是下标。
修改如下:
原代码:
now = time.localtime()
timestamp = f"{str(now[0])[-2:]}_{str(now[1]).zfill(2)}{str(now[2]).zfill(2)}_{str(now[3]).zfill(2)}{str(now[4]).zfill(2)}"
应该改为:
now = time.localtime()
# 获取年份的后两位
year_short = str(now.year)[-2:]
month = str(now.month).zfill(2)
day = str(now.day).zfill(2)
hour = str(now.hour).zfill(2)
minute = str(now.minute).zfill(2)
timestamp = f"{year_short}_{month}{day}_{hour}{minute}"
另外,在第一个代码中,我们使用的是`time`模块,它是MaixPy的time模块,不是Python标准库的datetime模块。
所以,我们只需要修改时间戳生成部分即可。
同时,我们注意到在第一个代码中,保存图片的代码段位于检测到圆形且满足保存间隔条件时。如果长时间没有检测到圆形,则不会保存图片。这可能是设计意图,但需要注意。
修改后的代码段如下:
```python
if time_since_last_save >= save_interval:
# 获取当前时间并格式化为时间戳字符串
now = time.localtime()
# 使用属性访问
year_short = str(now.year)[-2:] # 取年份后两位
month = str(now.month).zfill(2) # 月份补零
day = str(now.day).zfill(2) # 日期补零
hour = str(now.hour).zfill(2) # 小时补零
minute = str(now.minute).zfill(2) # 分钟补零
timestamp = f"{year_short}_{month}{day}_{hour}{minute}"
img_path = os.path.join(save_dir, f"{timestamp}.jpg")
cv2.imwrite(img_path, img_cv) # 保存原始图像
print(f"保存图片: {img_path}")
last_save_time = current_time
```
这样修改后,应该可以避免下标访问的错误。
完整修改后的代码(只修改了时间戳生成部分)如下:</think>我注意到代码中时间戳生成部分存在问题:`TypeError: 'maix._maix.time.DateTime' object is not subscriptable`。这是因为MaixPy的`time.localtime()`返回的是自定义的DateTime对象,而不是可索引的元组。以下是修正后的代码:
```python
from maix import image, display, app, time, camera
import cv2
import os
# 创建保存图片的目录
save_dir = '/boot/shengwu'
if not os.path.exists(save_dir):
os.makedirs(save_dir)
disp = display.Display()
cam = camera.Camera(320, 240, image.Format.FMT_BGR888)
# 初始化圆形跟踪参数
last_circles = None
circle_count = 0
last_save_time = 0
save_interval = 5000 # 保存间隔时间,单位为毫秒
while not app.need_exit():
img = cam.read()
# convert maix.image.Image object to numpy.ndarray object
t = time.ticks_ms()
img_cv = image.image2cv(img, ensure_bgr=False, copy=False)
print("time: ", time.ticks_ms() - t)
# 创建用于显示的图像副本
img_display = img_cv.copy()
# 圆形检测
gray = cv2.cvtColor(img_cv, cv2.COLOR_BGR2GRAY)
gray = cv2.medianBlur(gray, 5)
# 使用霍夫圆变换检测圆形
circles = cv2.HoughCircles(
gray, # 输入图像
cv2.HOUGH_GRADIENT, # 检测方法
1, # 累加器图像的分辨率与输入图像之比
30, # 检测到的圆的圆心之间的最小距离
param1=100, # Canny边缘检测的高阈值
param2=30, # 累加器阈值,值越小,检测到的圆越多
minRadius=10, # 最小圆半径
maxRadius=100 # 最大圆半径
)
current_time = time.ticks_ms()
time_since_last_save = current_time - last_save_time
# 如果检测到圆形
if circles is not None:
circles = circles[0, :].astype("int")
last_circles = circles
circle_count += 1
# 保存未绘制标记的原始图像
if time_since_last_save >= save_interval:
# 获取当前时间并格式化为时间戳字符串
now = time.localtime()
# 正确访问DateTime对象的属性
year_short = str(now.year)[-2:] # 取年份后两位
month = str(now.month).zfill(2) # 月份补零
day = str(now.day).zfill(2) # 日期补零
hour = str(now.hour).zfill(2) # 小时补零
minute = str(now.minute).zfill(2) # 分钟补零
timestamp = f"{year_short}_{month}{day}_{hour}{minute}"
img_path = os.path.join(save_dir, f"{timestamp}.jpg")
cv2.imwrite(img_path, img_cv) # 保存原始图像
print(f"保存图片: {img_path}")
last_save_time = current_time
# 绘制检测到的圆形
for (x, y, r) in circles:
cv2.circle(img_display, (x, y), r, (0, 255, 0), 2)
cv2.circle(img_display, (x, y), 2, (0, 0, 255), 3)
cv2.putText(img_display, f"({x}, {y})", (x - 20, y - 10),
cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 1)
# 如果之前检测到过圆形但当前帧没有检测到
elif last_circles is not None:
for (x, y, r) in last_circles:
overlay = img_display.copy()
cv2.circle(overlay, (x, y), r, (0, 255, 255), 2)
cv2.addWeighted(overlay, 0.5, img_display, 0.5, 0, img_display)
# 在画面上显示剩余保存时间
remaining_time = max(0, (save_interval - time_since_last_save) // 1000)
cv2.putText(img_display, f"下次保存: {remaining_time}秒", (10, 20),
cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 0, 0), 1)
# show by maix.display
img_show = image.cv2image(img_display, bgr=True, copy=False)
disp.show(img_show)
```
### 关键修正说明:
1. **DateTime对象访问方式**:
```python
# 错误方式(下标访问):
now = time.localtime()
timestamp = f"{str(now[0])[-2:]}_{str(now[1]).zfill(2)}{str(now[2]).zfill(2)}_{str(now[3]).zfill(2)}{str(now[4]).zfill(2)}"
# 正确方式(属性访问):
now = time.localtime()
year_short = str(now.year)[-2:]
month = str(now.month).zfill(2)
day = str(now.day).zfill(2)
hour = str(now.hour).zfill(2)
minute = str(now.minute).zfill(2)
timestamp = f"{year_short}_{month}{day}_{hour}{minute}"
```
2. **MaixPy时间对象特性**:
- `time.localtime()` 返回的是包含以下属性的对象:
- `year` (完整年份,如2025)
- `month` (1-12)
- `day` (1-31)
- `hour` (0-23)
- `minute` (0-59)
- `second` (0-59)
- 不能使用下标访问,必须使用属性访问
3. **格式化增强**:
- 使用`.zfill(2)`确保所有时间组件都是两位数
- 年份取后两位:`str(now.year)[-2:]`
### 其他改进建议:
1. **添加异常处理**:
```python
try:
cv2.imwrite(img_path, img_cv)
except Exception as e:
print(f"保存图片失败: {str(e)}")
```
2. **时间精度提升**:
如果需要秒级精度:
```python
second = str(now.second).zfill(2)
timestamp = f"{year_short}_{month}{day}_{hour}{minute}{second}"
```
3. **防止文件名冲突**:
```python
import random
rand_suffix = random.randint(100, 999)
timestamp = f"{year_short}_{month}{day}_{hour}{minute}_{rand_suffix}"
```
阅读全文
相关推荐


















