C# - Emgu CV - данные иерархии FindContours всегда нулевые

Я работаю над нахождением контура в проекте 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:

Снимок экрана: иерархический объект

Я не смог найти ответ о том, как извлечь данные контура (дерева) иерархии из этого объекта. В других сообщениях Stackru (см. Также комментарии) я видел, что другие боролись и / или что в библиотеке EmguCV 3.x могут быть ошибки, но я не смог найти ответ.

Мой вопрос таков: это нормально, что поле данных в Hierarchy Mat объект null?

  • Если так: как мне извлечь соответствующие иерархические данные из этого Mat объект?
  • Если нет: есть ли способ обойти эту ошибку, когда иерархические данные null? Можно ли, например, перейти на версию EmguCV 2.x?

1 ответ

Может быть, уже поздно, но...

Вы можете попробовать это:

using (VectorOfVectorOfPoint vecVecPts2 = new VectorOfVectorOfPoint())
{

    int[,] hierarchy = CvInvoke.FindContourTree(img3, vecVecPts2, 
    ChainApproxMethod.ChainApproxNone);
}

или: Emgu CV 3 findContours и параметр иерархии типа Vec4i эквивалентны?

        /// >>>>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;
        }

Это работает для меня:

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 ряд, n (количество контуров) для столбцов, 4 канала (следующий, предыдущий, первый дочерний, родительский)

Другие вопросы по тегам