Эмгу CV 3 findContours и параметр иерархии типа Vec4i эквивалентны?

Я пытаюсь перевести следующий код 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 для 3-го параметра для findContours, например, если сделать это таким образом, это будет переводом Visual Basic:

Dim contours As New VectorOfVectorOfPoint()

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

Что работает, если параметр иерархии не нужен, но что, если он есть? Я не могу понять эквивалент синтаксиса Emgu CV 3 для строки C++

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

Кто-нибудь еще получил это на работу? Любая помощь будет оценена.

3 ответа

Передайте конструкцию по умолчанию 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

EmguCV начал использовать VectorOfVectorPoint для FindContours, но на самом деле не обновил свой код для корректной работы с ним. Смотрите ниже рабочий пример:

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

Вы можете просто создать

матрица

затем скопируйте данные объекта 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);

Данные могут быть доступны в

matrix.Data

Удачи. ЧАС

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