C# 查找矩形时忽略外部点

C# 查找矩形时忽略外部点,c#,opencv,computer-vision,emgucv,C#,Opencv,Computer Vision,Emgucv,我有一些像这样的图像,我需要找到中心矩形 我使用EmguCV示例的一个变体来查找矩形,并附带了此示例 using (MemStorage storage = new MemStorage()) { //allocate storage for contour approximation //Contour<Point> contours = gray.FindContours() Contour<Point> contours = gray.FindC

我有一些像这样的图像,我需要找到中心矩形

我使用EmguCV示例的一个变体来查找矩形,并附带了此示例

using (MemStorage storage = new MemStorage())
{ //allocate storage for contour approximation

    //Contour<Point> contours = gray.FindContours()
    Contour<Point> contours = gray.FindContours(Emgu.CV.CvEnum.CHAIN_APPROX_METHOD.CV_CHAIN_APPROX_SIMPLE,
     Emgu.CV.CvEnum.RETR_TYPE.CV_RETR_LIST,
  storage);

    for (; contours != null; contours = contours.HNext)
    {
        Contour<Point> currentContour = contours.ApproxPoly(contours.Perimeter * 0.05, storage);
        //Seq<Point> currentContour = contours.GetConvexHull(Emgu.CV.CvEnum.ORIENTATION.CV_CLOCKWISE);

        if (contours.Area > MinRectangleArea) //only consider contours with area greater than 20000
        {
            if (currentContour.Total == 4) //The contour has 4 vertices.
            {
                bool isRectangle = true;
                Point[] pts = currentContour.ToArray();
                LineSegment2D[] edges = PointCollection.PolyLine(pts, true);

                for (int i = 0; i < edges.Length; i++)
                {
                    double angle = Math.Abs(edges[(i + 1) % edges.Length].GetExteriorAngleDegree(edges[i]));
                    if (angle < 90 - RectangleAngleMargin  || angle > RectangleAngleMargin + 90)
                    {
                        isRectangle = false;
                        break;
                    }
                }

                if (isRectangle)
                {
                    boxList.Add(currentContour.GetMinAreaRect());
                }
            }
        }
    }
使用(MemStorage=newmemstorage())
{//为轮廓近似分配存储空间
//等高线=灰色。FindContours()
等高线=灰色。FindContours(Emgu.CV.CvEnum.CHAIN_近似法。CV_CHAIN_近似法),
Emgu.CV.CvEnum.RETR_TYPE.CV_RETR_LIST,
储存);
对于(;轮廓!=null;轮廓=轮廓.HNext)
{
轮廓电流轮廓=轮廓.近似多边形(轮廓.周长*0.05,存储);
//Seq currentContour=等高线.GetConvexHull(Emgu.CV.CvEnum.ORIENTATION.CV_顺时针);
如果(Couth.Stand>MinRectangleArea)/只考虑大于20000的区域的等高线
{
如果(currentContour.Total==4)//轮廓有4个顶点。
{
布尔isRectangle=真;
点[]pts=currentContour.ToArray();
LineSegment2D[]边=点集合.多段线(pts,true);
对于(int i=0;i矩形边距+90)
{
isRectangle=false;
打破
}
}
如果(isRectangle)
{
Add(currentContour.getMinareact());
}
}
}
}
}

在这些图像上执行的结果有时会发现这两个矩形:

橙色的长方形可以,这就是我需要的。但是我不要蓝色的。有时四个顶点位于图像的边界内,通常其中一个在外

将FindContours函数的RETR_类型更改为CV_RETR_EXTERNAL,我只得到了蓝色矩形,因此我想知道是否有一个不获取带有外部点的轮廓的选项


真实的图像实际上可以在橙色内有更小的矩形(或者一条线将矩形分割),因此在这之后,我选择了更大的矩形作为我想要的矩形,但不能用蓝色的矩形来实现。

查看示例图像,我会选择另一种方法

与传统的轮廓检测不同,如果执行Hough线检测,然后形成找到的线的交点,您将准确地找到正在搜索的矩形的四个顶点


如果您在编码方面需要帮助,请告诉我,我将编辑我的答案。

谢谢您的回答。输入图像实际上是霍夫线检测的结果。实际图像的矩形内可能有一些“嘈杂”的线条(例如:)。有这么多线,我需要做一系列的检查,检查交点和点的位置,最终得到一个有点容易出错的代码。此时,我正在使用CV_RETR_EXTERNAL和CV_RETR_SIMPLE方法搜索轮廓,并从另一组中删除外部轮廓,但我认为解决方案更好您的场景现在更清晰了。如果您使用CV_RETR_EXTERNAL,它会给出“外部”轮廓,因此您的蓝色轮廓(包围橙色)将是您得到的轮廓。如果您想更好地了解轮廓在opencv中的组织方式,这里有一个有用的链接:好的,我误解了该参数的含义,我现在知道了。在我的例子中,findContentours函数似乎不是最好的选择,但仍然不知道为什么它会找到蓝色矩形。无论如何,我会通过手动检查交叉点来完成。