2016-04-17 4 views
0

Я пытаюсь найти значения для Height и Width для восстановления Aspect Ration объекта, используя контур изображения с приведенным ниже кодом, но не имеющий успеха, поскольку код создает много прямоугольников по всему изображению, когда я намерен создать единый прямоугольник вокруг объекта. Я пытаюсь создать этот прямоугольник, потому что я не знаю, есть ли другой способ получить Height и Width (или даже Aspect Ratio), кроме этого.OpenCV - Поиск высоты и ширины контурного изображения

*** RNG rng (12345); // Глобальная переменная используется для рисования прямоугольников и кругов для контуров изображений.

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

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

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

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

//Yellow 
inRange(img_hsv, Scalar(25, 0, 0), Scalar(36, 255, 255), yellow); //until 33 - consider "yellow" - from there up to 36 - consider for chlorosis 
imwrite("c:\\test\\results\\yellow.jpg", yellow); 

//Green 
inRange(img_hsv, Scalar(37, 0, 0), Scalar(70, 255, 255), green); //Consider lower as 37 
imwrite("c:\\test\\results\\green.jpg", green); 

//Brown 
inRange(img_hsv, Scalar(10, 0, 0), Scalar(20, 255, 255), brown); 
imwrite("c:\\test\\results\\brown.jpg", brown); 

namedWindow("Yellow", WINDOW_NORMAL); 
imshow("Yellow", yellow); 

namedWindow("Green", WINDOW_NORMAL); 
imshow("Green", green); 

namedWindow("Brown", WINDOW_NORMAL); 
imshow("Brown", 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); 

//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); 

//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); 


/*Creating rectangles around the contours*/ 
//Green 
vector<vector<Point>>green_contours_poly(green_cnt.size()); 
vector<Rect>green_boundRect(green_cnt.size()); 
vector<Point2f>green_center(green_cnt.size()); 
vector<float>green_radius(green_cnt.size()); 

for (int i = 0; i < green_cnt.size(); i++){ 
    approxPolyDP(Mat(green_cnt[i]), green_contours_poly[i], 3, true); 
    green_boundRect[i] = boundingRect(Mat(green_cnt[i])); 
    minEnclosingCircle((Mat)green_contours_poly[i], green_center[i], green_radius[i]); 
} 

//Green - Draw polygonal contour AND bounding rects + circles 
Mat green_drawRecAndCirc = Mat::zeros(green.size(), CV_8UC3); 
for (int i = 0; i < green_cnt.size(); i++){ 
    Scalar green_drawRecAndCircColor = Scalar(rng.uniform(0, 255), rng.uniform(0,255), rng.uniform(0,255)); 
    rectangle(green_drawRecAndCirc, green_boundRect[i].tl(), green_boundRect[i].br(), green_drawRecAndCircColor, 2, 8, 0); 
    //circle(green_drawRecAndCirc, green_center[i], (int)green_radius[i], green_drawRecAndCircColor, 2, 8, 0); 
} 
imwrite("c:\\testeimagem\\theeye\\resultados\\green_rectangle_and_circle.jpg", green_drawRecAndCirc); 

namedWindow("Green - Rectangle and Circle", CV_WINDOW_NORMAL); 
imshow("Green - Rectangle and Circle", green_drawRecAndCirc); 

/*Creating rectangles around the contours*/ 
//Yellow 
vector<vector<Point>>yellow_contours_poly(yellow_cnt.size()); 
vector<Rect>yellow_boundRect(yellow_cnt.size()); 
vector<Point2f>yellow_center(yellow_cnt.size()); 
vector<float>yellow_radius(yellow_cnt.size()); 

for (int i = 0; i < yellow_cnt.size(); i++){ 
    approxPolyDP(Mat(yellow_cnt[i]), yellow_contours_poly[i], 3, true); 
    yellow_boundRect[i] = boundingRect(Mat(yellow_cnt[i])); 
    minEnclosingCircle((Mat)yellow_contours_poly[i], yellow_center[i], yellow_radius[i]); 
} 

//Yellow - Draw polygonal contour AND bounding rects + circles 
Mat yellow_drawRecAndCirc = Mat::zeros(yellow.size(), CV_8UC3); 
for (int i = 0; i < yellow_cnt.size(); i++){ 
    Scalar yellow_drawRecAndCircColor = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255)); 
    rectangle(yellow_drawRecAndCirc, yellow_boundRect[i].tl(), yellow_boundRect[i].br(), yellow_drawRecAndCircColor, 2, 8, 0); 
    //circle(green_drawRecAndCirc, green_center[i], (int)green_radius[i], green_drawRecAndCircColor, 2, 8, 0); 
} 
waitKey(0); 
destroyAllWindows; 

return 0; 

Исходное изображение находится здесь:

enter image description here

И пример конечного результата здесь:

enter image description here

Я попытался примеры, описанные в следующей ссылке (OpenCV Bounding Box), но я не мог заставить его работать.


Изменить 2:

Так как я должен найти некоторые характеристики листа, которые я не могу найти с прямоугольником (например, соотношение сторон, средний диаметр, отношение радиуса, округлость и среднее Фере) я должен был изменить подход поиска листа от прямоугольника до эллипса. Дело в том, что эллипс рисуется внутри листовой интуиции контура.

Вот мой код:

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

/*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); 

// 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; 

Результат показан ниже:

enter image description here

Я не могу понять, что я делаю неправильно, так как я просто изменил код пользователя Miki дал, и это действительно работает отлично.

+1

Вам нужно * «одна большая коробка, чтобы управлять ими» * ... – karlphillip

+0

Привет Карл. Я вижу, что вы являетесь автором решения, упомянутого в ссылке, которую я опубликовал. Пожалуйста, не стесняйтесь делиться своим опытом и знаниями с нами. – Nicholas

ответ

1

Поскольку ваше изображение довольно простое (у вас есть плоский фон), вы можете упростить задачу поиска листа. Однако здесь я по-прежнему использую ваш подход, основанный на пороговых значениях HSV, которые, вероятно, будут более надежными в целом.


Чтобы найти ширину и высоту листа, вам в основном нужно найти его ограничивающий прямоугольник. Вам не нужно находить все контуры ваших цветных масок и объединять все ограничивающие прямоугольники.Но вы можете:

1) вычислить маску для желтого, зеленого и коричневого цвета (я sligthly изменил диапазоны для более значимых значений)

Желтые:

enter image description here

Зеленый:

enter image description here

Brown:

enter image description here

2) или же эти маски toghether

enter image description here

3) Найти все ненулевое пиксели 4) вычисления ограничивающего прямоугольника

enter image description here

Код:

#include <opencv2/opencv.hpp> 
#include <vector> 
#include <string> 

using namespace std; 
using namespace cv; 

int main() 
{ 
    // Load the image 
    Mat3b img_bgr = imread("path_to_image"); 
    if (img_bgr.empty()){ 
     cout << "No image..." << endl; 
     return -1; 
    } 

    // Convert to hsv 
    Mat3b img_hsv; 
    cvtColor(img_bgr, img_hsv, COLOR_BGR2HSV); 

    Mat1b 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); 

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

    // Find non zero pixels 
    vector<Point> pts; 
    findNonZero(mask, pts); 

    // Compute bounding box 
    Rect box = boundingRect(pts); 

    cout << "Width: " << box.width; 
    cout << "Height: " << box.height << endl; 

    // Show box 
    rectangle(img_bgr, box, Scalar(0,0,255), 3); 
    imshow("Box", img_bgr); 

    return 0; 
} 
+0

Не могли бы вы рассказать мне, как получить ширину и высоту листа? –

+0

он печатает несколько многозначных чисел –

+0

Это в конце кода, как показал Мики: '// Вычислить ограничительную рамку Rect box = boundingRect (pts); cout << "Ширина:" << box.width; cout << "Высота:" << box.height << endl; // Show box rectangle (img_bgr, box, Scalar (0,0,255), 3); imshow ("Box", img_bgr); ' – Nicholas

Смежные вопросы