You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何优化白墙黑点的轮廓检测效果?

问题描述

我想要识别这张图片中的黑点:
原始图片

虽然Canny边缘检测能捕捉到大部分特征:
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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 10:27:03