C# 找到给定一组点的区域
给定x、y坐标列表和已知的宽度和高度,如何确定封闭区域的数量(以C#为单位) 例如: 在该图中,定义了5个封闭区域:C# 找到给定一组点的区域,c#,image-processing,geometry,C#,Image Processing,Geometry,给定x、y坐标列表和已知的宽度和高度,如何确定封闭区域的数量(以C#为单位) 例如: 在该图中,定义了5个封闭区域: 面部(1) 眼睛(2) 鼻子(1) 面部右侧(1) x、y点列表可以是任何黑色像素,包括嘴巴。示例图像中有几个特殊情况。你必须决定如何对付他们 通常,首先将光栅图像转换为一系列多边形。那么,计算面积就相当简单了(见Servy的评论) 特殊情况是面部和口腔的侧面。两者都是开放形状,而不是闭合形状。你需要弄清楚如何关闭它们。我使用OpenCV取得了巨大成功。有一个名为.net的库
x、y点列表可以是任何黑色像素,包括嘴巴。示例图像中有几个特殊情况。你必须决定如何对付他们 通常,首先将光栅图像转换为一系列多边形。那么,计算面积就相当简单了(见Servy的评论)
特殊情况是面部和口腔的侧面。两者都是开放形状,而不是闭合形状。你需要弄清楚如何关闭它们。我使用OpenCV取得了巨大成功。有一个名为.net的库 以下是一个关于Emgu CV替代品的问题: 该库包含用于识别轮廓和查找轮廓特性的函数。您可以在该区域搜索以查找更多信息
如果您正在寻找这个特定问题的快速解决方案,并且希望编写自己的代码,而不是重用其他代码,那么我没有一个算法可以实现这一点。抱歉。我认为这归结为计算每个区域中(非黑色)像素的数量。如果选择一个非黑色的像素,请将其添加到
散列集
,查看所选像素上方、下方、左侧和右侧的像素是否也是非黑色的
每次你发现新的非黑色像素(通过向上/向下/向左/向右)时,将它们添加到你的集合中。当你找到它们时,数一数
区域的面积是count/(像素totaldrawing的宽度*像素totaldrawing的高度)
乘以整个矩形的面积(取决于所需的单位)
评论:我不认为这看起来像一个多边形。这就是为什么我想到了简单绘图软件的“用油漆填充”功能。你可以使用这个简单的算法,基于使用辅助位图进行洪水填充的想法:
//backColor是开头填充点处颜色的整数表示形式。
//生成封闭形状的像素。
私有int GetFillSize(位图b,点填充点)
{
整数计数=0;
p点;
堆栈像素=新堆栈();
var backColor=b.GetPixel(fillPoint.X,fillPoint.Y);
像素。推(填充点);
while(pixels.Count!=0)
{
计数++;
p=(点)像素。Pop();
b、 设置像素(p.X,p.Y,背景色);
if(b.GetPixel(p.X-1,p.Y).ToArgb()==背景色)
Push(新点(p.X-1,p.Y));
if(b.GetPixel(p.X,p.Y-1).ToArgb()==背景色)
像素。推(新点(p.X,p.Y-1));
if(b.GetPixel(p.X+1,p.Y).ToArgb()==背景色)
像素。推(新点(p.X+1,p.Y));
if(b.GetPixel(p.X,p.Y+1).ToArgb()==背景色)
像素。推(新点(p.X,p.Y+1));
}
返回计数;
}
更新
上述代码仅适用于此四重链接的封闭区域。以下代码适用于八位链接的封闭区域
//偏移点初始化。
点[]偏移=新点[]
{
新点(-1,-1),
新点(-0,-1),
新点(+1,-1),
新点(+1,-0),
新点(+1,+1),
新点(+0,+1),
新点(-1,+1),
新点(-1,+0),
};
...
专用整型填充(位图b,点填充点)
{
整数计数=0;
p点;
堆栈像素=新堆栈();
var backColor=b.GetPixel(fillPoint.X,fillPoint.Y).ToArgb();
像素。推(填充点);
while(pixels.Count!=0)
{
计数++;
p=(点)像素。Pop();
b、 设置像素(p.X,p.Y,颜色来自argb(背景色));
foreach(偏移量中的var偏移量)
if(b.GetPixel(p.X+offset.X,p.Y+offset.Y).ToArgb()==背景色)
像素推送(新点(p.X+offset.X,p.Y+offset.Y));
}
返回计数;
}
下面的图片清楚地说明了我的意思。还可以向偏移阵列添加更多的远点,以便能够用间隙填充区域
将包围区域的像素想象成多边形,然后查看如何获取多边形区域抱歉,在转换过程中丢失了一些东西…我需要计算区域数(5)而不是区域面积。酷。这使我模糊的描述清晰明了。我喜欢。不错,对我正在研究的另一个区域很有用,但是你知道如何确定封闭区域的数量吗?你可以使用我的算法对每个非背景色(你的示例图像上的黑色)像素进行区域检测。每次填充后,该区域将不会被检测到(因为它们将被填充),并且您必须增加已查找区域的数量。当然,此方法适用于链接区域。因此,在另一种情况下,使用OpenCV,@Jason Hermann如何回答。@KvanTTT-这在像素宽度为2或更大的情况下非常有效,但是,如果像素宽度为1px,它总是返回为仅1个封闭区域。有没有办法修改上面的代码来处理这个问题?