OpenCV findContours无法检测散点图中浅色点的问题求助
散点图浅色点轮廓检测问题及解决方案
我正尝试检测散点图中的点并获取其位置,使用OpenCV的findContours函数时,发现该函数仅能正确检测并绘制深色点的轮廓,浅色点无法被识别。
原代码
import cv2 img = cv2.imread('808.png') imgGray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 寻找轮廓/形状 _, threshold = cv2.threshold(imgGray, 127, 255, cv2.THRESH_BINARY) # 使用findContours函数 contours, _ = cv2.findContours(threshold, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE) i = 0 # 存储形状名称的列表(未实际使用) for contour in contours: if i == 0: i = 1 continue approx = cv2.approxPolyDP( contour, 0.01 * cv2.arcLength(contour, True), True) cv2.drawContours(img, [contour], 0, (0, 0, 0), 5) # 计算形状中心点 M = cv2.moments(contour) if M['m00'] != 0.0: x = int(M['m10']/M['m00']) y = int(M['m01']/M['m00']) cv2.imshow('shapes', img) cv2.waitKey(0) cv2.destroyAllWindows()
输入与输出效果


问题原因
原代码使用cv2.THRESH_BINARY固定阈值(127)处理,会将灰度值高于127的像素转为白色,低于127的转为黑色。浅色点的灰度值接近白色(高于127),阈值处理后会与背景融合,无法形成可被findContours识别的轮廓。
解决方案
1. 反向二值化+自动阈值
使用cv2.THRESH_BINARY_INV反转二值化效果,让浅色点转为黑色前景;搭配cv2.THRESH_OTSU自动计算最优阈值,无需手动设置固定值,适配不同亮度的图像。
2. 优化轮廓检索模式
改用cv2.RETR_EXTERNAL只检测最外层轮廓,避免获取背景等冗余轮廓,简化后续处理逻辑。
修改后的完整代码
import cv2 img = cv2.imread('808.png') imgGray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 反向二值化+Otsu自动阈值 _, threshold = cv2.threshold(imgGray, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU) # 仅检测最外层轮廓 contours, _ = cv2.findContours(threshold, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) for contour in contours: # 过滤过小的噪声轮廓 if cv2.contourArea(contour) < 10: continue # 绘制点的轮廓 cv2.drawContours(img, [contour], 0, (0, 0, 0), 5) # 计算并标记中心点 M = cv2.moments(contour) if M['m00'] != 0.0: x = int(M['m10'] / M['m00']) y = int(M['m01'] / M['m00']) cv2.circle(img, (x, y), 3, (0, 255, 0), -1) cv2.imshow('all_points_detected', img) cv2.waitKey(0) cv2.destroyAllWindows()
额外优化建议
- 轮廓面积过滤:通过
cv2.contourArea过滤面积过小的噪声点,避免误检测。 - 轮廓点压缩:使用
cv2.CHAIN_APPROX_SIMPLE替代cv2.CHAIN_APPROX_NONE,减少轮廓点数量,提升处理效率。
内容的提问来源于stack exchange,提问作者KG_1
相关产品推荐
相关产品推荐

