Ask Your Question
1

Detect all black pixels inside a surrounded closed white area [closed]

asked Jun 13 '0

sn4k3 gravatar image

updated Oct 21 '0

How can i detect black pixels surrounded by closed white pixels? Background outside shapes should not be considered.

See next two images: First image i would like to extract all black pixels inside the hallow shape because it's traped/surrounded by white, but image 2 have a opeing and in that case i don't need the pixels. Image 3 shows the desired capture area in red

close open

Image 3: Desired capture area from image1 in red. Same pass on image 2 should return 0 pixels (No area detected) capture area

Another example:

Input: ex2_input

Needed area in red: ex2_output

EDIT 1:

                Image<Gray, byte> grayscale = ActualLayerImage.ToEmguImage();
                VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint();
                Mat external = new Mat();

                CvInvoke.FindContours(grayscale, contours, external, RetrType.Ccomp, ChainApproxMethod.ChainApproxSimple);

                var arr = external.GetData();
                for (int i = 0; i < contours.Size; i++)
                {
                    if((int)arr.GetValue(0, i, 2) != -1) continue;
                    var r = CvInvoke.BoundingRectangle(contours[i]);
                    CvInvoke.Rectangle(grayscale, r, new MCvScalar(125), 10);
                }

Code on different inputs:

Image 4: OK ex3

Image 5: OK ex4

Image 6: Not OK! ex4

How to discard image6 cases?

EDIT 2: The solution:

                 Image<Gray, byte> grayscale = ActualLayerImage.ToEmguImage();

                VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint();
                Mat external = new Mat();

                CvInvoke.FindContours(grayscale, contours, external, RetrType.Ccomp, ChainApproxMethod.ChainApproxSimple);

                var arr = external.GetData();

                /*
                 * hierarchy[i][0]: the index of the next contour of the same level
                 * hierarchy[i][1]: the index of the previous contour of the same level
                 * hierarchy[i][2]: the index of the first child
                 * hierarchy[i][3]: the index of the parent
                 */
                for (int i = 0; i < contours.Size; i++)
                {
                    if ((int)arr.GetValue(0, i, 2) != -1 || (int)arr.GetValue(0, i, 3) == -1) continue;
                    var r = CvInvoke.BoundingRectangle(contours[i]);
                    CvInvoke.Rectangle(grayscale, r, new MCvScalar(125), 5);
                }
Preview: (hide)

Closed for the following reason the question is answered, right answer was accepted by sturkmen
close date 2020-06-14 12:02:37.115635

Comments

That almost solved the problem, but when shape is all solid it get returned. I have edited my post to show the problem.

sn4k3 gravatar imagesn4k3 (Jun 14 '0)edit

see https://docs.opencv.org/master/d9/d8b... i think you can find the answer yourself (if the contour has no child )

sturkmen gravatar imagesturkmen (Jun 14 '0)edit

2 answers

Sort by » oldest newest most voted
1

answered Jun 14 '0

sn4k3 gravatar image

updated Jun 14 '0

Thank you! if ((int)arr.GetValue(0, i, 2) != -1 || (int)arr.GetValue(0, i, 3) == -1) continue; // Solved my problem :)

"contour must be a child of a existing parent" stange fact -> child of no parent can exist ^^

Preview: (hide)
-1

answered Jun 13 '0

updated Jun 13 '0

do you want to find red areas like in this result image ?

morphological operators: Erosion and Dilation will help on this kind of shapes

image description

#include <iostream>
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"

using namespace cv;
using namespace std;

int main(int argc, const char* argv[])
{

    Mat src,gray,thresh,diff;

    src = imread("15920212749451237.png");
    cvtColor(src, gray, COLOR_BGR2GRAY);

    gray = gray > 127;
    thresh = gray > 127;

    dilate(thresh, thresh, Mat(), Point(-1, -1), 20);
    erode(thresh, thresh, Mat(), Point(-1, -1), 20);

    absdiff(gray, thresh, diff);

    src.setTo(Scalar(0, 0, 255), diff);

    imshow("src", src);
    imshow("diff", diff);
    waitKey();
    return 0;
}

image description

Preview: (hide)

Comments

No, i've add the desired capture area on main post. Also the shape is an example, but they can by any shape and odd forms. EDIT: Added one more example

sn4k3 gravatar imagesn4k3 (Jun 13 '0)edit

Question Tools

1 follower

Stats

Asked: Jun 13 '0

Seen: 3,309 times

Last updated: Jun 14 '20