如何使用 OpenCV 检测白色斑点

2023-12-03

I paint a picture to test: enter image description here

我想知道黑色圆圈中有多少斑点以及每个斑点的大小是多少(所有斑点都是白色的)。

For example, in this case I have 12 spots: enter image description here

我知道如何找到白色像素,并且很容易从左侧验证序列:

int whitePixels = 0;
for (int i = 0; i < height; ++i)
{
    uchar * pixel = image.ptr<uchar>(i);
    for (int j = 0; j < width; ++j)
    {
        if (j>0 && pixel[j-1]==0)   // to group pixels for one spot
            whitePixels++;
    }
}

但很明显,这段代码还不够好(斑点可以是对角线的,等等)。

所以,最重要的是,我需要帮助:如何定义斑点?

谢谢


以下代码查找所有白点的边界矩形(斑点)。

Remark:如果我们可以假设白点确实是白色的(即灰度图像中的值为 255),则可以使用此代码片段。考虑将其放入某个类中,以避免将不必要的参数传递给函数 Traverse。虽然它有效。这个想法是基于DFS的。除了灰度图像之外,我们还有 ids 矩阵来分配并记住哪个像素属于哪个 blob(具有相同 id 的所有像素都属于同一个 blob)。

void Traverse(int xs, int ys, cv::Mat &ids,cv::Mat &image, int blobID, cv::Point &leftTop, cv::Point &rightBottom) {
    std::stack<cv::Point> S;
    S.push(cv::Point(xs,ys));

    while (!S.empty()) {
        cv::Point u = S.top();
        S.pop();

        int x = u.x;
        int y = u.y;

        if (image.at<unsigned char>(y,x) == 0 || ids.at<unsigned char>(y,x) > 0)
            continue;

        ids.at<unsigned char>(y,x) = blobID;
        if (x < leftTop.x)
            leftTop.x = x;
        if (x > rightBottom.x)
            rightBottom.x = x;
        if (y < leftTop.y)
            leftTop.y = y;
        if (y > rightBottom.y)
            rightBottom.y = y;

        if (x > 0)
            S.push(cv::Point(x-1,y));
        if (x < ids.cols-1)
            S.push(cv::Point(x+1,y));
        if (y > 0)
            S.push(cv::Point(x,y-1));
        if (y < ids.rows-1)
            S.push(cv::Point(x,y+1));
    }


}

int FindBlobs(cv::Mat &image, std::vector<cv::Rect> &out, float minArea) {
    cv::Mat ids = cv::Mat::zeros(image.rows, image.cols,CV_8UC1);
    cv::Mat thresholded;
    cv::cvtColor(image, thresholded, CV_RGB2GRAY);
    const int thresholdLevel = 130;
    cv::threshold(thresholded, thresholded, thresholdLevel, 255, CV_THRESH_BINARY);
    int blobId = 1;
    for (int x = 0;x<ids.cols;x++)
        for (int y=0;y<ids.rows;y++){
            if (thresholded.at<unsigned char>(y,x) > 0 && ids.at<unsigned char>(y,x) == 0) {
                cv::Point leftTop(ids.cols-1, ids.rows-1), rightBottom(0,0);
                Traverse(x,y,ids, thresholded,blobId++, leftTop, rightBottom);
                cv::Rect r(leftTop, rightBottom);
                if (r.area() > minArea)
                    out.push_back(r);
            }
        }
    return blobId;
}

EDIT:我修复了一个错误,降低了阈值级别,现在输出如下。我认为这是一个很好的起点。

Output

EDIT2:我摆脱了递归Traverse()。在更大的图像中,递归导致了 Stackoverflow。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何使用 OpenCV 检测白色斑点 的相关文章

随机推荐

  • 使用 Kryo 序列化任意 Java 对象(出现 IllegalAccessError)

    动机 为了帮助远程调试 Java 能够请求远程服务器将任意对象发送到我的本地计算机进行检查非常有用 然而 这意味着远程服务器必须能够序列化运行时事先未知的任意java对象 于是我四处打听 偶然发现Kryo序列化库 From Kryo 的文档
  • 在固定 div 内旋转文本

    我正在尝试在页面左侧设置一个固定 div 距离左侧 24px 并从页面顶部延伸到底部 该 div 内将包含导航和标题 我试图将标题旋转 90 度并居中定位到 div 的底部 很难弄清楚这一点 查了很多地方都没有看到类似的例子 我已经用当前的
  • 将 HTML 字符串转换为 DOM 元素?

    有没有办法将 HTML 转换为 div a href a span span div 或者任何其他 HTML 字符串到 DOM 元素中 这样我就可以使用appendChild 我知道我可以执行 innerHTML 和 innerText 但
  • write_csv read_csv 在第 1000 行后使用科学记数法

    使用 write csv 将混合有小整数条目 值小于 1000 和 大 整数条目 值 1000 或以上 的数据框写入 csv 文件 会混合科学和非科学条目 如果前 1000 行是小值 但此后有一个大值 则 read csv 似乎会与这种混合
  • Cassandra-Windows 10

    我已经安装了 apache cassandra 3 11 11 和 DATASTAX DDC 但它们无法在 Windows 10 上运行 它在 cmd 中给出错误 如图所示 我尝试在 powershell 上编写 cassandra bat
  • ASP.NET MVC3如何使用间隔一小时的计时器执行控制器的操作方法

    Hello 我正在使用 asp net mvc3 我有一个特殊的控制器 它有一种特殊的操作方法 我需要使用计时器以一小时为间隔执行此操作方法 任何最好 最有效的想法 thanks 我能够使用 VBScript 和 Windows Sched
  • 如何从 hapi.js 路由处理程序外部进行回复

    我有一个hapi js我想推迟响应的路线 我尝试过存储reply函数并稍后调用它 或者将其包装在 Promise 中 但 hapi 总是立即响应 500 内部服务器错误响应 存储回复以供稍后使用 var pendingReplies ser
  • 使用 == 运算符将 char 与 0x80 进行比较总是结果为 false?

    char byte 0x80 if byte 0x80 cout lt lt This message never gets printed 十六进制值0x80二进制等价于1000 0000 这显然适合一个字节 但是 编译器会警告我有关条件
  • 控制插入符号 R 包中交叉验证的采样

    我有以下问题 在来自 N 个受试者的数据集中 每个受试者有几个样本 我想在数据集上训练模型 但我想确保在每次重采样中 训练集中没有受试者的重复 或者 我会阻止按主题进行交叉验证 那可能吗 如果没有插入符号包 我会做类似的事情 模拟代码 su
  • boost asio Streambuf 调用消耗后不释放内存?

    boost asio streambuf b void handler const boost system error code e std size t size if e std stringstream sstr std strin
  • 如何在不使用服务的情况下在子组件和父组件之间传递反应式表单数据

    当我们单击父级按钮时 我们希望使用来自父级的子级反应式表单数据 目前我们正在使用 viewchild 来获取子组件引用 我们正在获取所有静态数据 但没有获取表单填充的数据 parent component ts ViewChild Deta
  • Git 跟踪、未跟踪、暂存、索引的含义?

    有人可以澄清这些术语的含义吗 跟踪的文件是否是在某个时刻添加到舞台中的任何文件 索引 和 阶段 一样吗 是否跟踪所有暂存文件 但反之则不一定成立 即 曾经暂存并提交的文件 但不是要提交的当前阶段的一部分 我如何知道哪些文件被跟踪 我如何知道
  • 使用 volley 以 json 格式将数据发送到服务器

    您好 我正在以 json 格式将数据发布到服务器 但它在错误响应中返回齐射服务器错误 RequestQueue queue Volley newRequestQueue this JSONObject jobj new JSONObject
  • 自定义html标签——有更好的方法吗?

    我正在尝试完成一个浏览器插件 它将分析文本并以某种方式标记它 基本上 假设您在浏览时发现页面中的某处出现了此文本 p and then Tom Cruise devoured the planet p 该插件正在扫描文本并会找到 Tom C
  • JS:将数组减少为嵌套对象

    所以我有这个数组 var mapped 2016 October Monday object 2017 January Friday object 2017 January Wednesday object 2017 October Mon
  • 勾画出图中的区域

    我有两个 2D numpy 数组 尺寸相同 我正在使用 matplotlib 绘制它们 我将第一个数组绘制为灰度彩色图 第二个代表光圈 但它是不规则形状 一些像素被勾勒出轮廓 它是形成轮廓的一组水平和垂直线 我不知道如何要求它绘制第二个数组
  • 多边形三角剖分的相反是什么?

    完成 2D 三角测量后 一些三角形具有相同的颜色 我想重新组合它们以绘制类似颜色的图形路径 我发现 如果我只是一一绘制三角形 一些图形渲染器会显示三角形之间的接缝 至少在涉及抗锯齿和 或透明度的情况下 那么 如何获取一组 不重叠 三角形并生
  • 使用 ctop.xsl 的内容 mathml 到中缀表示法未获得所需格式

    我正在尝试从内容 mathml 中制作数学符号或中缀表达式 我正在提供帮助ctop xsl为了这 ctop xsl Refer 可以解析得到表达式如下
  • 互斥锁所有权队列顺序

    假设我有三个线程 它们都通过互斥体访问相同的互斥部分 让我给你举这个例子 第一个线程探测互斥体并首先获取其所有权 THREAD 1 TIME 2013 03 13 01 00 00 000Z WaitForSingleObject hMut
  • 如何使用 OpenCV 检测白色斑点

    I paint a picture to test 我想知道黑色圆圈中有多少斑点以及每个斑点的大小是多少 所有斑点都是白色的 For example in this case I have 12 spots 我知道如何找到白色像素 并且很容