我正在尝试检测此图像上的矩形:
使用此代码:
static void Main(string[] args)
{
// Open your image
string path = "test.png";
Bitmap image = (Bitmap)Bitmap.FromFile(path);
// locating objects
BlobCounter blobCounter = new BlobCounter();
blobCounter.FilterBlobs = true;
blobCounter.MinHeight = 5;
blobCounter.MinWidth = 5;
blobCounter.ProcessImage(image);
Blob[] blobs = blobCounter.GetObjectsInformation();
// check for rectangles
SimpleShapeChecker shapeChecker = new SimpleShapeChecker();
foreach (var blob in blobs)
{
List<IntPoint> edgePoints = blobCounter.GetBlobsEdgePoints(blob);
List<IntPoint> cornerPoints;
// use the shape checker to extract the corner points
if (shapeChecker.IsQuadrilateral(edgePoints, out cornerPoints))
{
// only do things if the corners form a rectangle
if (shapeChecker.CheckPolygonSubType(cornerPoints) == PolygonSubType.Rectangle)
{
// here i use the graphics class to draw an overlay, but you
// could also just use the cornerPoints list to calculate your
// x, y, width, height values.
List<Point> Points = new List<Point>();
foreach (var point in cornerPoints)
{
Points.Add(new Point(point.X, point.Y));
}
Graphics g = Graphics.FromImage(image);
g.DrawPolygon(new Pen(Color.Red, 5.0f), Points.ToArray());
image.Save("result.png");
}
}
}
}
但它无法识别矩形(墙)。它只识别大正方形,当我减小 minHeight 和 minWidth 时,它识别文字上的梯形..
我提出了一种不同的算法方法,在使用图像处理算法近一年之后,我可以告诉你的是,要创建一个有效的算法,你必须“反思”你作为一个人会如何做到这一点,这是建议的方法:
我们并不真正关心纹理,我们关心边缘(矩形是边缘),因此我们将应用边缘检测>差异(http://www.aforgenet.com/framework/docs/html /d0eb5827-33e6-c8bb-8a62-d6dd3634b0c9.htm),这给了我们:
我们想要夸大墙壁,作为人类,我们知道我们正在寻找墙壁,但计算机不知道这一点,因此,应用两轮形态学>膨胀(http://www.aforgenet.com/ Framework/docs/html/88f713d4-a469-30d2-dc57-5ceb33210723.htm),这给了我们:
我们只关心什么是墙,什么不是墙,应用二值化>阈值(http://www.aforgenet.com/framework/docs/html/503a43b9-d98b-a19f-b74e-44767916ad65.htm ),我们得到:
(可选)我们可以应用斑点提取来擦除标签(“QUARTO、BANHEIRO”等)
我们应用颜色>反转,这只是完成,因为下一步检测到白色而不是黑色。
应用Blob>处理>连接组件标签(http://www.aforgenet.com/framework/docs/html/240525ea-c114-8b0a-f294-508aae3e95eb.htm),这将为我们提供所有矩形,像这样:
请注意,对于每个彩色框,您都有其坐标、中心、宽度和高度。因此,您可以使用该坐标从真实图像中提取片段。
PS:强烈建议使用 AForge 图像处理实验室程序来测试您的算法。
每次找到矩形时,都会在图形上绘制多边形,并且仅保存该矩形的文件。这意味着
result.png
一次仅包含一个矩形。
首先尝试将所有矩形保存在
List<List<Points>>
中,然后遍历它并将所有矩形添加到图像中。像这样的东西(伪):
var image..
var rectangles..
var blobs..
foreach (blob in blobs)
{
if (blob is rectangle)
{
rectangles.add(blob);
}
}
foreach (r in rectangles)
{
image.draw(r.points);
}
image.save("result.png");
如果您现在的问题是避免图像上的文字产生噪音,请使用 FillHoles,其孔的宽度和高度小于最小矩形但大于任何文字。
如果图像质量良好并且没有文本接触图像边框,则反转图像和 FillHoles 将删除大部分内容。
希望我正确理解你的问题。
我们正在尝试检测这么多矩形中的矩形(考虑网格的灰色矩形)。几乎所有的算法都会在这里感到困惑。您没有从输入图像中消除externals。为什么不使用背景颜色替换网格线颜色或使用上面的阈值首先消除所有网格。
然后将所有像素增长到等于墙的宽度,找到所有水平和垂直线,然后使用数学来找到使用检测到的线的矩形。不受控制的填充是有风险的,因为当边界不闭合时,填充会使两个房间成为一个矩形。
Imports System.Drawing
Imports AForge.Imaging.Filters
Module Module1
Sub Main()
Dim Img = Bitmap.FromFile("Img3.png")
Dim grayImage = Grayscale.CommonAlgorithms.RMY.Apply(Img)
Dim Edge = New DifferenceEdgeDetector()
Dim DifferenceEdgeDetector = New DifferenceEdgeDetector()
DifferenceEdgeDetector.ApplyInPlace(grayImage)
Dim Dilatation = New Dilatation()
Dilatation.Apply(grayImage)
Dim Threshold = New Threshold(100)
Threshold.ApplyInPlace(grayImage)
Dim ConnectedComponentsLabeling = New ConnectedComponentsLabeling()
Dim newImage = ConnectedComponentsLabeling.Apply(grayImage)
newImage.Save("Out.png")
End Sub
End Module