2

在這個項目的輪廓內配合葉子,我必須適應橢圓內許多不同的葉片圖像(一次一個),以獲得以下信息:的OpenCV - fitEllipse()

1)長寬比; 2)平均直徑,每2度測量直徑;

3)半徑比;

4)圓度;

5)意味着Feret。

問題是:當我嘗試在橢圓內部擬合對象時,橢圓實際上是在其內部繪製的,因此,對象的高度和寬度都是錯誤的。 我不明白我做錯了什麼,因爲我使用findNonZero()來獲取實際上有像素的圖像的部分。

下面是結果:enter image description here

這是我的代碼:

/*Load the image*/ 
Mat img_bgr = imread("image path", 1); 
if (img_bgr.empty()){ 
    cout << "No image found..." << endl; 
    return -1; 
} 

/*Display the image*/ 
namedWindow("Original Image", WINDOW_NORMAL); 
imshow("Original Image", img_bgr); 
waitKey(0); 

/*Conversion to HSV*/ 
Mat img_hsv; 
cvtColor(img_bgr, img_hsv, CV_BGR2HSV); 

/*Extracting colors - HSV*/ 
Mat yellow, green, brown; 

//Yellow 
inRange(img_hsv, Scalar(25, 80, 80), Scalar(36, 255, 255), yellow); 

//Green 
inRange(img_hsv, Scalar(37, 80, 80), Scalar(70, 255, 255), green); 

//Brown 
inRange(img_hsv, Scalar(10, 80, 80), Scalar(30, 200, 200), brown); 


/*Finding Contours of the Thresholded images*/ 
vector<std::vector<Point>>green_cnt; 
vector<std::vector<Point>>yellow_cnt; 
vector<std::vector<Point>>brown_cnt; 

//Green Contour 
findContours(green, green_cnt, CV_RETR_TREE, CV_CHAIN_APPROX_NONE); 

//Draw the Contours - Green 
Mat green_cnt_draw(green.size(), CV_8UC3, Scalar(0, 0, 0)); 
Scalar green_cnt_colors[3]; 
green_cnt_colors[0] = Scalar(0, 255, 0); 
green_cnt_colors[1] = Scalar(0, 255, 0); 
green_cnt_colors[2] = Scalar(0, 255, 0); 

for (size_t idx_green = 0; idx_green < green_cnt.size(); idx_green++){ 
    drawContours(green_cnt_draw, green_cnt, idx_green, green_cnt_colors[idx_green % 3]); 
} 

namedWindow("Green - Contours", CV_WINDOW_NORMAL); 
imshow("Green - Contours", green_cnt_draw); 
waitKey(0); 

//Yellow Contour 
findContours(yellow, yellow_cnt, CV_RETR_TREE, CV_CHAIN_APPROX_NONE); 

//Draw the Contours - Yellow 
Mat yellow_cnt_draw(yellow.size(), CV_8UC3, Scalar(0, 0, 0)); 
Scalar yellow_cnt_colors[3]; 
yellow_cnt_colors[0] = Scalar(0, 255, 255); 
yellow_cnt_colors[1] = Scalar(0, 255, 255); 
yellow_cnt_colors[2] = Scalar(0, 255, 255); 

for (size_t idx_yellow = 0; idx_yellow < yellow_cnt.size(); idx_yellow++){ 
    drawContours(yellow_cnt_draw, yellow_cnt, idx_yellow, yellow_cnt_colors[idx_yellow % 3]); 
} 

namedWindow("Yellow - Contours", CV_WINDOW_NORMAL); 
imshow("Yellow - Contours", yellow_cnt_draw); 
waitKey(0); 

//Brown Contour 
findContours(brown, brown_cnt, CV_RETR_TREE, CV_CHAIN_APPROX_NONE); 

//Draw the Contours - Brown 
Mat brown_cnt_draw(brown.size(), CV_8UC3, Scalar(0, 0, 0)); 
Scalar brown_cnt_colors[3]; 
brown_cnt_colors[0] = Scalar(42, 42, 165); 
brown_cnt_colors[1] = Scalar(42, 42, 165); 
brown_cnt_colors[1] = Scalar(42, 42, 165); 

for (size_t idx_brown = 0; idx_brown < brown_cnt.size(); idx_brown++){ 
    drawContours(brown_cnt_draw, brown_cnt, idx_brown, brown_cnt_colors[idx_brown % 3]); 
} 

namedWindow("Brown - Contours", CV_WINDOW_NORMAL); 
imshow("Brown - Contours", brown_cnt_draw); 
waitKey(0); 
destroyAllWindows; 

// logical OR mask 
Mat1b mask = yellow | green | brown; 

// Find non zero pixels 
vector<Point> pts; 

findNonZero(mask, pts); 

// Compute ellipse 
RotatedRect elipse = fitEllipse(pts); 

//ELLIPSE - Heigth, Width and Center of Mass 
cout << "ELLIPSE:" << endl; 
cout << "\nHeight and Width: " << elipse.size; //Height and Width 
cout << "\nCenter of Mass: " << elipse.center << endl; //Center of mass (probably given in X and Y coordinates) 

// Show Ellipse 
ellipse(img_bgr, elipse, Scalar(0, 0, 255), 3); 
namedWindow("Ellipse", CV_WINDOW_NORMAL); 
imshow("Ellipse", img_bgr); 

waitKey(0); 
destroyAllWindows; 

return 0; 

EDIT 1:

響應於由用戶進行的問題,我我們決定編輯主帖,而不是簡單地回覆沒有新圖片來說明情況。

的findCountours後掩碼()看起來是這樣的: enter image description here

,沒有它: enter image description here

隨着我們沒有輪廓,最後的結果總是相同的。


編輯2:

繼用戶sietschie給出的解決方案,我試圖實現他的代碼,這是可以here,但事實證明,我總是得到一個錯誤在命令行中所示的線105的消息是:

OpenCV的錯誤:輸入數組的大小不正確(點數應> = 5)在cvFitEllipse2,文件C:\建立\ 2_4_Pac kSlave-Win64上-VC12共享\ OpenCV的\模塊\ imgproc \ src.cpp,線799

我仍然想不通我做錯了什麼,因爲這是同來,他寫道而工作,因爲他表現結果。 爲了試圖瞭解發生了什麼,我得到的輪廓(線104)的圖像,它實際上看起來很奇怪:

enter image description here

+0

難道你看看4席會是什麼樣這一行後:'Mat1b面膜=黃色|綠色|棕色;'? ** findContours(...)**以未定義的方式修改輸入圖像。 –

回答

0

的問題是,您嘗試使用適合橢圓面具的所有白色像素。這導致了一個橢圓,它試圖最小化到所有白色像素的距離。你想要的是一個橢圓,可以最大限度地減少到蒙板輪廓的距離。像這樣:

std::vector< std::vector<cv::Point> > contours; 
cv::Mat tmp = mask.clone(); 
cv::findContours(tmp, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE); 
cv::RotatedRect elipse = cv::fitEllipse(contours[0]); 

除了莖位於的區域之外,這會導致更好的近似。

+0

我正試圖實現您的解決方案,但代碼並未編譯。 Visual Studio顯示代碼爲0x000007FEFD7A965D的錯誤。你是否更改了代碼的其他部分,或者只是添加了這部分以獲得上面顯示的結果?更確切地說,錯誤發生在最後一行。 – Nicholas

+0

這就是我所添加的。可以肯定的是,[這裏](http://pastebin.com/XikhXTW9)是我使用的整個文件。我在這裏和那裏評論了一些東西。但沒有什麼會影響它的工作方式。 – sietschie

+0

我試圖從你發佈的鏈接運行你的代碼,但它還沒有編譯。 我在命令行注意到以下消息: OpenCV錯誤:在cvFitEllipse2文件C:\ builds \ 2_4_PackSlave-win64-vc12-shared \ opencv中輸入數組的大小錯誤(點數應大於等於5) \ modules \ imgproc \ src.cpp,line 799 您對如何解決此問題有任何想法嗎? 你使用的是什麼版本的OpenCV?我的是2.4.10。 我們的代碼之間的唯一區別是我使用的是特定圖像的路徑,而不是使用命令行手動傳遞路徑。 – Nicholas