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