Emgu CV 3 findContours and hierarchy parameter of type Vec4i equivalent?

cdahms picture cdahms · Dec 6, 2015 · Viewed 10.9k times · Source

I'm attempting to translate the following OpenCV C++ code into 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);

I can find some Emgu CV 3 examples that use null for the 3rd parameter to findContours, for example doing it that way here would be a Visual Basic translation:

Dim contours As New VectorOfVectorOfPoint()

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

Which works if the hierarchy parameter is not needed, but what if it is? I can't seem to figure the Emgu CV 3 syntax equivalent for the C++ line

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

Anybody else gotten this to work? Any help would be appreciated.

Answer

joshuanapoli picture joshuanapoli · Sep 26, 2016

Pass a default-constructed Mat to get the hierarchy.

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

You can access the hierarchy data using the 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