根の写真をもとに、根の量がどれくらいあるのかを調べる方法として、面積で計算するような場合は根の太さに影響されますが、それに影響されずに長さを調べたいと思うのなら、輪郭線を抽出し、その長さを求めた後に、その長さを1/2倍するという方法があるでしょう。この方法は根が十分に細いことから利用できる計算方法です。面積計算と同様に、はじめにカラー画像をcvtColor関数によりグレースケールに変換し、それをthreshold関数により二値化します。続いてfindcontour関数により輪郭を検出し、その長さを計算し出力します。findcontour関数のオプションのCV_RETR_LISTはすべての輪郭線を検出しますが、検出した輪郭線のデータ保持を階層構造を持たせないで保持することを意味します。 CV_CHAIN_APPROX_NONEはすべての輪郭点を完全に格納することを意味します。すなわち、この手法により格納された任意の隣り合う2点は互いに8近傍に存在します。よって、隣接する輪郭線要素のx、yのどちらかが等しい時には輪郭線要素の長さは1、どちらも異なる場合には√2となります。
このソースコードはGNU GPLライセンスにより保護されています。GNU GPLライセンスの条項に関してはこちらをご覧ください。
//
// 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);
}