Ask Your Question
4

Detach two blob

asked 2015-02-24 08:14:05 -0600

Tonio123 gravatar image

updated 2015-02-25 05:11:20 -0600

Hi, For a project I need to differentiate two blob wich have a contatc point.

After binarization I have this image:

image description

How can I proceed in order to separate the two blob and proceed with the analysis? Is there a morphological operator that can help me with this task or I must necessarily use some sort of object recognition?

EDIT: As requested this is the original image

image description

I have tried with erosion or opening but unfortunatly the result aren't good:

image description

maybe have I used the wrong kernel?

edit retag flag offensive close merge delete

Comments

Do you always need to separate two instances of the same object?

FooBar gravatar imageFooBar ( 2015-02-24 13:06:50 -0600 )edit

Not always, in the same image there could be even objects with two holes... Anyway separate instance of the same object could be a starting point

Tonio123 gravatar imageTonio123 ( 2015-02-24 14:08:02 -0600 )edit

just apply some morphology operation like erosion or opening, most likely will fit you in these kind of cases

theodore gravatar imagetheodore ( 2015-02-24 14:39:12 -0600 )edit

I've edited the question with the result of an erosion! As for opening I've thinked of using it with a rectangular kernel with the same orientation of the rods in order to delete the holes and keep only the "body", but I'm stuck because if I can't divide the two blobs how can I compute their orientation?

Tonio123 gravatar imageTonio123 ( 2015-02-25 03:25:36 -0600 )edit

can you add the original image as well, it might help

theodore gravatar imagetheodore ( 2015-02-25 04:36:44 -0600 )edit

Added also the original image! Thank you for the help by the way. Maybe a lower threshold value during the binarization could help to better differentiate the two blob?

Tonio123 gravatar imageTonio123 ( 2015-02-25 05:12:03 -0600 )edit

do you want to achieve a solution specific for this image, or a more generic solution that would work for other more advanced cases as well. Because if the latter is the case then for sure morphological approaches will fail at some point.

theodore gravatar imagetheodore ( 2015-02-25 06:57:15 -0600 )edit

Certainly a more generic solution will be preferable, but a simple morphological approach could also be a good starting point! The image that I have to process are all similar to this one, what change is the number of touching objects...

Tonio123 gravatar imageTonio123 ( 2015-02-25 08:35:17 -0600 )edit

1 answer

Sort by ยป oldest newest most voted
4

answered 2015-02-25 15:08:13 -0600

theodore gravatar image

A basic idea based on morphological operations and distance transformation can be seen in the example below. For sure you will need to test it further in order to see how much it fits to all of your use cases. My basic assumption is that in order to extract an object you need to use a feature that is quite significant in each object. The feature that I used is the trunk of each object which I find it to be the strongest. Moreover, you can use it for getting the orientation of each object as well. So, at the end you do not need to detect the full object in order to obtain the information that you want, but only part of it.

#include <iostream>
#include <opencv2/opencv.hpp>

using namespace std;
using namespace cv;

int main()
{
    // Load your image
    cv::Mat src = cv::imread("blobs.png");

    // Check if everything was fine
    if (!src.data)
        return -1;

    // Show source image
    cv::imshow("src", src);

image description

    // Create binary image from source image
    cv::Mat gray;
    cv::cvtColor(src, gray, CV_BGR2GRAY);
//    cv::imshow("gray", gray);

    // Obtain binary image
    Mat bw;
    cv::threshold(gray, bw, 40, 255, CV_THRESH_BINARY_INV | CV_THRESH_OTSU);
    cv::imshow("bin", bw);

image description

    // Erode a bit
    Mat kernel = Mat::ones(3, 3, CV_8UC1);
    erode(bw, bw, kernel);
//    imshow("erode", bw);

    // Perform the distance transform algorithm
    Mat dist;
    distanceTransform(bw, dist, CV_DIST_L2, 5);

    // Normalize the distance image for range = {0.0, 1.0}
    // so we can visualize and threshold it
    normalize(dist, dist, 0, 1., NORM_MINMAX);
    imshow("distTransf", dist);

image description

    // Threshold to obtain the peaks
    // This will be the markers for the foreground objects
    threshold(dist, dist, .5, 1., CV_THRESH_BINARY);

    // Dilate a bit the dist image, this can be optional since in
    // other use case might cause problems. Here though it works quite well
    Mat kernel1 = Mat::ones(5, 5, CV_8UC1);
    dilate(dist, dist, kernel1, Point(-1, -1), 2);
    imshow("peaks", dist);

image description

    // Create the CV_8U version of the distance image
    // It is needed for findContours()
    Mat dist_8u;
    dist.convertTo(dist_8u, CV_8U);

    // Find total markers
    vector<Vec4i> hierarchy;
    vector<vector<Point> > contours;
    findContours(dist_8u, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE);

    // Find the rotated rectangles
    vector<RotatedRect> minRect( contours.size() );

    for( size_t i = 0; i < contours.size(); i++ )
    {
        minRect[i] = minAreaRect( Mat(contours[i]) );
    }

    RNG rng(12345);
    for( size_t i = 0; i< contours.size(); i++ )
    {
        Scalar color = Scalar( rng.uniform(0, 255), rng.uniform(0,255), rng.uniform(0,255) );
        // contour
        drawContours( src, contours, static_cast<int>(i), color, 1, 8, vector<Vec4i>(), 0, Point() );
        // rotated rectangle
        Point2f rect_points[4]; minRect[i].points( rect_points );
        for( int j = 0; j < 4; j++ )
            line( src, rect_points[j], rect_points[(j+1)%4], color, 1, 8 );
    }

/* From here you can extract the orientation of each object by using
 * the information that you can extract from the contours and the
 * rotate rectangles. For example, the center point, rectange angle, etc...
 */

    cv::imshow("result", src);

image description

    waitKey(0);
    return 0;
}

I do not know how close is this to what you want but I hope that it ... (more)

edit flag offensive delete link more

Comments

1

thank you! From this point I can obtain all the information I needed

Tonio123 gravatar imageTonio123 ( 2015-02-26 03:03:51 -0600 )edit

Question Tools

2 followers

Stats

Asked: 2015-02-24 08:14:05 -0600

Seen: 2,678 times

Last updated: Feb 25 '15