Emgu CV 绘制旋转矩形

Posted

技术标签:

【中文标题】Emgu CV 绘制旋转矩形【英文标题】:Emgu CV draw rotated rectangle 【发布时间】:2015-06-18 13:00:15 【问题描述】:

我正在寻找几天在图像框架上绘制矩形的解决方案。基本上我使用CvInvoke.cvRectangle 方法在图像上绘制矩形,因为我需要抗锯齿矩形。 但问题是当我需要为给定角度旋转给定形状时。我找不到任何好的解决方案。 我试图在单独的框架上绘制矩形,然后旋转孔框架并将这个新图像应用到我的基础框架之上。但在这个解决方案中,抗锯齿存在问题。它不工作。 我正在开发一个简单的应用程序,它应该允许绘制几种形状,调整它们的大小并旋转给定的角度。 知道如何实现这一目标吗?

【问题讨论】:

【参考方案1】:

我发现在轮廓上绘制最小封闭矩形的最佳方法是使用Polylines() 函数,该函数使用从MinAreaRect() 函数返回的顶点。当然还有其他方法可以做到这一点。下面是代码:

// Find contours
var contours = new Emgu.CV.Util.VectorOfVectorOfPoint();
Mat hierarchy = new Mat();
CvInvoke.FindContours(image, contours, hierarchy, RetrType.Tree, ChainApproxMethod.ChainApproxSimple);

// According to your metric, get an index of the contour you want to find the min enclosing rectangle for
int index = 2; // Say, 2nd index works for you.
var rectangle = CvInvoke.MinAreaRect(contours[index]);
Point[] vertices = Array.ConvertAll(rectangle.GetVertices(), Point.Round);
CvInvoke.Polylines(image, vertices, true, new MCvScalar(0, 0, 255), 5);

结果可以在下图中可视化,红色是最小的封闭矩形。

【讨论】:

【参考方案2】:

我使用 C# 和 EMGU.CV(4.1),我认为这段代码移植到任何平台都不会困难。

在你的助手中添加函数:

public static Mat DrawRect(Mat input, RotatedRect rect, MCvScalar color = default(MCvScalar),
        int thickness = 1, LineType lineType = LineType.EightConnected, int shift = 0)

    var v = rect.GetVertices();

    var prevPoint = v[0];
    var firstPoint = prevPoint;
    var nextPoint = prevPoint;
    var lastPoint = nextPoint;


    for (var i = 1; i < v.Length; i++)
    
        nextPoint = v[i];
        CvInvoke.Line(input, Point.Round(prevPoint), Point.Round(nextPoint), color, thickness, lineType, shift);
        prevPoint = nextPoint;
        lastPoint = prevPoint;
    
    CvInvoke.Line(input, Point.Round(lastPoint), Point.Round(firstPoint), color, thickness, lineType, shift);
    return input;

这会按点绘制旋转矩形。这里通过方法 Point.Round 使用舍入点,因为 RotatedRect 在浮点坐标中有点,CvInvoke.Line 将点作为整数。

用途:

    var mat = Mat.Zeros(200, 200, DepthType.Cv8U, 3);
    mat.GetValueRange();
    var rRect = new RotatedRect(new PointF(100, 100), new SizeF(100, 50), 30);
    DrawRect(mat, rRect,new MCvScalar(255,0,0));
    var brect = CvInvoke.BoundingRectangle(new VectorOfPointF(rRect.GetVertices()));
    CvInvoke.Rectangle(mat, brect, new MCvScalar(0,255,0), 1,  LineType.EightConnected, 0);

结果:

【讨论】:

【参考方案3】:

您应该阅读OpenCV documentation。

有一个RotatedRectangle 类可用于您的任务。您可以指定矩形旋转的角度。

这是一个用于绘制旋转矩形的示例代码(取自文档):

Mat image(200, 200, CV_8UC3, Scalar(0));
RotatedRect rRect = RotatedRect(Point2f(100,100), Size2f(100,50), 30);

Point2f vertices[4];
rRect.points(vertices);
for (int i = 0; i < 4; i++)
    line(image, vertices[i], vertices[(i+1)%4], Scalar(0,255,0));

Rect brect = rRect.boundingRect();
rectangle(image, brect, Scalar(255,0,0));

imshow("rectangles", image);
waitKey(0);

结果如下:

【讨论】:

Point2f 不是 CvInvoke.Line() 的正确类型。因此答案是错误的。

以上是关于Emgu CV 绘制旋转矩形的主要内容,如果未能解决你的问题,请参考以下文章

如何在emgu CV中进行相机校准后访问旋转和平移向量

如何使用 C# 中的 Emgu CV 库在图像上绘制矩形。举个例子

使用旋转矩形提取图像 ROI

OpenCV-最小包围旋转矩形边框cv::minAreaRect

OpenCV-最小包围旋转矩形边框cv::minAreaRect

在python中的openCV中绘制一个旋转的框