2014-10-27 1 views
5
http://oi60.tinypic.com/51lkp.jpg

OpenCV С ++ - обнаружение Прямоугольник, который имеет нерегулярных стороны

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

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

Есть ли какой-либо другой метод рядом с houghline, который является более простым (не требует переконфигурации/сложной конфигурации)?

+0

, возможно, вы можете рассмотреть вопрос расширения и эрозии последовательностей в CREA т. е. более «правильный» прямоугольник с целью получения угловых координат с помощью метода контура. после этого вы можете повернуть исходный прямоугольник. –

+0

Пример squares.cpp в примерах OpenCV может помочь вам. Используйте простое пороговое значение, извлеките внешние контуры, затем выполните многоугольное приближение этих контуров, как показано в образце. – dhanushka

+0

Попробуйте следующее: http://docs.opencv.org/modules/imgproc/doc/structural_analysis_and_shape_descriptors.html?highlight=minarearect#minarearect – Micka

ответ

5

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

Может быть, вы можете комбинировать, что с ответом Взант, так что вы можете сначала аппроксимировать полином, чтобы получить очередную границу, а затем извлечь повернутый прямоугольник с cv::minAreaRect

Вот мой код:

int main() 
{ 
    cv::Mat input = cv::imread("../inputData/RotatedRect.png"); 

    // convert to grayscale (you could load as grayscale instead) 
    cv::Mat gray; 
    cv::cvtColor(input,gray, CV_BGR2GRAY); 

    // compute mask (you could use a simple threshold if the image is always as good as the one you provided) 
    cv::Mat mask; 
    cv::threshold(gray, mask, 0, 255, CV_THRESH_BINARY_INV | CV_THRESH_OTSU); 

    // find contours (if always so easy to segment as your image, you could just add the black/rect pixels to a vector) 
    std::vector<std::vector<cv::Point>> contours; 
    std::vector<cv::Vec4i> hierarchy; 
    cv::findContours(mask,contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE); 

    /// Draw contours and find biggest contour (if there are other contours in the image, we assume the biggest one is the desired rect) 
    // drawing here is only for demonstration! 
    int biggestContourIdx = -1; 
    float biggestContourArea = 0; 
    cv::Mat drawing = cv::Mat::zeros(mask.size(), CV_8UC3); 
    for(int i = 0; i< contours.size(); i++) 
    { 
     cv::Scalar color = cv::Scalar(0, 100, 0); 
     drawContours(drawing, contours, i, color, 1, 8, hierarchy, 0, cv::Point()); 

     float ctArea= cv::contourArea(contours[i]); 
     if(ctArea > biggestContourArea) 
     { 
      biggestContourArea = ctArea; 
      biggestContourIdx = i; 
     } 
    } 

    // if no contour found 
    if(biggestContourIdx < 0) 
    { 
     std::cout << "no contour found" << std::endl; 
     return 1; 
    } 

    // compute the rotated bounding rect of the biggest contour! (this is the part that does what you want/need) 
    cv::RotatedRect boundingBox = cv::minAreaRect(contours[biggestContourIdx]); 
    // one thing to remark: this will compute the OUTER boundary box, so maybe you have to erode/dilate if you want something between the ragged lines 



    // draw the rotated rect 
    cv::Point2f corners[4]; 
    boundingBox.points(corners); 
    cv::line(drawing, corners[0], corners[1], cv::Scalar(255,255,255)); 
    cv::line(drawing, corners[1], corners[2], cv::Scalar(255,255,255)); 
    cv::line(drawing, corners[2], corners[3], cv::Scalar(255,255,255)); 
    cv::line(drawing, corners[3], corners[0], cv::Scalar(255,255,255)); 

    // display 
    cv::imshow("input", input); 
    cv::imshow("drawing", drawing); 
    cv::waitKey(0); 

    cv::imwrite("rotatedRect.png",drawing); 

    return 0; 
} 

давая это результат:

enter image description here

+1

спасибо Микка .. этот метод работает для меня .. спасибо также за пояснения в этот код – stranger

4

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

  • Черного расположение пикселей с наималейшим й координатой
  • Черного расположения пикселей с крупным й координатой
  • Черного пикселея место с наименьшим у координате
  • черный пиксель месте с самым большим у координате

Эти 4 точки будут краями вашего прямоугольника.

+0

Спасибо bikz05, я ценю ваш ответ, +1 к простоте – stranger

3

Попробуйте это:

1.Run findCountours на изображении.

2.Apply approxPolyDP для приближения контура к прямоугольнику. Контурные стороны будут намного более регулярными.

3.Segment прямоугольные контуры, используя moments и/или геометрию.

+0

Спасибо, Vasanth, я ценю ваш ответ, теперь я знаю другой метод рядом с houghline – stranger

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