如何合并blob /轮廓 [英] How can I merge blobs / contours

查看:744
本文介绍了如何合并blob /轮廓的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用 findContours 进行blob检测。现在我将密切和类似的blob合并在一起。



以下是一些示例图片:





普通Opencv可以实现吗?

解决方案

您提供给我们的输入图片非常容易使用:





第一步是将黄色斑点与其他一切隔离,简单的颜色分割技术可以完成此任务。您可以查看,将所有blob放入矩形。请注意,在下图中,blob周围有一个绿色矩形:





之后,您需要做的就是填写具有您选择颜色的矩形,从而连接所有blob。我将这最后留作你的作业。



这是我能想到的最快捷,最简单的方法。以下代码演示了如何实现我刚才描述的内容:

  #include< cv.h> 
#include< highgui.h>

#include< iostream>
#include< vector>

int main(int argc,char * argv [])
{
cv :: Mat img = cv :: imread(argv [1]);
if(!img.data)
{
std :: cout!!!无法打开文件:<< argv [1]<<的std :: ENDL;
返回0;
}

//将RGB Mat转换为HSV色彩空间
cv :: Mat hsv;
cv :: cvtColor(img,hsv,CV_BGR2HSV);

//将HSV Mat拆分为HSV组件
std :: vector< cv :: Mat> v;
cv :: split(hsv,v);

//删除低饱和度的像素
int min_sat = 70;
cv :: threshold(v [1],v [1],min_sat,255,cv :: THRESH_BINARY);

/ *从现在开始使用饱和图像* /

// Erode可以提供一些增强功能,但我不确定。
// cv :: Mat element = cv :: getStructuringElement(cv :: MORPH_RECT,cv :: Size(3,3));
// cv :: erode(v [1],v [1],element);

//在组装边界框之前在图像中存储点集
std :: vector< cv :: Point>点;
cv :: Mat_< uchar> :: iterator it = v [1] .begin< uchar>();
cv :: Mat_< uchar> :: iterator end = v [1] .end< uchar>();
for(; it!= end; ++ it)
{
if(* it)points.push_back(it.pos());
}

//计算最小边界框
cv :: RotatedRect box = cv :: minAreaRect(cv :: Mat(points));

//在原始图像上显示边界框
cv :: Point2f vertices [4];
box.points(顶点);
for(int i = 0; i< 4; ++ i)
{
cv :: line(img,vertices [i],vertices [(i + 1)%4 ],cv :: Scalar(0,255,0),1,CV_AA);
}

cv :: imshow(box,img);
// cv :: imwrite(argv [2],img);

cvWaitKey(0);

返回0;
}


I use findContours for blob detection. Now I would merge close and similar blobs together.

Here are some sample images:

Is that possible with normal Opencv?

解决方案

The input images you gave us are pretty easy to work with:

The first step is isolate the yellow blobs from everything else and a simple color segmentation technique can accomplish this task. You can take a look at Segmentation & Object Detection by color or Tracking colored objects in OpenCV to have an idea on how to do it.

Then, it's time to merge the blobs. One technique in particular that can be useful is the bounding box, to put all the blobs inside a rectangle. Notice in the images below, that there is a green rectangle surrounding the blobs:

After that, all you need to do is fill the rectangle with the color of your choice, thus connecting all the blobs. I'm leaving this last as homework for you.

This is the quickest and most simple approach I could think of. The following code demonstrates how to achieve what I just described:

#include <cv.h>
#include <highgui.h>

#include <iostream>
#include <vector>

int main(int argc, char* argv[])
{
    cv::Mat img = cv::imread(argv[1]);
    if (!img.data)
    {
        std::cout "!!! Failed to open file: " << argv[1] << std::endl;
        return 0;
    }

    // Convert RGB Mat into HSV color space
    cv::Mat hsv;
    cv::cvtColor(img, hsv, CV_BGR2HSV);

    // Split HSV Mat into HSV components
    std::vector<cv::Mat> v;
    cv::split(hsv,v);

    // Erase pixels with low saturation
    int min_sat = 70;
    cv::threshold(v[1], v[1], min_sat, 255, cv::THRESH_BINARY);

    /* Work with the saturated image from now on */

// Erode could provide some enhancement, but I'm not sure.
//  cv::Mat element = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(3, 3));
//  cv::erode(v[1], v[1], element);

    // Store the set of points in the image before assembling the bounding box
    std::vector<cv::Point> points;
    cv::Mat_<uchar>::iterator it = v[1].begin<uchar>();
    cv::Mat_<uchar>::iterator end = v[1].end<uchar>();
    for (; it != end; ++it)
    {
        if (*it) points.push_back(it.pos());
    }

    // Compute minimal bounding box
    cv::RotatedRect box = cv::minAreaRect(cv::Mat(points));

    // Display bounding box on the original image
    cv::Point2f vertices[4];
    box.points(vertices);
    for (int i = 0; i < 4; ++i)
    {
            cv::line(img, vertices[i], vertices[(i + 1) % 4], cv::Scalar(0, 255, 0), 1, CV_AA);
    }

    cv::imshow("box", img);
    //cv::imwrite(argv[2], img);

    cvWaitKey(0);

    return 0;
}

这篇关于如何合并blob /轮廓的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆