Detect Contours

When you want to measure the length of root of plants, one solution is detecting and measureing the contours. When you calculate the amount of root by measuring the area, the result is affected by the thickness of root. To deny this effect, you can detect contours and calculate the length of it. Like the area calculation, at firtst, converts the image to gray scale by cvtColor function. Then it it will be binarized by the threshold function. Then it detects the outline by findcontour function, and then output calculated contour length. The option of findcontour function, CV_RETR_LIST means it detects all of the outline, but means that it hold data without a hierarchical structure. CV_CHAIN_APPROX_NONE means that it completely stores all of the contour points. In other words, it exists in any of eight adjacent to each other adjacent two points that are stored by this method. Thus, the length of the contour line element is 1 when x or y is same between the two neiboring points of contour, otherwise, it is √2.

root root_contour

Source Code

This source code is protected by the GNU GPL license. Please visit here for the terms of the GNU GPL license.

//
//  contour length
//
//  Copyright 2015 Yuki Mochizuki
//

#include <iostream>
#include <stdio.h>
#include "opencv/cv.h"
#include "opencv/highgui.h"
#include <cmath>

using namespace std;
using namespace cv;


int main()
{
    Mat src_img = imread("/Users/YM/Desktop/root.jpg");

    Mat gray_img;
    cvtColor(src_img, gray_img, CV_BGR2GRAY);
    
    Mat bin_img;
    threshold(gray_img, bin_img, 0, 255, THRESH_BINARY|THRESH_OTSU);
    
    bin_img = ~bin_img;
    imshow("bin", bin_img);
    cvNamedWindow("bin", CV_WINDOW_AUTOSIZE);
    
    vector<vector<Point>> contours;
    findContours(bin_img, contours, CV_RETR_LIST, CV_CHAIN_APPROX_NONE);
    double contour_len=0;
    drawContours(bin_img,contours,-1,Scalar(255,125,0),1,8);
    for(int i = 0; i < contours.size(); ++i) {
        double x=contours.at(i).at(0).x;
        double y=contours.at(i).at(0).y;
        
        size_t count = contours[i].size();
        for(int ii=1;ii<count;ii++){
            if(contours.at(i).at(ii).x==x || contours.at(i).at(ii).y==y)contour_len+=1;
            else contour_len+=1.41421356;
            x=contours.at(i).at(ii).x;
            y=contours.at(i).at(ii).y;
        }
    }
    
    imshow("bin", bin_img);
    cout<<"total contours length; "<<contour_len<<endl;
    cout<<"estimated root length; "<<contour_len/2<<endl;
    
    cvWaitKey(0);
}