Ask Your Question
0

Detecting objects with a certain surface area

asked 2015-08-26 04:55:27 -0600

Vizier87 gravatar image

updated 2015-08-26 04:57:08 -0600

Hi guys,

I'd like to detect small but undefined shapes with a certain value of surface area, say 25 pixels worth. Now, I tried coding by calculating an array of pixels with adjacency but it seems pretty tedious and demanding for the debugging.

Let's say I want to detect an image with at least 3 x 1 green pixels (where I have performed threshold the image to a binary black & green form):

  for (int i = 0; i < Image.rows; i++){

        if (Image.at<cv::Vec3b>(i , 200)[1] == 255){                

           if (Image.at<cv::Vec3b>(i+1 , 200)[1] == 255){

                if (Image.at<cv::Vec3b>(i+2 , 200)[1] == 255){              
                   putText(Image, "Detected", Point(20, 20), FONT_HERSHEY_PLAIN, 1, Scalar::all(255), 2, 8);
                }

           }

        }
    }

Now, this seemed to work but occasionally it'll crash due to the memory.

I suppose there are workarounds to this? How do I do this?

Thanks bros.

edit retag flag offensive close merge delete

1 answer

Sort by ยป oldest newest most voted
3

answered 2015-08-26 12:01:01 -0600

Guyygarty gravatar image

You can use "findContours" to find all blobs (binary large objects). BinaryImage needs to be an 8-bit single-channel image. It is helpful if you blur the image a bit before binarizing so that you don't get many 1 pixel objects.

vector<vector<Point>> contours;
vector<Vec4i> hierarchy;

findContours(BinaryImage, contours, hierarchy, CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE); //find all blobs
for (int i = 0; i < contours.size(); i++)
{
    vector<Point> contour_poly;
    approxPolyDP( Mat(contours[i]), contour_poly, 3, true );
    double Area=contourArea(contour_poly); //find area of each blob
    if (Area>25)
       //do whatever
}

guy

edit flag offensive delete link more

Comments

Thanks Guy. I'll try this out and if will get back here to update.

Vizier87 gravatar imageVizier87 ( 2015-08-26 22:51:54 -0600 )edit

Hi bro, it seems that there's a problem. I only added these lines:

vector<vector<Point>> contours;
vector<Vec4i> hierarchy;
findContours(Black_Green, contours, hierarchy, CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE);

......and it returns:

cv::Exception at memory location 0x00000000002DEAC0

Where did I go wrong?

Vizier87 gravatar imageVizier87 ( 2015-08-27 03:02:35 -0600 )edit

Make sure that Black_Green is a Mat of type CV_8C1? if it is CV_8C3, the program will crash.

also, just to be sure that there are no ambiguities, you can change vector to std::vector, Point to cv::Point and Vec4i to cv::Vec4i guy

Guyygarty gravatar imageGuyygarty ( 2015-08-27 10:57:36 -0600 )edit

Yeah Guy, you're right it was CV_8C3. You really know your stuff man! :)

However, when I changed it to CV_8C1 the Black_Green didn't appear. I tried reading up some docs on these types but I don't really understand. Where can I get good references on this?

Vizier87 gravatar imageVizier87 ( 2015-09-01 23:30:15 -0600 )edit

You really know your stuff man I use findContours a lot and have had more than my fair share of exceptions...

what do you mean by "didn't appear"? can you show how you are generating that Mat? guy

Guyygarty gravatar imageGuyygarty ( 2015-09-02 13:58:29 -0600 )edit

Here's how I did it:

Mat Black_Green(current_frame.size(), CV_8UC1, Scalar(0, 255, 0));

I took the current_frame from running webcam.

It worked for CV_8UC3 though.

Vizier87 gravatar imageVizier87 ( 2015-09-02 23:39:25 -0600 )edit

That would generate a black image - since the Mat is one channel, only the first element of the Scalar is used.

Mat Black_Green(current_frame.size(), CV_8UC1, Scalar(255)); would initialize a white image.

In any case I don't see how you get a binary image with objects this way.

guy

Guyygarty gravatar imageGuyygarty ( 2015-09-04 14:47:56 -0600 )edit

Perhaps I needed to post the whole thing:

capture >> current_frame;
        if (current_frame.empty()) break;
        cvtColor(current_frame, Gray_frame, CV_RGB2GRAY);
        threshold(Gray_frame, Black_White, threshold_value, max_value, threshold_type);
        Mat Black_Green(current_frame.size(), CV_8UC3, Scalar(0, 255, 0));
        Black_Green.setTo(Scalar::all(0), Black_White);

With this in a loop I managed a binary green and black. Well it's a noob code so I'd really appreciate it if you can point out any bad coding on my part.

Whaddaya think? Thanks bro.

Vizier87 gravatar imageVizier87 ( 2015-09-06 21:27:51 -0600 )edit
1

In this code, you would need to apply findContours to Black_White, not to Black_Green, which is a three channel image.
To generate the green image, I would use:

Mat Black_Green(current_frame.size(), CV_8UC3, Scalar(0, 0, 0));
Black_Green.setTo(Scalar(0,255,0), Black_White);
Guyygarty gravatar imageGuyygarty ( 2015-09-09 13:41:13 -0600 )edit

Aaahh I see now you've hit the nail. I missed the part where it needed to be a Black and White only. It works now. Thanks.

Vizier87 gravatar imageVizier87 ( 2015-09-09 22:49:07 -0600 )edit

Question Tools

1 follower

Stats

Asked: 2015-08-26 04:55:27 -0600

Seen: 1,293 times

Last updated: Aug 26 '15