填补emgu cv中的漏洞
Posted
技术标签:
【中文标题】填补emgu cv中的漏洞【英文标题】:Fill the holes in emgu cv 【发布时间】:2011-11-04 11:36:33 【问题描述】:如何填补 emgu cv 中二进制图像中的漏洞? 在 Aforge.net 中使用 Fillholes 类很简单。
【问题讨论】:
【参考方案1】:认为这个问题有点老了,我想为这个问题提供一个替代解决方案。
如果您使用以下方法,您可以获得与 Chris' 相同的结果而不会出现内存问题:
private Image<Gray,byte> FillHoles(Image<Gray,byte> image)
var resultImage = image.CopyBlank();
Gray gray = new Gray(255);
using (var mem = new MemStorage())
for (var contour = image.FindContours(
CHAIN_APPROX_METHOD.CV_CHAIN_APPROX_SIMPLE,
RETR_TYPE.CV_RETR_CCOMP,
mem); contour!= null; contour = contour.HNext)
resultImage.Draw(contour, gray, -1);
return resultImage;
上述方法的好处是您可以选择性地填充符合您标准的孔。例如,您可能想要填充像素数(blob 内的黑色像素数)低于 50 的孔,等等。
private Image<Gray,byte> FillHoles(Image<Gray,byte> image, int minArea, int maxArea)
var resultImage = image.CopyBlank();
Gray gray = new Gray(255);
using (var mem = new MemStorage())
for (var contour = image.FindContours(
CHAIN_APPROX_METHOD.CV_CHAIN_APPROX_SIMPLE,
RETR_TYPE.CV_RETR_CCOMP,
mem); contour!= null; contour = contour.HNext)
if ( (contour.Area < maxArea) && (contour.Area > minArea) )
resultImage.Draw(contour, gray, -1);
return resultImage;
【讨论】:
我认为这是最好的答案。 我也是。以前经常会导致 OutOfMemory 问题【参考方案2】:是的,有一种方法,但它基于 cvFloodFill 操作有点混乱。现在,这个算法的设计目的是用一种颜色填充一个区域,直到它达到类似于区域增长算法的边缘。要有效地使用它,您需要使用一些创造性的编码,但我警告您,此代码只是为了让您入门,它可能需要重构以加快速度。就目前而言,循环遍历小于 255 的每个像素应用 cvFloodFill 检查该区域的大小,然后如果它在某个区域以下,则将其填充。
重要的是要注意,图像的副本是由原始图像制成的,以作为指针提供给 cvFloodFill 操作。如果提供了直接图像,那么您最终将得到一个白色图像。
OpenFileDialog OpenFile = new OpenFileDialog();
if (OpenFileDialog.ShowDialog() == DialogResult.OK)
Image<Bgr, byte> image = new Image<Bgr, byte>(OpenFile.FileName);
for (int i = 0; i < image.Width; i++)
for (int j = 0; j < image.Height; j++)
if (image.Data[j, i, 0] != 255)
Image<Bgr, byte> image_copy = image.Copy();
Image<Gray, byte> mask = new Image<Gray, byte>(image.Width + 2, image.Height + 2);
MCvConnectedComp comp = new MCvConnectedComp();
Point point1 = new Point(i, j);
//CvInvoke.cvFloodFill(
CvInvoke.cvFloodFill(image_copy.Ptr, point1, new MCvScalar(255, 255, 255, 255),
new MCvScalar(0, 0, 0),
new MCvScalar(0, 0, 0), out comp,
Emgu.CV.CvEnum.CONNECTIVITY.EIGHT_CONNECTED,
Emgu.CV.CvEnum.FLOODFILL_FLAG.DEFAULT, mask.Ptr);
if (comp.area < 10000)
image = image_copy.Copy();
“new MCvScalar(0, 0, 0), new MCvScalar(0, 0, 0)”在这种情况下并不重要,因为您只是填写二进制图像的结果。您可以尝试使用其他设置,看看您可以实现什么结果。 "if (comp.area key 常量,要更改的是您要更改方法将填充的孔大小。
这些是您可以期待的结果:
原创
结果
这种方法的问题是它非常占用内存,它在 200x200 的图像上消耗了 6GB 的内存,当我尝试 200x300 时,它吃掉了我所有的 8GB 内存,并导致一切崩溃。除非你的大部分图像是白色的,并且你想填补微小的空白,否则你可以尽量减少应用我会避免的方法的位置。我建议您编写自己的类来检查不是 255 的每个像素并添加围绕它的像素数。然后,您可以记录不是 255 的每个像素的位置(在一个简单的列表中),如果您的计数低于阈值,则在您的图像中将这些位置设置为 255(通过迭代列表)。
如果您不想编写自己的 Aforge FillHoles 类,我会坚持使用它,因为它是为此目的而设计的。
干杯
克里斯
【讨论】:
【参考方案3】:您可以使用 FillConvexPoly
image.FillConvexPoly(externalContours.ToArray(), new Gray(255));
【讨论】:
以上是关于填补emgu cv中的漏洞的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 C# 中的 Emgu CV 库在图像上绘制矩形。举个例子