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

OpenCV检测黑色圆点时findContours返回轮廓数量异常问题求解

问题原因
  • 输入图像未做格式校验:如果传入cv::threshold的srcImg是三通道彩色图像,阈值计算逻辑会失效,导致二值化结果异常,目标圆点被拆分为多个离散的水平小区域。
  • 缺少形态学预处理:原图存在抗锯齿边缘、JPG压缩伪影时,OTSU二值化后同一个圆点的区域会出现断裂,没有闭运算(先膨胀后腐蚀)操作的话,无法合并这些同属一个圆点的离散区块,每个独立小区域都会被识别为单独轮廓。
  • 轮廓检测参数适配错误:CV_RETR_LIST会检索所有层级的轮廓,若圆点内部存在微小白色噪点,会额外检测出大量内部轮廓;加上断裂后的每个小区域都是短水平线段,CV_CHAIN_APPROX_SIMPLE仅保留线段两端端点,就会出现你看到的所有轮廓仅含2个同Y值点的情况。
修复方案
  1. 先统一转换输入为单通道灰度图,避免多通道图像导致的阈值计算异常:
cv::Mat gray;
if (srcImg.channels() == 3) {
    cv::cvtColor(srcImg, gray, cv::COLOR_BGR2GRAY);
} else {
    gray = srcImg.clone();
}
  1. 二值化后增加形态学闭运算,合并同属一个圆点的断裂区域,消除内部微小噪点:
cv::Mat threshedImg;
// OTSU阈值会自动计算最优阈值,传入的100参数会被忽略,这里直接填0即可
const double th = cv::threshold(gray, threshedImg, 0, 255, cv::THRESH_BINARY_INV | cv::THRESH_OTSU);
// 结构元大小可根据圆点实际尺寸调整,圆点越大可以适当调大结构元
cv::Mat kernel = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(3, 3));
cv::morphologyEx(threshedImg, threshedImg, cv::MORPH_CLOSE, kernel);
  1. 调整轮廓检测参数,只保留最外层轮廓,调试阶段可以先获取完整轮廓点方便排查:
std::vector<std::vector<cv::Point>> contours;
// 使用RETR_EXTERNAL只检测最外层轮廓,过滤内部噪点产生的无效轮廓
// 调试阶段用CHAIN_APPROX_NONE获取完整轮廓点,后续如果需要压缩存储可以改回CHAIN_APPROX_SIMPLE
cv::findContours(threshedImg, contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE);
  1. 增加面积过滤逻辑,进一步剔除不符合圆点尺寸的噪点轮廓:
std::vector<std::vector<cv::Point>> validContours;
// 最小、最大面积阈值根据你的实际圆点尺寸调整即可
const double minDotArea = 8;
const double maxDotArea = 2000;
for (auto& contour : contours) {
    double area = cv::contourArea(contour);
    if (area >= minDotArea && area <= maxDotArea) {
        validContours.push_back(contour);
    }
}

修改完成后validContours中就会是你需要的12个圆点的完整轮廓。

内容的提问来源于stack exchange,提问作者Elmi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 21:54:08