From 89fcb4e6bb8d433e0ce27f321638ddeade575976 Mon Sep 17 00:00:00 2001 From: Mason Huang Date: Fri, 11 Apr 2025 15:22:25 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=20mutiple=20bounding=20boxes?= =?UTF-8?q?=20=E9=A1=AF=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 6 +-- README.md | 11 +++- src/controllers/media_controller.py | 47 ++++------------- .../__pycache__/mainWindows.cpython-312.pyc | Bin 16245 -> 0 bytes src/views/mainWindows.py | 48 ++++++++++++++---- update_diary.md | 22 ++++++-- 6 files changed, 80 insertions(+), 54 deletions(-) delete mode 100644 src/views/__pycache__/mainWindows.cpython-312.pyc diff --git a/.gitignore b/.gitignore index 4b296f3..660c7b1 100644 --- a/.gitignore +++ b/.gitignore @@ -34,9 +34,9 @@ temp/ __pycache__/ *.py[cod] *$py.class -src/__pycache__/config.cpython-312.pyc -src/services/__pycache__/device_service.cpython-312.pyc -src/views/__pycache__/mainWindows.cpython-312.pyc +src/__pycache__/ +src/services/__pycache__/ +src/views/__pycache__/ main.spec dist/output/ dist/main.exe diff --git a/README.md b/README.md index 6ca58db..718ddaa 100644 --- a/README.md +++ b/README.md @@ -209,4 +209,13 @@ global config 範例如下 } ] } -``` \ No newline at end of file +``` + +## bounding boxes 格式 + ``` + { + "num_boxes": 2, + "bounding boxes": [[x1, y1, x2, y2], [x3, y3, x4, y4]], + "results": ["label1", "label2"] + } + ``` \ No newline at end of file diff --git a/src/controllers/media_controller.py b/src/controllers/media_controller.py index 5a1bae2..8b1076f 100644 --- a/src/controllers/media_controller.py +++ b/src/controllers/media_controller.py @@ -76,27 +76,23 @@ class MediaController: if hasattr(self.main_window, 'canvas_label'): pixmap = QPixmap.fromImage(qt_image) - # 如果有邊界框,繪製它 - if hasattr(self.main_window, 'current_bounding_box') and self.main_window.current_bounding_box is not None: + # 如果有邊界框,繪製它們 + if hasattr(self.main_window, 'current_bounding_boxes') and self.main_window.current_bounding_boxes is not None: painter = QPainter(pixmap) pen = QPen(Qt.red) pen.setWidth(2) painter.setPen(pen) - # 獲取邊界框 - bbox_info = self.main_window.current_bounding_box - - # 檢查邊界框格式 - if isinstance(bbox_info, dict) and "bounding box" in bbox_info: - # 從字典中獲取邊界框座標 - bbox = bbox_info["bounding box"] - if len(bbox) >= 4: + # 遍歷並繪製所有邊界框 + for bbox_info in self.main_window.current_bounding_boxes: + # 確保邊界框資訊是合法的 + if isinstance(bbox_info, list) and len(bbox_info) >= 4: # 繪製矩形 - x1, y1, x2, y2 = bbox[0], bbox[1], bbox[2], bbox[3] + x1, y1, x2, y2 = bbox_info[0], bbox_info[1], bbox_info[2], bbox_info[3] painter.drawRect(QRect(x1, y1, x2 - x1, y2 - y1)) - # 如果有結果標籤,繪製它 - if "result" in bbox_info: + # 如果有標籤(邊界框的第5個元素),繪製它 + if len(bbox_info) > 4 and bbox_info[4]: font = QFont() font.setPointSize(10) painter.setFont(font) @@ -110,28 +106,7 @@ class MediaController: if label_y < 10: label_y = y2 + 15 # 如果上方空間不足,放在底部 - painter.drawText(label_x, label_y, bbox_info["result"]) - elif isinstance(bbox_info, list) and len(bbox_info) >= 4: - # 直接使用列表作為邊界框座標 - x1, y1, x2, y2 = bbox_info[0], bbox_info[1], bbox_info[2], bbox_info[3] - painter.drawRect(QRect(x1, y1, x2 - x1, y2 - y1)) - - # 如果有標籤,繪製它 - if len(bbox_info) > 4 and bbox_info[4]: - font = QFont() - font.setPointSize(10) - painter.setFont(font) - painter.setPen(QColor(255, 0, 0)) # 紅色 - - # 計算標籤位置(邊界框上方) - label_x = x1 - label_y = y1 - 10 - - # 確保標籤在畫布範圍內 - if label_y < 10: - label_y = y2 + 15 # 如果上方空間不足,放在底部 - - painter.drawText(label_x, label_y, bbox_info[4]) + painter.drawText(label_x, label_y, str(bbox_info[4])) painter.end() @@ -286,7 +261,7 @@ class MediaController: self._inference_paused = not self._inference_paused if self._inference_paused: # 暫停時清除邊界框 - self.main_window.current_bounding_box = None + self.main_window.current_bounding_boxes = None else: # 恢復推論時,確保相機仍在運行 if self.video_thread is None or not self.video_thread.isRunning(): diff --git a/src/views/__pycache__/mainWindows.cpython-312.pyc b/src/views/__pycache__/mainWindows.cpython-312.pyc deleted file mode 100644 index 7ef550770e432d8898ee73243990c8741486c4ef..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16245 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 4: - # 確保邊界框列表至少有5個元素 - while len(self.current_bounding_box) < 5: - self.current_bounding_box.append(None) - # 設置第5個元素為結果標籤 - self.current_bounding_box[4] = result["result"] + # 確保邊界框列表至少有5個元素 + while len(self.current_bounding_boxes[0]) < 5: + self.current_bounding_boxes[0].append(None) + # 設置第5個元素為結果標籤 + self.current_bounding_boxes[0][4] = result["result"] + + # 不需要顯示彈窗,因為邊界框會直接繪製在畫面上 + return + # 新格式: 多邊界框 + elif isinstance(result, dict) and "bounding boxes" in result: + bboxes = result["bounding boxes"] + results = result.get("results", []) + + # 確保邊界框是列表格式 + if not isinstance(bboxes, list): + print("錯誤: 'bounding boxes' 必須是列表格式") + return + + # 如果只有邊界框座標沒有標籤 + if not results: + self.current_bounding_boxes = bboxes + else: + # 結合邊界框和標籤 + self.current_bounding_boxes = [] + for i, bbox in enumerate(bboxes): + # 創建包含座標的新列表 + new_bbox = list(bbox) + # 添加標籤(如果有) + if i < len(results): + new_bbox.append(results[i]) + else: + new_bbox.append(None) + self.current_bounding_boxes.append(new_bbox) # 不需要顯示彈窗,因為邊界框會直接繪製在畫面上 return diff --git a/update_diary.md b/update_diary.md index 5d897a7..30a83ba 100644 --- a/update_diary.md +++ b/update_diary.md @@ -1,6 +1,22 @@ -### 0411 +### 0410 1. 修改 repo 中的資料, 添加 .gitignore -> 0.5 hrs -2. 開會 meeting -> 1.5 hrs +2. 準備資料 + 開會 meeting -> 2 hrs #### total: 2 hrs --- -### \ No newline at end of file +### 0411 +1. 解決 yolov5s 報錯: 將 input image 調整成 1500 * 1500 之後再把結果 mapping 回原先影像大小 + ``` + Error code: 22. Description: ApiReturnCode KP_ERROR_IMAGE_RESOLUTION_TOO_SMALL_22 + ``` + +2. 修正 yolov5s 的回傳資料以符合 bounding box 顯示的格式 +3. 添加 yolov5s classname mapping 機制 +4. 添加 mutiple bounding boxes 顯示 + ``` + { + "num_boxes": 2, + "bounding boxes": [[x1, y1, x2, y2], [x3, y3, x4, y4]], + "results": ["label1", "label2"] + } + ``` +5. 更新 README.md: 添加 bounding boxes 的 return value \ No newline at end of file