根の写真をもとに、根の量がどれくらいあるのかを調べる方法として、面積で計算するような場合は根の太さに影響されますが、それに影響されずに長さを調べたいと思うのなら、輪郭線を抽出し、その長さを求めた後に、その長さを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); }