OpenCVSharp findContours returns 错误数据
OpenCVSharp's findContour returns wrong data
我正在尝试实现一个在二值图像中查找轮廓并滤除小轮廓的函数。
这是我的代码和示例图片。这是一个超级简单的功能,可以去除小面积的斑点。但是我一直得到 "contours of edges" 而不是区域的轮廓。 :S
private IplImage RemoveNoise( IplImage image, int minArea )
{
List<CvPoint[]> listOfPoints = new List<CvPoint[]>();
CvSeq<CvPoint> contoursRaw;
List<ContourData> contours = new List<ContourData>();
using( CvMemStorage storage = new CvMemStorage() )
{
//find contoures
//Cv.FindContours( image, storage, out contoursRaw );
Cv.FindContours( image, storage, out contoursRaw, CvContour.SizeOf, ContourRetrieval.Tree, ContourChain.ApproxSimple );
//contoursRaw = Cv.ApproxPoly( contoursRaw, CvContour.SizeOf, storage, ApproxPolyMethod.DP, 3, true );
while( contoursRaw != null )
{
CvSeq<CvPoint> result = contoursRaw;
double area = Cv.ContourArea( result );
//filter out small regions
if( area >= minArea )
{
List<CvPoint> points = new List<CvPoint>();
int i = 0;
while( result[ i ] != null )
{
points.Add( new CvPoint( result[ i ].Value.X, result[ i ].Value.Y ) );
i++;
}
listOfPoints.Add( points.ToArray() );
}
contoursRaw = contoursRaw.HNext;
}
}
// draw large regions
IplImage output = new IplImage( image.Size, image.Depth, 1 );
output.Set( CvColor.Black );
CvPoint[][] ArrayOfPoints = listOfPoints.ToArray();
output.FillPoly( ArrayOfPoints, CvColor.White );
return output;
}
为什么我总是得到 "contour of edges" 而不是区域轮廓?
结果如下:
enter image description here
试试这个。
IplImage input = new IplImage(@"C:\Users396600\Downloads\cont.jpg");
IplImage gray = new IplImage(input.Size, BitDepth.U8, 1);
IplImage invert = gray.Clone();
input.CvtColor(gray, ColorConversion.BgrToGray);
gray.Threshold(invert, 70, 255, ThresholdType.BinaryInv);
RemoveNoise(invert, 150);
private IplImage RemoveNoise(IplImage image, int minArea)
{
IplImage output = new IplImage(image.Size, BitDepth.U8, 3);//image.Depth, 1);
output.Set(CvColor.Black);
CvSeq<CvPoint> contoursRaw;
using (CvMemStorage storage = new CvMemStorage())
{
//find contours
Cv.FindContours(image, storage, out contoursRaw, CvContour.SizeOf, ContourRetrieval.Tree, ContourChain.ApproxSimple);
//Taken straight from one of the OpenCvSharp samples
using (CvContourScanner scanner = new CvContourScanner(image, storage, CvContour.SizeOf, ContourRetrieval.Tree, ContourChain.ApproxSimple))
{
foreach (CvSeq<CvPoint> c in scanner)
{
//Some contours are negative so make them all positive for easy comparison
double area = Math.Abs(c.ContourArea());
//Uncomment below to see the area of each contour
//Console.WriteLine(area.ToString());
if (area >= minArea)
{
List<CvPoint[]> points = new List<CvPoint[]>();
List<CvPoint> point = new List<CvPoint>();
foreach (CvPoint p in c.ToArray())
point.Add(p);
points.Add(point.ToArray());
//Use FillPoly instead of DrawContours as requested
output.FillPoly(points.ToArray(), CvColor.Red, LineType.AntiAlias);
//-1 means fill the polygon
//output.DrawContours(c, CvColor.White, CvColor.Green, 0, -1, LineType.AntiAlias);
//Uncomment two lines below to see contours being drawn gradually
//Cv.ShowImage("Window", output);
//Cv.WaitKey();
}
}
}
}
output.SaveImage("output.png");
return output;
}
根据要求解释这里是秘诀。
- 反转图像有助于正确找到轮廓。 FindContour 想要在黑色背景上找到白色对象。
- ContourArea() 返回负值,因此 Math.Abs() 有助于过滤到您想要的内容。
- 如果传递的厚度为 -1,DrawContour() 函数将填充轮廓。
其他一切都与 OpenCvSharp 下载中提供的示例非常相似。希望这有帮助。
编辑:通过另一个渠道,作者要求能够使用 FillPoly 而不是 DrawContours,因此已更新示例代码以反映这一点。
我正在尝试实现一个在二值图像中查找轮廓并滤除小轮廓的函数。
这是我的代码和示例图片。这是一个超级简单的功能,可以去除小面积的斑点。但是我一直得到 "contours of edges" 而不是区域的轮廓。 :S
private IplImage RemoveNoise( IplImage image, int minArea )
{
List<CvPoint[]> listOfPoints = new List<CvPoint[]>();
CvSeq<CvPoint> contoursRaw;
List<ContourData> contours = new List<ContourData>();
using( CvMemStorage storage = new CvMemStorage() )
{
//find contoures
//Cv.FindContours( image, storage, out contoursRaw );
Cv.FindContours( image, storage, out contoursRaw, CvContour.SizeOf, ContourRetrieval.Tree, ContourChain.ApproxSimple );
//contoursRaw = Cv.ApproxPoly( contoursRaw, CvContour.SizeOf, storage, ApproxPolyMethod.DP, 3, true );
while( contoursRaw != null )
{
CvSeq<CvPoint> result = contoursRaw;
double area = Cv.ContourArea( result );
//filter out small regions
if( area >= minArea )
{
List<CvPoint> points = new List<CvPoint>();
int i = 0;
while( result[ i ] != null )
{
points.Add( new CvPoint( result[ i ].Value.X, result[ i ].Value.Y ) );
i++;
}
listOfPoints.Add( points.ToArray() );
}
contoursRaw = contoursRaw.HNext;
}
}
// draw large regions
IplImage output = new IplImage( image.Size, image.Depth, 1 );
output.Set( CvColor.Black );
CvPoint[][] ArrayOfPoints = listOfPoints.ToArray();
output.FillPoly( ArrayOfPoints, CvColor.White );
return output;
}
为什么我总是得到 "contour of edges" 而不是区域轮廓?
结果如下:
enter image description here
试试这个。
IplImage input = new IplImage(@"C:\Users396600\Downloads\cont.jpg");
IplImage gray = new IplImage(input.Size, BitDepth.U8, 1);
IplImage invert = gray.Clone();
input.CvtColor(gray, ColorConversion.BgrToGray);
gray.Threshold(invert, 70, 255, ThresholdType.BinaryInv);
RemoveNoise(invert, 150);
private IplImage RemoveNoise(IplImage image, int minArea)
{
IplImage output = new IplImage(image.Size, BitDepth.U8, 3);//image.Depth, 1);
output.Set(CvColor.Black);
CvSeq<CvPoint> contoursRaw;
using (CvMemStorage storage = new CvMemStorage())
{
//find contours
Cv.FindContours(image, storage, out contoursRaw, CvContour.SizeOf, ContourRetrieval.Tree, ContourChain.ApproxSimple);
//Taken straight from one of the OpenCvSharp samples
using (CvContourScanner scanner = new CvContourScanner(image, storage, CvContour.SizeOf, ContourRetrieval.Tree, ContourChain.ApproxSimple))
{
foreach (CvSeq<CvPoint> c in scanner)
{
//Some contours are negative so make them all positive for easy comparison
double area = Math.Abs(c.ContourArea());
//Uncomment below to see the area of each contour
//Console.WriteLine(area.ToString());
if (area >= minArea)
{
List<CvPoint[]> points = new List<CvPoint[]>();
List<CvPoint> point = new List<CvPoint>();
foreach (CvPoint p in c.ToArray())
point.Add(p);
points.Add(point.ToArray());
//Use FillPoly instead of DrawContours as requested
output.FillPoly(points.ToArray(), CvColor.Red, LineType.AntiAlias);
//-1 means fill the polygon
//output.DrawContours(c, CvColor.White, CvColor.Green, 0, -1, LineType.AntiAlias);
//Uncomment two lines below to see contours being drawn gradually
//Cv.ShowImage("Window", output);
//Cv.WaitKey();
}
}
}
}
output.SaveImage("output.png");
return output;
}
根据要求解释这里是秘诀。
- 反转图像有助于正确找到轮廓。 FindContour 想要在黑色背景上找到白色对象。
- ContourArea() 返回负值,因此 Math.Abs() 有助于过滤到您想要的内容。
- 如果传递的厚度为 -1,DrawContour() 函数将填充轮廓。
其他一切都与 OpenCvSharp 下载中提供的示例非常相似。希望这有帮助。
编辑:通过另一个渠道,作者要求能够使用 FillPoly 而不是 DrawContours,因此已更新示例代码以反映这一点。