
接上一篇图像预处理这次把轮廓检测和面积计算撸出来。轮廓提取、最大面积筛选、ROI坐标校正、轮廓绘制——最重要的都在了。一、轮廓检测整体流程┌─────────────────────────────────────────────────────────────┐ │ 液滴轮廓检测流程 │ ├─────────────────────────────────────────────────────────────┤ │ 1. 图像预处理上一篇已讲 │ │ └─ 灰度转换 → 高斯模糊 → OTSU二值化 → Canny边缘检测 │ │ │ │ 2. 轮廓提取 │ │ └─ cv2.findContours() 提取所有轮廓 │ │ │ │ 3. 轮廓筛选 │ │ └─ 选择面积最大的轮廓作为液滴轮廓 │ │ │ │ 4. 轮廓坐标校正ROI模式 │ │ └─ 将ROI内的坐标转换回原图坐标 │ │ │ │ 5. 轮廓绘制与面积计算 │ │ └─ 绘制轮廓 → 计算面积 → 更新显示 │ └─────────────────────────────────────────────────────────────┘二、轮廓提取findContours2.1 参数说明contours, _ cv2.findContours(edges.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)参数值说明imageedges.copy()二值化边缘图像必须传副本modecv2.RETR_EXTERNAL只检测最外层轮廓methodcv2.CHAIN_APPROX_SIMPLE压缩轮廓点只保留拐点2.2 完整检测代码def auto_detect_droplet(self): 自动检测液滴轮廓支持区域选择 if self.original_image is None: return False, 请先加载图像 # 1. ROI选择可选 if self.is_region_mode and len(self.region_points) 2: x1, y1 self.region_points[0] x2, y2 self.region_points[1] x_min, x_max min(x1, x2), max(x1, x2) y_min, y_max min(y1, y2), max(y1, y2) if x_max - x_min 10 or y_max - y_min 10: return False, 选择的区域太小请重新选择 roi self.original_image[y_min:y_max, x_min:x_max] else: roi self.original_image x_min y_min 0 # 2. 图像处理流水线 gray cv2.cvtColor(roi, cv2.COLOR_BGR2GRAY) blurred cv2.GaussianBlur(gray, (15, 15), 0) _, thresh cv2.threshold(blurred, 0, 255, cv2.THRESH_BINARY_INV cv2.THRESH_OTSU) edges cv2.Canny(thresh, 50, 150) # 3. 轮廓提取 contours, _ cv2.findContours(edges.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) if len(contours) 0: return False, 未检测到轮廓 # 4. 选择面积最大的轮廓 max_contour max(contours, keycv2.contourArea) # 5. ROI模式下的坐标转换 if self.is_region_mode and len(self.region_points) 2: max_contour[:, :, 0] x_min max_contour[:, :, 1] y_min # 6. 保存并绘制轮廓 self.contour max_contour self.processed_image self.draw_contour(self.original_image.copy(), self.contour) # 7. 重置区域选择模式 self.is_region_mode False self.region_points [] return True, 液滴检测成功三、轮廓筛选最大面积法max_contour max(contours, keycv2.contourArea)原理液滴通常是图像中面积最大的物体直接选最大的那个。面积计算公式格林公式Area 0.5 × |Σ(x_i × y_{i1} - x_{i1} × y_i)|其中 (x_i, y_i) 是轮廓上的点最后一个点连接回第一个点。四、ROI坐标校正4.1 为什么要校正ROI模式下检测是在裁剪后的小图上进行的轮廓坐标是相对ROI的需要转换回原图坐标。4.2 校正代码if self.is_region_mode and len(self.region_points) 2: max_contour[:, :, 0] x_min # X坐标偏移 max_contour[:, :, 1] y_min # Y坐标偏移4.3 坐标转换示意原图坐标系: ROI裁剪后坐标系: ┌─────────────────────┐ ┌─────────────┐ │ │ │ (0,0) │ │ ┌───────────┐ │ │ ┌──────┘ │ │ ROI │ │ │ │ 轮廓 │ │ (x_min, │ │ -- │ │ (相对坐标) │ │ y_min) │ │ └──────┘ │ │ ┌────┘ │ │ │ │ 轮廓 │ 转换规则: │ └──────┴──────────┘ 原图坐标 ROI坐标 (x_min, y_min) └─────────────────────┘五、轮廓绘制def draw_contour(self, image, contour): 绘制轮廓并计算文字位置 result image.copy() cv2.drawContours(result, [contour], -1, (0, 0, 255), 2) self.calculate_text_position(contour, image.shape[1], image.shape[0]) return resultdrawContours参数参数值说明image图像副本避免修改原图contours[contour]轮廓列表contourIdx-1绘制所有轮廓color(0, 0, 255)红色BGR格式thickness2线条宽度六、文字位置计算def calculate_text_position(self, contour, image_width, image_height): 计算文字位置放在轮廓正下方居中 x, y, w, h cv2.boundingRect(contour) text_x x w // 2 - 80 text_y y h 20 text_x max(10, min(text_x, image_width - 180)) text_y max(30, min(text_y, image_height - 60)) self.text_position (text_x, text_y)逻辑cv2.boundingRect()获取外接矩形文字放在外接矩形正下方居中边界检查确保文字不超出图像范围七、检测精度提升7.1 形态学操作可选kernel np.ones((3, 3), np.uint8) thresh cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel) # 闭运算填充小洞 thresh cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel) # 开运算去除小噪点7.2 轮廓近似可选epsilon 0.001 * cv2.arcLength(max_contour, True) # 周长 × 系数 approx_contour cv2.approxPolyDP(max_contour, epsilon, True) # 轮廓近似7.3 参数调优建议参数默认值噪声多时边缘弱时高斯核(15, 15)增大减小Canny低阈值50增大减小Canny高阈值150增大减小八、错误处理# 无轮廓 if len(contours) 0: return False, 未检测到轮廓 # ROI区域太小 if x_max - x_min 10 or y_max - y_min 10: return False, 选择的区域太小请重新选择 # UI层处理 success, msg self.image_processor.auto_detect_droplet() if success: self.display_image() self.calculate_and_display_area() self.add_log(msg) else: show_error(self, msg)九、检测模式对比模式优点缺点适用场景全局检测自动无需交互可能误检干扰物单液滴、背景干净ROI检测精确排除干扰需要用户框选多物体、背景复杂自动检测快速方便可能不准液滴清晰手动圈选精确控制操作复杂液滴模糊十、踩坑记录findContours会修改原图必须传入edges.copy()否则原图被破坏ROI坐标转换容易忘加偏移量导致轮廓画错位置空轮廓处理检测不到轮廓时直接返回错误不要继续计算面积文字出界计算文字位置后要做边界检查否则显示不全下篇预告下一篇写面积计算与数据导出像素面积 → 实际面积转换、CSV导出、报告生成。传统的自动识别方法对图源有一定的要求有机会我会用Yolo再做一版大家对Yolo有兴趣评论区留言yolo样本已经在收集了。