使用 EMGU CV 从图像中切出形状
Cut the shapes out of the image with EMGU CV
一天中的所有美好时光!
面临以下任务:您需要找到图像中的形状,将它们剪下来并保存为jpg或png。
找到算出的形状(附上图片),但如何得到它们的极坐标?
我用 EMGU CV 找到形状。
我正在从 PictureBox 中取出图像。
// - 想通过朋友圈求图形中心到边缘的距离,但是没看懂它们是怎么工作的
Image<Gray, byte> grayImage = inputImage.SmoothMedian(1).Convert<Gray, byte>().ThresholdBinaryInv(new Gray(230), new Gray(255));
VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint();
Mat hierarchy = new Mat();
for (int i = 0; i < contours.Size; i++)
{
double perimetr = CvInvoke.ArcLength(contours[i], true);
VectorOfPoint approximation = new VectorOfPoint();
CvInvoke.ApproxPolyDP(contours[i], approximation, 0.04 * perimetr, true);
if (approximation.Size >= 3 && perimetr > 100 && approximation.Size != 5)
{
CvInvoke.DrawContours(inputImage, contours, i, new MCvScalar(0, 255, 0), 2);
}
Moments moments = CvInvoke.Moments(contours[i]);
int x = (int)(moments.M10 / moments.M00);
int y = (int)(moments.M01 / moments.M00);
if (perimetr > 100)
{
if (approximation.Size == 3)
{
CvInvoke.DrawContours(inputImage, contours, i, new MCvScalar(0, 255, 0), 2);
CvInvoke.PutText(inputImage, "Triangle", new Point(x, y), Emgu.CV.CvEnum.FontFace.HersheyPlain, 1,
new MCvScalar(0, 0, 255), 1);
}
if (approximation.Size == 4)
{
Rectangle rect = CvInvoke.BoundingRectangle(contours[i]);
double aspectRatio = (double)rect.Width / (double)rect.Height;
if (aspectRatio >= 0.95 && aspectRatio <= 1.05)
{
CvInvoke.DrawContours(inputImage, contours, i, new MCvScalar(0, 255, 0), 2);
CvInvoke.PutText(inputImage, "Square", new Point(x, y), Emgu.CV.CvEnum.FontFace.HersheyPlain, 1,
new MCvScalar(0, 0, 255), 1);
}
else
{
CvInvoke.DrawContours(inputImage, contours, i, new MCvScalar(0, 255, 0), 2);
CvInvoke.PutText(inputImage, "Rectangle", new Point(x, y), Emgu.CV.CvEnum.FontFace.HersheyPlain, 1,
new MCvScalar(0, 0, 255), 1);
}
}
if (approximation.Size == 5)
{
CvInvoke.DrawContours(inputImage, contours, i, new MCvScalar(0, 255, 0), 2);
CvInvoke.PutText(inputImage, "Pentagon", new Point(x, y), Emgu.CV.CvEnum.FontFace.HersheyPlain, 1,
new MCvScalar(0, 0, 255), 1);
}
if (approximation.Size == 6)
{
CvInvoke.DrawContours(inputImage, contours, i, new MCvScalar(0, 255, 0), 2);
CvInvoke.PutText(inputImage, "Hexagon", new Point(x, y), Emgu.CV.CvEnum.FontFace.HersheyPlain, 1,
new MCvScalar(0, 0, 255), 1);
}
if (approximation.Size > 6)
{
var R = (double)perimetr / (3.14 * 2);
if (R > (Math.Min(inputImage.Width, inputImage.Height) / 3) * 0.1 && R < (Math.Min(inputImage.Width, inputImage.Height) / 2))
{
CvInvoke.DrawContours(inputImage, contours, i, new MCvScalar(0, 255, 0), 2);
CvInvoke.PutText(inputImage, "Circle", new Point(x, y), Emgu.CV.CvEnum.FontFace.HersheyPlain, 1,
new MCvScalar(0, 0, 255), 1);
}
}
}
}
感谢您的关注。
Input image
Output image
我找到了问题的解决方案。有一种方法 returns 用点数组描述轮廓。
Point[] contour = contours[i].ToArray();
一天中的所有美好时光!
面临以下任务:您需要找到图像中的形状,将它们剪下来并保存为jpg或png。
找到算出的形状(附上图片),但如何得到它们的极坐标?
我用 EMGU CV 找到形状。
我正在从 PictureBox 中取出图像。
// - 想通过朋友圈求图形中心到边缘的距离,但是没看懂它们是怎么工作的
Image<Gray, byte> grayImage = inputImage.SmoothMedian(1).Convert<Gray, byte>().ThresholdBinaryInv(new Gray(230), new Gray(255));
VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint();
Mat hierarchy = new Mat();
for (int i = 0; i < contours.Size; i++)
{
double perimetr = CvInvoke.ArcLength(contours[i], true);
VectorOfPoint approximation = new VectorOfPoint();
CvInvoke.ApproxPolyDP(contours[i], approximation, 0.04 * perimetr, true);
if (approximation.Size >= 3 && perimetr > 100 && approximation.Size != 5)
{
CvInvoke.DrawContours(inputImage, contours, i, new MCvScalar(0, 255, 0), 2);
}
Moments moments = CvInvoke.Moments(contours[i]);
int x = (int)(moments.M10 / moments.M00);
int y = (int)(moments.M01 / moments.M00);
if (perimetr > 100)
{
if (approximation.Size == 3)
{
CvInvoke.DrawContours(inputImage, contours, i, new MCvScalar(0, 255, 0), 2);
CvInvoke.PutText(inputImage, "Triangle", new Point(x, y), Emgu.CV.CvEnum.FontFace.HersheyPlain, 1,
new MCvScalar(0, 0, 255), 1);
}
if (approximation.Size == 4)
{
Rectangle rect = CvInvoke.BoundingRectangle(contours[i]);
double aspectRatio = (double)rect.Width / (double)rect.Height;
if (aspectRatio >= 0.95 && aspectRatio <= 1.05)
{
CvInvoke.DrawContours(inputImage, contours, i, new MCvScalar(0, 255, 0), 2);
CvInvoke.PutText(inputImage, "Square", new Point(x, y), Emgu.CV.CvEnum.FontFace.HersheyPlain, 1,
new MCvScalar(0, 0, 255), 1);
}
else
{
CvInvoke.DrawContours(inputImage, contours, i, new MCvScalar(0, 255, 0), 2);
CvInvoke.PutText(inputImage, "Rectangle", new Point(x, y), Emgu.CV.CvEnum.FontFace.HersheyPlain, 1,
new MCvScalar(0, 0, 255), 1);
}
}
if (approximation.Size == 5)
{
CvInvoke.DrawContours(inputImage, contours, i, new MCvScalar(0, 255, 0), 2);
CvInvoke.PutText(inputImage, "Pentagon", new Point(x, y), Emgu.CV.CvEnum.FontFace.HersheyPlain, 1,
new MCvScalar(0, 0, 255), 1);
}
if (approximation.Size == 6)
{
CvInvoke.DrawContours(inputImage, contours, i, new MCvScalar(0, 255, 0), 2);
CvInvoke.PutText(inputImage, "Hexagon", new Point(x, y), Emgu.CV.CvEnum.FontFace.HersheyPlain, 1,
new MCvScalar(0, 0, 255), 1);
}
if (approximation.Size > 6)
{
var R = (double)perimetr / (3.14 * 2);
if (R > (Math.Min(inputImage.Width, inputImage.Height) / 3) * 0.1 && R < (Math.Min(inputImage.Width, inputImage.Height) / 2))
{
CvInvoke.DrawContours(inputImage, contours, i, new MCvScalar(0, 255, 0), 2);
CvInvoke.PutText(inputImage, "Circle", new Point(x, y), Emgu.CV.CvEnum.FontFace.HersheyPlain, 1,
new MCvScalar(0, 0, 255), 1);
}
}
}
}
感谢您的关注。
Input image
Output image
我找到了问题的解决方案。有一种方法 returns 用点数组描述轮廓。
Point[] contour = contours[i].ToArray();