Подтвердить что ты не робот

Автоматическая коррекция перспективы OpenCV

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

Я использую код, найденный в этом tutorial

Когда я даю ему изображение, которое выглядит так:

enter image description here

Я получаю это как результат:

enter image description here

Вот что мне может помочь dst.

enter image description here

Я использую это для вызова метода, который содержит код.

quadSegmentation(Img, bw, dst, quad);

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

4b9b3361

Ответ 1

Для преобразования перспективы вам нужно,

исходные точки- > Координаты четырехугольников в исходном изображении.

точки назначения- > Координаты соответствующих четырехугольников в целевом изображении.

Здесь мы вычислим эту точку контурным процессом.

Вычислить координаты четырехугольников в исходном изображении

  • Вы получите свою карту как контур, просто размывкой, порогом, затем найдите контур, найдите самый большой контур и т.д.
  • После нахождения наибольшего контура просто вычислить приближается к полигональной кривой, здесь вы должны получить 4 точки, которые представляют углы вашей карты. Вы можете отрегулировать параметр epsilon, чтобы сделать 4 координаты.

enter image description here

Вычислить координаты соответствующих четырехугольников в изображении назначения

  • Об этом легко узнать, вычисляя ограничивающий прямоугольник для наибольшего контура.

enter image description here

В нижнем изображении красный прямоугольник представляет точки источника и зеленый для точек назначения.

enter image description here

Отрегулировать порядок ордеров и применить преобразование перспективы

  • Здесь я вручную корректирую порядок ордеров, и вы можете использовать какой-то алгоритм сортировки.
  • Затем вычислите матрицу преобразования и примените wrapPrespective

См. окончательный результат

enter image description here

код

 Mat src=imread("card.jpg");
 Mat thr;
 cvtColor(src,thr,CV_BGR2GRAY);
 threshold( thr, thr, 70, 255,CV_THRESH_BINARY );

 vector< vector <Point> > contours; // Vector for storing contour
 vector< Vec4i > hierarchy;
 int largest_contour_index=0;
 int largest_area=0;

 Mat dst(src.rows,src.cols,CV_8UC1,Scalar::all(0)); //create destination image
 findContours( thr.clone(), contours, hierarchy,CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE ); // Find the contours in the image
 for( int i = 0; i< contours.size(); i++ ){
    double a=contourArea( contours[i],false);  //  Find the area of contour
    if(a>largest_area){
    largest_area=a;
    largest_contour_index=i;                //Store the index of largest contour
    }
 }

 drawContours( dst,contours, largest_contour_index, Scalar(255,255,255),CV_FILLED, 8, hierarchy );
 vector<vector<Point> > contours_poly(1);
 approxPolyDP( Mat(contours[largest_contour_index]), contours_poly[0],5, true );
 Rect boundRect=boundingRect(contours[largest_contour_index]);
 if(contours_poly[0].size()==4){
    std::vector<Point2f> quad_pts;
    std::vector<Point2f> squre_pts;
    quad_pts.push_back(Point2f(contours_poly[0][0].x,contours_poly[0][0].y));
    quad_pts.push_back(Point2f(contours_poly[0][1].x,contours_poly[0][1].y));
    quad_pts.push_back(Point2f(contours_poly[0][3].x,contours_poly[0][3].y));
    quad_pts.push_back(Point2f(contours_poly[0][2].x,contours_poly[0][2].y));
    squre_pts.push_back(Point2f(boundRect.x,boundRect.y));
    squre_pts.push_back(Point2f(boundRect.x,boundRect.y+boundRect.height));
    squre_pts.push_back(Point2f(boundRect.x+boundRect.width,boundRect.y));
    squre_pts.push_back(Point2f(boundRect.x+boundRect.width,boundRect.y+boundRect.height));

    Mat transmtx = getPerspectiveTransform(quad_pts,squre_pts);
    Mat transformed = Mat::zeros(src.rows, src.cols, CV_8UC3);
    warpPerspective(src, transformed, transmtx, src.size());
    Point P1=contours_poly[0][0];
    Point P2=contours_poly[0][1];
    Point P3=contours_poly[0][2];
    Point P4=contours_poly[0][3];


    line(src,P1,P2, Scalar(0,0,255),1,CV_AA,0);
    line(src,P2,P3, Scalar(0,0,255),1,CV_AA,0);
    line(src,P3,P4, Scalar(0,0,255),1,CV_AA,0);
    line(src,P4,P1, Scalar(0,0,255),1,CV_AA,0);
    rectangle(src,boundRect,Scalar(0,255,0),1,8,0);
    rectangle(transformed,boundRect,Scalar(0,255,0),1,8,0);

    imshow("quadrilateral", transformed);
    imshow("thr",thr);
    imshow("dst",dst);
    imshow("src",src);
    imwrite("result1.jpg",dst);
    imwrite("result2.jpg",src);
    imwrite("result3.jpg",transformed);
    waitKey();
   }
   else
    cout<<"Make sure that your are getting 4 corner using approxPolyDP..."<<endl;

Ответ 2

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

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

Чтобы устранить проблему, вы должны убедиться, что только линии на периферии извлечены. Если у вас всегда есть темный фон, вы можете использовать этот факт, чтобы отбросить линии с другими контрастами/полярностями. В качестве альтернативы вы можете извлечь все строки, а затем выбрать те, которые ближе всего к границе изображения (если ваш фон не имеет линий).