Проблемы с нахождением контура в видеоизображении с помощью C ++ FindContours

Программа, над которой я сейчас работаю почти сделано, но я не очень удовлетворен результатом. С помощью алгоритма Канни мне удалось получить четкое представление о контуре объекта, но в программе возникла проблема с распознаванием контура и рисованием контура красной линией. Программа:

void setwindowSettings(){
namedWindow("Contours", CV_WINDOW_AUTOSIZE);

createTrackbar("LowerC", "Contours", &lowerC, 255, NULL);
createTrackbar("UpperC", "Contours", &upperC, 255, NULL);
}

void wait(void)
{
long t=30000000;
while(t--);
}

int main(void)
{
VideoCapture cap(0); // open the default camera
if(!cap.isOpened())  // check if we succeeded
return -1;

Mat frame,foreground,image;
double pt1, pt2, area;
Rect rect;
int i;

vector<vector<Point> > contours;
vector<vector<Point> > largest_contours;

namedWindow("Capture", CV_WINDOW_AUTOSIZE);
setwindowSettings();

while(1){
cap >> frame; // get a new frame from camera
if( frame.empty() )
break;
image=frame.clone();

cvtColor(image,foreground,CV_BGR2GRAY);
GaussianBlur(foreground,foreground,Size(9,11),0,0);
Canny(foreground,foreground,lowerC,upperC,3);

findContours(foreground,contours,CV_RETR_EXTERNAL,CV_CHAIN_APPROX_SIMPLE);

if(contours.empty())
continue;

double largest_area = 0;

for( i= 0; i < contours.size(); i++){  // get the largest contour
area = fabs(contourArea(contours[i]));
if(area >= largest_area){
largest_area = area;
largest_contours.clear();
largest_contours.push_back(contours[i]);
}
}

if(largest_area>=3000){   // draw the largest contour if exceeded minimum largest area
drawContours(image,largest_contours,-1,Scalar(0,0,255),2);
printf("area = %.f\n",largest_area);
}

wait();

imshow( "Capture",image );
imshow("Contours",foreground);

if(waitKey(30) >= 0) break;
}
// the camera will be deinitialized automatically in VideoCapture destructor
return 0;
}

Краткое содержание программы:

  1. Получить изображения с камеры
  2. Шумовая фильтрация (Преобразовать в серый → размытие → Canny)
  3. Найти контуры
  4. Найдите самый большой контур и его площадь на изображении или объекте
  5. Нарисуйте красную линию вокруг объекта и распечатайте самую большую область
  6. Промыть и повторить

И результаты:

Редко я получаю то, что хочу; Обнаружен контур, нарисована красная линия (НЕПЛОХО):

Обнаружены контуры. Отмечено, что половина линии контура исчезает

…и обычно я получаю это; Контур не обнаружен, нет красной линии (ПЛОХОЙ):

Контур не обнаружен, хотя контур есть

Шансы получить НЕПЛОХО о 1/20 что не очень хорошо Кроме того, линия контура объекта в Contours Экран будет мигать, когда вокруг объекта появится красная линия (см. изображение «ХОРОШО»).
Я использую один из моих объектов (маленький черный квадрат) для этого вопроса, но, пожалуйста, обратите внимание, что основной целью этой программы обнаружения объектов является обнаруживать объект независимо от его формы или цвета.

Итак, мои вопросы:

  1. Почему я все еще получаю плохие, несмотря на то, что контур ясен как день?
  2. Кто-нибудь может поделиться лучшей идеей о том, как улучшить обнаружение контура? (т.е. лучше алгоритм размытия)
  3. Как избежать мигания линии контура, когда вокруг объекта нарисована красная линия?

РЕДАКТИРОВАТЬ: Я только что обнаружил, что линия контура мигает не из-за красной линии, нарисованной вокруг нее (либо с drawContoursили же line функция), но это происходит после того, как самый большой контур обнаружен findContours функция и рассчитывается как самый большой контур.

На вопрос о нет. 3 клика ВОТ. ВИДЕО ЗДЕСЬ, НАЖМИТЕ НА ЭТО !!!

Заранее спасибо.

PS: я использую OpenCV 2.4.3 на MS Visual C ++ 2010 Exp.

2

Решение

  1. Поскольку вы используете факт наибольшего контура, я предполагаю, что вы пытаетесь обнаружить самый большой объект, появляющийся в поле зрения камеры. Интересно, почему оконный источник света / источник яркого света в правом верхнем углу не создает никакого контура ( может быть из-за размытия). Вы можете сохранить фоновое изображение и вычесть его из изображения, где появляется объект. Таким образом, вы можете получить объект. Вы можете применить поиск контура в разностном изображении.absdiff(frame_now,frame_backgrnd,diff) где diff это разница изображения.
  2. Если объект находится в движении и вы хотите его обнаружить, вы можете использовать оптический поток в сочетании с наибольшим контуром для обнаружения объекта.
  3. Попробуйте выполнить обработку без функции размытия, а затем определите наибольшую площадь контура.
  4. Для построения точек попробуйте это

    for(int i = 1;i<(int)largest_contours[0].size();i++)
    line(image,largest_contours[0][i-1],largest_contours[0][i],cv::Scalar(0,0,255),2,8,0);
    
1

Другие решения

Других решений пока нет …