2013-05-11 2 views
8

Я пытаюсь определить положение в образе обоих красных стен и белых квадратов на изображении ниже двух белой стены с красными вершинами и белыми «постов»:Multiple определение цвета объекта с использованием OpenCV

enter image description here

Мой подход должен был сделать пороговую найти красные стены, которые я могу теперь легко обнаружить из этого вывода:

enter image description here

Теперь моя проблема определения местоположения на йоту квадраты, но это сложнее, учитывая белые стены. Если я порог, основанный на белом, я все еще сохраняю нежелательные белые стены между белыми квадратными столбами.

Любая помощь была бы принята с благодарностью.

+0

Ну, белые в середине красных, arent они? Пойдите для этого. Найдите белый цвет между красными. Или найдите разрыв между красными и проверьте, белый ли он. –

+0

@AnderBiguri Это звучит правильно, я все еще рисую пустую информацию о том, как реализовать это в OpenCV. – salgarcia

+0

. Пораженное изображение, которое вы использовали, не является результатом обработки этого входного изображения. Они не совпадают :) – karlphillip

ответ

15

Один подход состоит в пороговым входного изображения с cv::inRange():

cv::Mat image = cv::imread(argv[1]); 
if (image.empty()) 
{ 
    std::cout << "!!! Failed imread()" << std::endl; 
    return -1; 
} 

cv::Mat red_image; 
cv::inRange(image, cv::Scalar(40, 0, 180), cv::Scalar(135, 110, 255), red_image); 
//cv::imwrite("out1.png", red_image); 

Выходы:

enter image description here

Мы можем использовать cv::findContours, чтобы получить контуры пороговую образ для творчества е ограничивающей коробки для них, which is a technique described here:

std::vector<std::vector<cv::Point> > contours; 
std::vector<cv::Vec4i> hierarchy; 
cv::findContours(red_image, 
        contours, 
        hierarchy, 
        CV_RETR_TREE, 
        CV_CHAIN_APPROX_SIMPLE, 
        cv::Point(0, 0)); 

std::vector<std::vector<cv::Point> > contours_poly(contours.size()); 
std::vector<cv::Rect> boundRect(contours.size()); 
for(int i = 0; i < contours.size(); i++) 
    { 
     cv::approxPolyDP(cv::Mat(contours[i]), contours_poly[i], 3, true); 
     boundRect[i] = cv::boundingRect(cv::Mat(contours_poly[i])); 
    } 


// Debug purposes: draw bonding rects 
//cv::Mat tmp = cv::Mat::zeros(red_image.size(), CV_8UC3); 
//for(int i = 0; i< contours.size(); i++) 
// rectangle(tmp, boundRect[i].tl(), boundRect[i].br(), cv::Scalar(0, 255, 0), 2, 8, 0); 
//cv::imwrite("out2.png", tmp); 

Выход:

enter image description here

Все отображаемые на изображении выше, хранятся в виде cv::Rect объекта внутри boundRect вектора прямоугольниками.Каждый rectangle состоит из 2 противоположных cv::Point объектов, поэтому мы итерация по этому вектору, чтобы создать новый вектор, состоящие только из cv::Point объектов:

// Two opposite cv::Point can be used to draw a rectangle. 
// Iterate on the cv::Rect vector and retrieve all cv::Point 
// and store them in a cv::Point vector. 
std::vector<cv::Point> rect_points; 
for(int i = 0; i < contours.size(); i++) 
{ 
    rect_points.push_back(boundRect[i].tl()); 
    rect_points.push_back(boundRect[i].br()); 
} 

//cv::Mat drawing = cv::Mat::zeros(red_image.size(), CV_8UC3); 
cv::Mat drawing = image.clone(); 

логика, чтобы найти белые квадраты: предположу, что 2 пикселя в пределах 25х25 расстояние друг от друга определяют белый квадрат:

// Draw a rectangle when 2 points are less than 25x25 pixels of 
// distance from each other 
for(int i = 0; i < rect_points.size(); i++) 
{ 
    for(int j = 0; j < rect_points.size(); j++) 
    { 
     if (i == j) 
      continue; 

     int x_distance = (rect_points[i].x - rect_points[j].x); 
     if (x_distance < 0) 
      x_distance *= -1; 

     int y_distance = (rect_points[i].y - rect_points[j].y); 
     if (y_distance < 0) 
      y_distance *= -1; 

     if ((x_distance < 25) && (y_distance < 25)) 
     { 
      std::cout << "Drawing rectangle " << i << " from " 
         << rect_points[i] << " to " << rect_points[j] 
         << " distance: " << x_distance << "x" << y_distance << std::endl; 

      cv::rectangle(drawing, 
          rect_points[i], 
          rect_points[j], 
          cv::Scalar(255, 50, 0), 
          2); 
      break; 
     } 
    } 

} 

    //cv::imwrite("out3.png", drawing); 
cv::imshow("white rectangles", drawing);  
cv::waitKey(); 

Выход:

enter image description here

Этот алгоритм довольно сырой и пропускает два белых квадрата внизу, потому что под ними нет красных стен, только над ними.

Так я оставляю это до вас, чтобы улучшить этот подход :)

удачи.

1

Вся важная информация на сцене, кажется, находится в бинарном изображении извлеченных красных полос. Я попытался бы проигнорировать исходную картинку для этого шага и использовать только геометрию прямоугольников, чтобы найти область между ними.

Например, вы можете позвонить findContours, чтобы получить 8 капель в вашем примере. Если вы проверяете точки на линии между их центрами масс, точка, возвращающая минимальное значение в точкуPolygonTest, является центральной точкой одного из белых пятен (или, по крайней мере, близко).

Вы можете использовать известную информацию о месте и изображениях, с которыми вы столкнетесь. Например, вы можете группировать контуры в «левые» и «правые» бары и выполнять поиск линии между определенными контурами. Однако, если вам нужно быть более агностиком повторно. ваш ввод, вы получаете более или менее все (ориентация сцены, количество стен, толщина прямоугольников ...) с порогового изображения должно быть вполне возможным.