如何优化白墙黑点的轮廓检测效果?
问题描述
我想要识别这张图片中的黑点:
虽然Canny边缘检测能捕捉到大部分特征:
但使用contours, _ = cv2.findContours(thresholded, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)仅能检测到少量孤立点,有没有办法改进这种情况?
现有代码
import cv2 import numpy as np image1 = cv2.imread(r"C:\Users\54-0461100-01\Desktop\img_process\Daphnia\WIN_20231103_09_47_45_Pro.jpg") gray_image = cv2.cvtColor(image1, cv2.COLOR_BGR2GRAY) _, thresholded = cv2.threshold(gray_image, 100, 255, cv2.THRESH_BINARY) kernel = np.ones((5, 5), np.uint8) thresholded = cv2.dilate(thresholded, kernel, iterations=1) cv2.imshow('thresholded1', thresholded) thresholded = cv2.Canny(thresholded, 100, 200) cv2.imshow('thresholded2', thresholded) cv2.imwrite("thresholded2.jpg", thresholded) contours, _ = cv2.findContours(thresholded, cv2.RETR_LIST , cv2.CHAIN_APPROX_SIMPLE)#cv2.CHAIN_APPROX_SIMPLE object_count = 0 img_with_boxes = image1.copy() for contour in contours: area = cv2.contourArea(contour) if area < 15: # x, y, w, h = cv2.boundingRect(contour) img_with_boxes = cv2.rectangle(img_with_boxes, (x, y), (x + w, y + h), (0, 0, 255), 2) object_count += 1 font = cv2.FONT_HERSHEY_SIMPLEX cv2.putText(img_with_boxes, f'Black Dots: {object_count}', (10, 30), font, 1, (0, 0, 255), 2, cv2.LINE_AA) cv2.imwrite("detected_black_dots.jpg", img_with_boxes) cv2.imshow('Black Dots Detected', img_with_boxes) cv2.waitKey(0) cv2.destroyAllWindows()
改进方案
1. 替换全局阈值为自适应阈值
全局阈值容易受光照不均影响,换成自适应阈值能精准保留黑点细节,同时用THRESH_BINARY_INV将黑点转为白色,方便后续轮廓检测:
# 替换原全局阈值代码 gray_image = cv2.GaussianBlur(gray_image, (3,3), 0) # 先模糊降噪 thresholded = cv2.adaptiveThreshold(gray_image, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 11, 2)
2. 简化检测流程
原流程里的膨胀会让小斑点合并,Canny边缘检测会丢失实心黑点的完整轮廓,直接对阈值后的图像检测最外层轮廓即可:
# 删除原膨胀和Canny代码,直接检测最外层轮廓 contours, _ = cv2.findContours(thresholded, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
3. 优化轮廓筛选条件
除了面积,增加外接圆半径判断,过滤非圆形的干扰点(黑点通常近似圆形):
for contour in contours: area = cv2.contourArea(contour) # 根据实际黑点大小调整面积和半径范围 if 5 < area < 50: (x,y), radius = cv2.minEnclosingCircle(contour) if radius > 1.5 and radius < 5: x, y, w, h = cv2.boundingRect(contour) cv2.rectangle(img_with_boxes, (x, y), (x + w, y + h), (0, 0, 255), 2) object_count += 1
完整改进代码
import cv2 import numpy as np image1 = cv2.imread(r"C:\Users\54-0461100-01\Desktop\img_process\Daphnia\WIN_20231103_09_47_45_Pro.jpg") gray_image = cv2.cvtColor(image1, cv2.COLOR_BGR2GRAY) # 高斯模糊降噪 + 自适应阈值 gray_image = cv2.GaussianBlur(gray_image, (3,3), 0) thresholded = cv2.adaptiveThreshold(gray_image, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 11, 2) cv2.imshow('thresholded', thresholded) # 检测最外层轮廓 contours, _ = cv2.findContours(thresholded, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) object_count = 0 img_with_boxes = image1.copy() for contour in contours: area = cv2.contourArea(contour) # 筛选面积和近似圆形的轮廓 if 5 < area < 50: (x,y), radius = cv2.minEnclosingCircle(contour) if radius > 1.5 and radius < 5: x, y, w, h = cv2.boundingRect(contour) cv2.rectangle(img_with_boxes, (x, y), (x + w, y + h), (0, 0, 255), 2) object_count += 1 font = cv2.FONT_HERSHEY_SIMPLEX cv2.putText(img_with_boxes, f'Black Dots: {object_count}', (10, 30), font, 1, (0, 0, 255), 2, cv2.LINE_AA) cv2.imwrite("detected_black_dots.jpg", img_with_boxes) cv2.imshow('Black Dots Detected', img_with_boxes) cv2.waitKey(0) cv2.destroyAllWindows()
内容的提问来源于stack exchange,提问作者RobertLink
相关产品推荐
相关产品推荐

