2015-03-11 5 views
-1

Я пишу приложение C++ с использованием библиотеки OpenCV для обнаружения объектов на изображениях. Эти изображения выглядят так: http://fs1.directupload.net/images/150311/my6uczfn.png Верхняя часть изображения, которая является черной, может быть проигнорирована.OpenCV найти контуры закрытых объектов

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

Mat image = imread("2.png", CV_LOAD_IMAGE_COLOR); 
if(!image.data) 
{ 
    std::cout << "Could not open or find the image." << std::endl; 
} 

Range range_rows(0, image.size().height); 
Range range_columns_left(0, image.size().width); 
Range range_columns_middle(image.size().width, image.size().width * 2); 
Range range_columns_right(image.size().width * 2, image.size().width * 3); 
Mat display_mat(image.size().height, image.size().width * 3, CV_8UC3); 
Mat left(display_mat, range_rows, range_columns_left); 
image.copyTo(left); 

Mat classified_image; 
threshold(image, classified_image, 254, 255, THRESH_BINARY); 
Mat middle(display_mat, range_rows, range_columns_middle); 
classified_image.copyTo(middle); 

Mat cimage = Mat::zeros(image.size(), CV_8UC3); 

Mat classified_grayscale_image; 
cvtColor(classified_image, classified_grayscale_image, CV_RGB2GRAY); 
std::vector< std::vector<cv::Point> > contours; 
findContours(classified_grayscale_image, contours, CV_RETR_LIST, CV_CHAIN_APPROX_NONE); 

for(size_t counter = 0; counter < contours.size(); counter++) 
{ 
    std::cout << "Contours size: " << contours[counter].size() << std::endl; 
    if(contours[counter].size() < 6) 
    continue; 

    Mat pointsf; 
    Mat(contours[counter]).convertTo(pointsf, CV_32F); 
    RotatedRect box = fitEllipse(pointsf); 

    drawContours(cimage, contours, (int)counter, Scalar::all(255), 1, 8); 
    ellipse(cimage, box, Scalar(0,0,255), 1, CV_AA); 
    std::cout << "Ellipse Parameter:\t"; 
    ellipse(cimage, box.center, box.size*0.5f, box.angle, 0, 360, Scalar(0,255,255), 1, CV_AA); 
    Point2f vtx[4]; 
    box.points(vtx); 
    for(int j = 0; j < 4; j++) 
     line(cimage, vtx[j], vtx[(j+1)%4], Scalar(0,255,0), 1, CV_AA); 
} 

Mat right(display_mat, range_rows, range_columns_right); 
cimage.copyTo(right); 

namedWindow("Results", CV_WINDOW_AUTOSIZE); 
imshow("Results", display_mat); 

waitKey(0); 

return 0; 

Результат выглядит следующим образом: http://fs1.directupload.net/images/150311/toiy3aes.png

Как вы видите, классификация, что является объектом, а что нет, не является совершенным, так 2 объекта распознаются как один. Классификация будет улучшена, но может произойти что-то подобное, если эти объекты очень близки. Еще большая проблема - когда они касаются друг друга. Как я могу сделать правильное распознавание объектов в случае, показанном выше? Есть идеи?

ответ

0

У вас есть несколько вариантов:

  • использовать некоторые фильтрации метода/пороговый на результирующее изображении, чтобы разделить объекты друг от друга. В этом случае должно быть достаточно бинаризации Otsu, в качестве альтернативы вы можете попытаться использовать операцию расширения.
  • обратное ваше изображение результата, а не использование преобразования расстояния и бинаризации Otsu (или какой-либо другой вид o порогового значения - большинство из них должно работать нормально). Это сделает вас объектами меньшими, но сделает их намного проще.
  • Если вам нужно отметить объекты как можно точнее, вам нужно использовать более сложный метод. Here есть учебник, в котором используются методы, описанные выше, и связанные компоненты и водораздел.
+0

Я использовал ваше второе предложение и с точки зрения подсчета объектов получаю неплохие результаты, спасибо за помощь и извините за поздний ответ. – Daiz

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