user3512156
user3512156

Reputation: 1

Extract circle area from an image in EMGUCV C#

I use: Emgucv 4.0.1 Opencv 4.1.0

I have a series of circles detected with HoughCircles function that I need to analize one by one. I need to calculate how much color is in the rounded green circle, so I have to extract only the circle image but I know how to extract only the box that contains much more pixel than the circle. How to extract only the image inside the surrounded green area? See images in link below.

1) Source Image

2) Boxed image I retrieved with more pixel than i want

3) Image that I would like to extract

// m_ListCircles = list from HoughCircles() circles coordinates.
// cell = cell number to extract.
// pictureBox1 = main picturebox with all circles detected.
// pictureBoxROI = picturebox destination single circles cutted.

int id = (int)m_ListCircles[0 + cell ];
int x = (int)m_ListCircles[1 + cell ];
int y = (int)m_ListCircles[2 + cell ];
int r = (int)m_ListCircles[3 + cell ]; // radius

// box area around the circle
int X0 = x;
int Y0 = y;
int X1 = x + r * 2;
int Y1 = y + r * 2;

// area to copy
int wid = Math.Abs(X0 - X1);
int hgt = Math.Abs(Y0 - Y1);

if ((wid < 1) || (hgt < 1)) return;

// create a rectangle are to copy
Rectangle source_rectangle = new Rectangle(Math.Min(X0, X1),Math.Min(Y0,Y1), wid, hgt);

// assign the area copied to image var
var image = new Image<Bgr, byte>(new Bitmap(pictureBox1.Image));

image.ROI = source_rectangle;

// show image
pictureBoxROI.Image = image.Bitmap;
pictureBoxROI.Refresh();

/*
// tried this but result is always a black image.
Point xyCell = new Point();
xyCell.X = X0;
xyCell.Y = Y0;

Image<Gray, byte> mask = new Image<Gray, byte>(image.Width, image.Height);
CvInvoke.Circle(mask, xyCella, r, new MCvScalar(255, 255, 255), -1, 
LineType.AntiAlias, 0);
Image<Bgr, byte> dest = new Image<Bgr, byte>(image.Width, image.Height);
dest = image.And(image, mask);

pictureBoxROI.Image = dest.Bitmap;
pictureBoxROI.Refresh();
*/

Upvotes: 0

Views: 1561

Answers (2)

FalcoGer
FalcoGer

Reputation: 2467

You can only have rectangular images. However you can after cutting the rectangle set all the pixels outside of the circle to transparent.
You can determine which pixels are outside of the circle by calculating their distance from the center point of your image using pythagoras. This is very slow of course, as you must loop over all pixels, but for low pixel counts it's reasonably fast.

try
{
    Image rectCroppedImage = originalImage.Clone(CropRect, originalImage.PixelFormat);
    double r = rectCroppedImage.Height; // because you are centered on your circle

    Bitmap img = new Bitmap(rectCroppedImage);

    for (int x = 0; x < img.Width; x++)
    {
        for (int y = 0; y < img.Height; y++)
        {
            // offset to center
            int virtX = x - img.Width / 2;
            int virtY = y - img.Height / 2;

            if (Math.Sqrt(virtX * virtX + virtY * virtY) > r)
            {
                img.SetPixel(x, y, Color.Transparent);
            }
        }
    }
    return img; // your circle cropped image
}
catch (Exception ex)
{
}

This could also be achieved by using a mask and "multiplying" your image with a white circle. Such a thing can be achieved for example with image magick. You can find an ImageMagick NuGet packet here: https://github.com/dlemstra/Magick.NET

Upvotes: 1

Krzysztof Skowronek
Krzysztof Skowronek

Reputation: 2936

You can always create masks of ROI form the found circles and analyze tha images like that

Custom ROI - this shows how to use the mask

Upvotes: 1

Related Questions