2

В этом проекте, я должен соответствовать много различных изображений листьев (по одному за раз) внутри эллипса, чтобы получить следующую информацию:OpenCV - Установка листьев внутри контура fitEllipse()

1) Соотношение сторон;

2) Средний диаметр, измеряющий диаметр на каждые 2 градуса;

3) Радиус действия;

4) округлость;

5) Средний Фере.

Проблема заключается в следующем: когда я пытаюсь поместить объект внутри эллипса, эллипс действительно нарисован внутри него, и из-за этого высота и ширина объекта неверны. Я не могу понять, что я делаю неправильно, так как я использую 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

С или без контуров, конечный результат всегда один и тот же.


EDIT 2:

После решения данного пользователя sietschie, я пытался реализовать свой код, который доступен here, но получается, что я всегда получаю ошибку при линия 105. сообщение, показанная в командной строке:

OpenCV Ошибка: Неправильный размер входного массива (количество точек должно быть> = 5) в cvFitEllipse2, файл с: \ \ строит 2_4_Pac kSlave-win64-VC12-Shared \ 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: неправильный размер входного массива (количество точек должно быть> = 5) в cvFitEllipse2, файл C: \ builds \ 2_4_PackSlave-win64-vc12-shared \ opencv \ modules \ imgproc \ src.cpp, строка 799 У вас есть идеи, как решить эту проблему? Какую версию OpenCV вы используете? Шахта - 2.4.10. Единственная разница между нашими кодами заключается в том, что я использую путь к конкретному изображению вместо того, чтобы вручную передавать путь с помощью командной строки. – Nicholas