2015-12-20 7 views
3

У меня есть фотография, где человек держит лист бумаги. Я хотел бы определить прямоугольник этого листа бумаги.OpenCV: Можно ли определить прямоугольник из углов?

enter image description here

Я попытался следующие различные учебники из OpenCV и различных SO ответы и примеры кода для обнаружения квадратов/прямоугольников, но проблема в том, что все они опираются на контуры какой-то.

Если я следую за squares.cpp примером, я получаю следующие результаты из контуров:

enter image description here

Как вы можете видеть, пальцы являются частью контура, поэтому алгоритм не находит квадрат.

Я тоже пытался использовать HoughLines() подход, но я получить аналогичные результаты выше:

enter image description here

я могу обнаружить углы, надежно, хотя:

enter image description here

Есть другие углы на изображении, но я ограничиваю общие углы, найденные < 50, а углы для листа бумаги - всегда найдено.

Есть ли алгоритм поиска прямоугольника из нескольких углов в изображении? Кажется, я не вижу существующего подхода.

+0

В принципе, вы хотите, чтобы контуры, кормить их 'appoxPolyDP()', а затем проверить полученный 'approxCurve' размер. Если это 4, у вас есть четырехугольник, и это ваши углы. Вероятно, вам придется снова упорядочить порядок углов, так как заказ не гарантируется. Дай мне знать, если тебе еще понадобится помощь. – MeetTitan

+0

Я пробовал это, но контуры пальцев ломают боковые края листа бумаги и appoxPolyDP не находит его тогда. –

+0

Тогда я не уверен.Не могли бы вы перебрать контуры с углом 90 °? – MeetTitan

ответ

6

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

Закрытые края:

closed

Контур:

contour

ConvexHull:

hull

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

Код

Mat im = imread("Sh1Vp.png", 0); // the edge image 
Mat kernel = getStructuringElement(MORPH_ELLIPSE, Size(11, 11)); 
Mat morph; 
morphologyEx(im, morph, CV_MOP_CLOSE, kernel); 

int rectIdx = 0; 
vector<vector<Point>> contours; 
vector<Vec4i> hierarchy; 
findContours(morph, contours, hierarchy, CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE, Point(0, 0)); 
for (size_t idx = 0; idx < contours.size(); idx++) 
{ 
    RotatedRect rect = minAreaRect(contours[idx]); 
    double areaRatio = abs(contourArea(contours[idx]))/(rect.size.width * rect.size.height); 
    if (areaRatio > .95) 
    { 
     rectIdx = idx; 
     break; 
    } 
} 
// get the convexhull of the contour 
vector<Point> hull; 
convexHull(contours[rectIdx], hull, false, true); 

// visualization 
Mat rgb; 
cvtColor(im, rgb, CV_GRAY2BGR); 
drawContours(rgb, contours, rectIdx, Scalar(0, 0, 255), 2); 
for(size_t i = 0; i < hull.size(); i++) 
{ 
    line(rgb, hull[i], hull[(i + 1)%hull.size()], Scalar(0, 255, 0), 2); 
} 
Смежные вопросы