Best way to gather all pixels location (XY) inside a closed contour?

asked 2020-06-16 23:01:53 -0500

sn4k3 gravatar image

updated 2020-06-16 23:12:44 -0500

Currently i have a black&white 3D model sliced in 2D images (+/- 500 to 1000 images), each layer is 0.05mm in Z, that aside i need to capture all closed black areas contours which i already have. I need to detect all empty spaces on the model looping all images and go up and down in Z at each countour area to find if is hollow space in a 3D prespective or if have any gap to outside the model and will not consider that area hollow.

Currently i'm doing the following:

  1. for first layer to last layer:
  2. Detect the required contours
  3. Foreach contour
  4. Create a empty image at same size of input
  5. FillConvexPoly at empty image
  6. Loop image pixels and find that previous draw pixels and save them in a array

That's the first part of the problem, what i'm doing is very inefficient/slow,... As can be observed each contour in layer image must loop all pixels in image, so if i have 5 countours on a image, it loop image 5 times to get pixels as a countour area.

Current code:

for (int i = 0; i < contours.Size; i++)
    if ((int)arr.GetValue(0, i, 2) != -1 || (int)arr.GetValue(0, i, 3) == -1) continue;

    grayscale = new Image<Gray, byte>(image.Width, image.Height);
    //grayscale = grayscale.CopyBlank();
    grayscale.FillConvexPoly(contours[i].ToArray(), new Gray(125));
    List<Point> points = new List<Point>();

    byte[,,] data = grayscale.Data;
    for (int y = 0; y < grayscale.Rows; y++)
        for (int x = 0; x < grayscale.Cols; x++)
            if(data[y, x, 0] != 125) continue;
            points.Add(new Point(x, y)); // Gather pixels
    listHollowArea.Add(new LayerHollowArea(points.ToArray()));

The question: Is there any function or code i can use to skip 4 to 6 and get all pixels inside the matched countours without that much effort?

edit retag flag offensive close merge delete


what weird language is it ? opencv does not have an Image class

berak gravatar imageberak ( 2020-06-17 01:26:26 -0500 )edit

have a look at connectedComponents() and findNonZero()

berak gravatar imageberak ( 2020-06-17 01:44:24 -0500 )edit

Language: C# with EmguCV. Will take a look at both, i also updated the code so i search only inside the contour rectangle by get the RectangleBounds, so now i have:

                       var rect = CvInvoke.BoundingRectangle(contours[i]);
                        byte[,,] data = grayscale.Data;
                        for (int y = rect.Y; y < rect.Bottom; y++)
                            for (int x = rect.X; x < rect.Right; x++)
                            { ....

is findNonZero faster than my last approach?

sn4k3 gravatar imagesn4k3 ( 2020-06-17 09:55:31 -0500 )edit

is findNoneZero faster than my last approach?

idk, YOU have to test it. at least it's vectorized

berak gravatar imageberak ( 2020-06-17 10:16:17 -0500 )edit

Ok it seens my search lot faster:

RectSearch: 1ms

FindNonZero: 27ms

RectSearch: 0ms (When empty)

FindNonZero: 2ms (When empty)

RectSearch: 1ms

FindNonZero: 22ms

Make sense since FindNonZero needs find whole image for nonZeros

Will continue my demand

sn4k3 gravatar imagesn4k3 ( 2020-06-17 15:47:53 -0500 )edit