如何计算二值图中多分离轮廓白色区域的整体质心?
获取二值图像白色区域整体质心的正确方法
你的思路方向是对的,但拼接轮廓点来计算质心的方式其实有个关键问题——你只用到了轮廓的边缘像素,忽略了白色区域内部的所有像素,这样算出来的是边缘点的质心,不是整个白色区域的质心,结果会和真实区域质心有偏差,尤其是当白色区域内部面积较大时,偏差会更明显。
下面给你两种更可靠的解决方案:
方法一:直接对二值图像计算矩(推荐,最简单高效)
OpenCV的cv2.moments()函数可以直接接收单通道图像作为输入,此时它会计算所有非零像素(也就是你的白色区域)的矩,直接得到整个白色区域的质心,完全符合你的需求:
# 直接对二值图像计算矩 mmt = cv2.moments(binary_image) # 计算质心坐标,注意先判断m00不为0(避免除以0错误) if mmt['m00'] != 0: self.cx = int(mmt['m10'] / mmt['m00']) self.cy = int(mmt['m01'] / mmt['m00']) else: # 处理图像中没有白色区域的特殊情况 self.cx, self.cy = 0, 0
方法二:通过填充轮廓生成掩码后计算矩
如果你一定要基于轮廓操作,可以先创建一个空白掩码,把所有检测到的轮廓填充为白色,再对这个掩码计算矩,结果和方法一完全一致:
_, contours, _ = cv2.findContours(binary_image, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # 创建和原图尺寸一致的空白掩码 mask = np.zeros_like(binary_image) # 填充所有轮廓(参数-1表示填充所有轮廓,cv2.FILLED表示填充内部) cv2.drawContours(mask, contours, -1, 255, thickness=cv2.FILLED) # 对填充后的掩码计算矩 mmt = cv2.moments(mask) if mmt['m00'] != 0: self.cx = int(mmt['m10'] / mmt['m00']) self.cy = int(mmt['m01'] / mmt['m00']) else: self.cx, self.cy = 0, 0
总结一下,方法一不需要处理轮廓,一步到位就能得到准确的整体质心,是最优选择;你的原方法因为只考虑了边缘点,所以无法反映整个白色区域的质量分布,建议替换成上面的方案。
内容的提问来源于stack exchange,提问作者YYK
相关产品推荐
相关产品推荐

