Ask Your Question
1

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

asked 2020-06-12 23:14:50 -0600

sn4k3 gravatar image

updated 2020-10-21 10:48:22 -0600

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);
                }
edit retag flag offensive reopen merge delete

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

sturkmen gravatar imagesturkmen ( 2020-06-13 14:41:03 -0600 )edit

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 ( 2020-06-13 23:28:00 -0600 )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 ( 2020-06-14 10:38:45 -0600 )edit

2 answers

Sort by ยป oldest newest most voted
1

answered 2020-06-14 11:16:38 -0600

sn4k3 gravatar image

updated 2020-06-14 11:21:10 -0600

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 ^^

edit flag offensive delete link more
-1

answered 2020-06-13 05:09:06 -0600

updated 2020-06-13 05:11:13 -0600

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

edit flag offensive delete link more

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 ( 2020-06-13 08:25:14 -0600 )edit

Question Tools

1 follower

Stats

Asked: 2020-06-12 23:14:50 -0600

Seen: 3,174 times

Last updated: Jun 14 '20