hierarchy of findContours

2,948 views
Skip to first unread message

Joram

unread,
Nov 30, 2011, 4:35:28 AM11/30/11
to android-opencv
After searching a lot with Google I finally found how to use the
contours from the findContours function. But what i can't find is how
to use the hierarchy mat. Has anyone got an example? I want to detect
if a contour has any inner contours.

Hardik

unread,
Nov 30, 2011, 4:41:54 AM11/30/11
to android...@googlegroups.com
Hi Joram,

pls look this code...hope it will help you...        

            List<Mat> contour = new ArrayList<Mat>();

            Mat matObject = new Mat(new Size(576,648),CvType.CV_8UC1,new Scalar(0));

            //find contours and store into list as Mat
            Imgproc.findContours(diff,contour,matObject,Imgproc.CHAIN_APPROX_SIMPLE, Imgproc.RETR_LIST);


Thanks
--
Regards,

Pansuria Hardik

Sourcebits  Inc.



Joram

unread,
Nov 30, 2011, 4:56:26 AM11/30/11
to android...@googlegroups.com
Hi,

Ok, my code is very similar only I didn't had the size and type of your matObject set. But how to use that matObject, how can I see if a contour is a child of an other contour or if a contour has a child?
My current code:
[code]
Imgproc.threshold(mGray, mExtra, 100, 255, Imgproc.THRESH_BINARY);
List<Mat> contours = new ArrayList<Mat>();
Mat hierarchy = new Mat(new Size(320,240),CvType.CV_8UC1,new Scalar(0));
Imgproc.findContours(mExtra, contours, hierarchy, 3, 2);
Imgproc.cvtColor(mExtra, mRgba, Imgproc.COLOR_GRAY2RGBA, 4);

if (contours.size() > 2 && contours.size()  < 20)
{
for (int i = 0; i < contours.size(); i++)
{
Mat c = contours.get(i); 
int num = (int) c.total(); 
int buff[] = new int[num*2]; // [x1, y1, x2, y2, ...] 
c.get(0, 0, buff);
List<Point> points = new ArrayList<Point>(num);
for (int p = 0; p < num*2; p+=2)
{
points.add(new Point(buff[p], buff[p+1]));
}

Rect rect = Imgproc.boundingRect(points);
Scalar lcolor;
//if (hierarchy == -1)
// lcolor = new Scalar(255,0,0);
//else
lcolor = new Scalar(0,0,255);
Core.line(mRgba, new Point(rect.x, rect.y), new Point(rect.x+rect.width, rect.y+rect.height), lcolor);
Log.i("vision", "draw line through contour: "+num+" points, ("+rect.x+","+rect.y+"), "+rect.width+"x"+rect.height);
}
}
[/code]

Joram

Rafa Ortega

unread,
Nov 30, 2011, 7:49:00 AM11/30/11
to android...@googlegroups.com
In order to draw the contours found you can use the function 
public static void drawContours(Mat image, java.util.List<Mat> contours, int contourIdx, Scalar color, int thickness, int lineType, Mat hierarchy, int maxLevel, Point offset)
in the Imgproc class, if you want all the contours to be drawn just pass a negative number in the contourIdx parameter.

2011/11/30 Joram <mic...@gmail.com>

Joram

unread,
Nov 30, 2011, 8:58:51 AM11/30/11
to android...@googlegroups.com
I understand that is possible, but not what I was looking for. 

In the c++ opencv you have:
"hiararchy – Optional output vector containing information about the image topology. It has as many elements as the number of contours. For each contour contours[i] , the elements hierarchy[i][0] , hiearchy[i][1] , hiearchy[i][2] , and hiearchy[i][3] are set to 0-based indices in contours of the next and previous contours at the same hierarchical level: the first child contour and the parent contour, respectively. If for a contour i there are no next, previous, parent, or nested contours, the corresponding elements of hierarchy[i] will be negative."

That is what I want, the information so I can check the for child or parent contours myself.

As I discovered the hierarchy.total() is the exact length as the number of contours but when I try to retreive the information as i do with the contours( hierarchy.get(0, 0, buff_h); ) it gives an error, UnsupportedOperationException.

Joram

Andrey Pavlenko

unread,
Dec 1, 2011, 3:10:14 AM12/1/11
to android...@googlegroups.com
The hierarchy is a Mat (1xN) of type CV_32SC4.
So to get its values you need an int[]:
    int iBuff[] = new int[ (int) (h.total() * h.channels()) ]; // [ Contour0 (next sibling num, previous sibling num, 1st child num, parent num), Contour1(...), ...
    h.get(0, 0, iBuff);

Joram

unread,
Dec 4, 2011, 10:26:56 AM12/4/11
to android...@googlegroups.com
Thanks that works!
Reply all
Reply to author
Forward
0 new messages