【问题标题】:Emgu CV 3 findContours and hierarchy parameter of type Vec4i equivalent?Emgu CV 3 findContours 和 Vec4i 类型的层次参数等效?
【发布时间】:2015-12-06 17:13:36
【问题描述】:

我正在尝试将以下 OpenCV C++ 代码翻译成 Emgu CV 3:

std::vector<std::vector<cv::Point> > contours;
std::vector<cv::Vec4i> v4iHierarchy;

cv::findContours(imgThreshCopy, contours, v4iHierarchy, cv::RETR_TREE, cv::CHAIN_APPROX_SIMPLE);

我可以找到一些 Emgu CV 3 示例,这些示例使用 null 作为 findContours 的第三个参数,例如,在这里这样做将是 Visual Basic 翻译:

Dim contours As New VectorOfVectorOfPoint()

CvInvoke.FindContours(imgThreshCopy, contours, Nothing, RetrType.Tree, ChainApproxMethod.ChainApproxSimple)

如果不需要层次结构参数,哪种方法有效,但如果需要呢?我似乎无法计算出与 C++ 行等效的 Emgu CV 3 语法

std::vector<cv::Vec4i> v4iHierarchy;

还有其他人让这个工作吗?任何帮助将不胜感激。

【问题讨论】:

    标签: emgucv


    【解决方案1】:

    传递默认构造的Mat 以获取层次结构。

    var VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint();
    var Mat hierarchy = new Mat();
    CvInvoke.FindContours(
        image,
        contours,
        hierarchy,
        RetrType.Ccomp,
        ChainApproxMethod.ChainApproxSimple
        );
    
    Console.WriteLine("contours.Size: " + contours.Size);
    Console.WriteLine("hierarchy.Rows: " + hierarchy.Rows);
    Console.WriteLine("hierarchy.Cols: " + hierarchy.Cols);
    Console.WriteLine("hierarchy.Depth: " + hierarchy.Depth);
    Console.WriteLine("hierarchy.NumberOfChannels: " + hierarchy.NumberOfChannels);
    
    // Example Output:
    // contours.Size: 4391
    // hierarchy.Rows: 1
    // hierarchy.Cols: 4391
    // hierarchy.Depth: Cv32S
    // hierarchy.NumberOfChannels: 4
    

    您可以使用 Mat DataPointer 访问层次结构数据:

        /// <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)
        {
            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 offset = (long)component + index * elementStride;
            if (0 <= offset && offset < Hierarchy.Total.ToInt64() * elementStride)
            {
                unsafe
                {
                    return *((Int32*)Hierarchy.DataPointer.ToPointer() + offset);
                }
            }
            else
            {
                return -1;
            }
        }
    

    https://gist.github.com/joshuanapoli/8c3f282cece8340a1dd43aa5e80d170b

    【讨论】:

    • 嗨,我坚持迭代数据。假设我想知道 50 号轮廓值。我怎样才能得到这些数据。
    • Yusuf,我添加了一个如何访问轮廓层次结构数据的示例。
    • 非常感谢。我已经用 Mat 类的字节数组完成了。
    【解决方案2】:

    EmguCV 开始为 FindContours 使用 VectorOfVectorPoint,但并没有真正更新他们的代码以使其正常工作。请参阅下面的工作示例:

        /// <summary>
        /// Find contours using the specific memory storage
        /// </summary>
        /// <param name="method">The type of approximation method</param>
        /// <param name="type">The retrieval type</param>
        /// <param name="stor">The storage used by the sequences</param>
        /// <returns>
        /// Contour if there is any;
        /// null if no contour is found
        /// </returns>
        public static VectorOfVectorOfPoint FindContours(this Image<Gray, byte> image, ChainApproxMethod method = ChainApproxMethod.ChainApproxSimple,
            Emgu.CV.CvEnum.RetrType type = RetrType.List) {
            //Check that all parameters are valid.
            VectorOfVectorOfPoint result = new VectorOfVectorOfPoint();
    
            if (method == Emgu.CV.CvEnum.ChainApproxMethod.ChainCode) {
                throw new ColsaNotImplementedException("Chain Code not implemented, sorry try again later");
            }
    
            CvInvoke.FindContours(image, result, null, type, method);
            return result;
        }
    

    这将返回一个 VectorOfVectorPoint,它实现了 IInputOutputArray、IOutputArray、IInputArrayOfArrays 和 IInputArray。我不确定你需要对轮廓做什么,但这里有一个如何获取每个边界框的示例。我们还做一些其他事情,所以请告诉我您的需求,我可以帮助您。

            VectorOfVectorOfPoint contours = canvass2.FindContours(ChainApproxMethod.ChainApproxSimple, RetrType.Tree);
            int contCount = contours.Size;
            for (int i = 0; i < contCount; i++) {
                using (VectorOfPoint contour = contours[i]) {
                    segmentRectangles.Add(CvInvoke.BoundingRectangle(contour));
                    if (debug) {
                        finalCopy.Draw(CvInvoke.BoundingRectangle(contour), new Rgb(255, 0, 0), 5);
                    }
                }
            }
    

    【讨论】:

      【解决方案3】:

      你可以简单地创建一个

      矩阵

      然后将您的 Mat 对象数据复制到该矩阵中。请参阅下面的示例:

        Mat hierarchy = new Mat();
        CvInvoke.FindContours(imgThreshCopy, contours, hierarchy , RetrType.Tree,ChainApproxMethod.ChainApproxSimple);
      
        Matrix<int> matrix = new Matrix<int>(hierarchy.Rows, hierarchy.Cols,hierarchy.NumberOfChannels);
        hierarchy.CopyTo(matrix);
      

      数据可以在

      中访问

      矩阵.数据

      祝你好运。 H

      【讨论】:

        猜你喜欢
        • 2017-05-24
        • 1970-01-01
        • 2013-12-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-02-15
        • 1970-01-01
        相关资源
        最近更新 更多