我正在C#EmguCV项目中进行轮廓查找。对于这个项目,我必须获得轮廓层次数据。我以前在C ++ OpenCV项目中使用过这个方法,所以我理解FindContours
方法和Hierarchy
信息的工作原理。请在下面找到相关代码:
Mat grayImage = new Mat(originalImage.Size, originalImage.Depth, 1);
Mat edges = new Mat(originalImage.Size, originalImage.Depth, 1);
CvInvoke.CvtColor(originalImage, grayImage, ColorConversion.Bgr2Gray);
CvInvoke.Canny(grayImage, edges, 100, 200, 3);
var contours = new VectorOfVectorOfPoint();
Mat hierarchy = new Mat();
CvInvoke.FindContours(edges, contours, hierarchy, RetrType.Tree, ChainApproxMethod.ChainApproxSimple);
当我运行此代码时,可以按预期找到轮廓。此外,Hierarchy Mat
对象似乎按预期填充,即1 x size of outputResult x 4
(参见下图),但此对象中的数据仍为null
:
Screenshot of hierarchy mat object
我无法找到有关如何从此对象中提取层次结构轮廓(树)数据的答案。我在other StackOverflow posts (see also the comments)看到其他人一直在努力和/或EmguCV 3.x库中可能存在错误,但我找不到答案。
我的问题是:Hierarchy Mat
对象中的数据字段是null
是否正常?
Mat
对象中提取相关的分层数据?null
的错误?例如是否可以降级到EmguCV 2.x?答案 0 :(得分:1)
也许已经晚了,但是......
你可以试试这个:
using (VectorOfVectorOfPoint vecVecPts2 = new VectorOfVectorOfPoint())
{
int[,] hierarchy = CvInvoke.FindContourTree(img3, vecVecPts2,
ChainApproxMethod.ChainApproxNone);
}
或: more info
/// >>>>Based on [joshuanapoli] answer<<<
/// <summary>
/// Get a neighbor index in the heirarchy tree.
/// </summary>
/// <returns>
/// A neighbor index or -1 if the given neighbor does not exist.
/// </returns>
//public int Get(HierarchyIndex component, int index)
//public int GetHierarchy(Mat Hierarchy, int contourIdx, int component)
public int[] GetHierarchy(Mat Hierarchy, int contourIdx)
{
int[] ret = new int[] { };
if (Hierarchy.Depth != Emgu.CV.CvEnum.DepthType.Cv32S)
{
throw new ArgumentOutOfRangeException("ContourData must have Cv32S hierarchy element type.");
}
if (Hierarchy.Rows != 1)
{
throw new ArgumentOutOfRangeException("ContourData must have one hierarchy hierarchy row.");
}
if (Hierarchy.NumberOfChannels != 4)
{
throw new ArgumentOutOfRangeException("ContourData must have four hierarchy channels.");
}
if (Hierarchy.Dims != 2)
{
throw new ArgumentOutOfRangeException("ContourData must have two dimensional hierarchy.");
}
long elementStride = Hierarchy.ElementSize / sizeof(Int32);
var offset0 = (long)0 + contourIdx * elementStride;
if (0 <= offset0 && offset0 < Hierarchy.Total.ToInt64() * elementStride)
{
var offset1 = (long)1 + contourIdx * elementStride;
var offset2 = (long)2 + contourIdx * elementStride;
var offset3 = (long)3 + contourIdx * elementStride;
ret = new int[4];
unsafe
{
//return *((Int32*)Hierarchy.DataPointer.ToPointer() + offset);
ret[0] = *((Int32*)Hierarchy.DataPointer.ToPointer() + offset0);
ret[1] = *((Int32*)Hierarchy.DataPointer.ToPointer() + offset1);
ret[2] = *((Int32*)Hierarchy.DataPointer.ToPointer() + offset2);
ret[3] = *((Int32*)Hierarchy.DataPointer.ToPointer() + offset3);
}
}
//else
//{
// return new int[] { };
//}
return ret;
}
答案 1 :(得分:0)
这对我有用:
Mat hierarchy = new Mat();
CvInvoke.FindContours(edges, contours, hierarchy, RetrType.Tree, ChainApproxMethod.ChainApproxSimple);
Array arr = hierarchy.GetData(true);
我将层次数据提取到dataGridView
dataGridView1.Columns.Add("n-cont", "n-cont");
dataGridView1.Columns.Add("next", "next");
dataGridView1.Columns.Add("prev", "prev");
dataGridView1.Columns.Add("f-child", "f-child");
dataGridView1.Columns.Add("parent", "parent");
for (int y = 0; y < hier.Cols; y++)
{
dataGridView1.Rows.Add(y.ToString(), arr.GetValue(0, y, 0).ToString(), arr.GetValue(0, y, 1).ToString()
, arr.GetValue(0, y, 2).ToString(), arr.GetValue(0, y, 3).ToString());
}
层次结构Mat中的数据被放入(1行,用于cols的n个(轮廓数),4个通道 (下一个,previos,第一个孩子,父母)