Как обрезать самый большой прямоугольник из изображения

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

Я делаю следующее, но не получаю желаемых результатов:

import cv2 import numpy as np im = cv2.imread('images/img5.jpg') gray=cv2.cvtColor(im,cv2.COLOR_BGR2GRAY) ret,thresh = cv2.threshold(gray,127,255,0) _,contours,_ = cv2.findContours(thresh,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE) areas = [cv2.contourArea(c) for c in contours] max_index = np.argmax(areas) cnt=contours[max_index] x,y,w,h = cv2.boundingRect(cnt) cv2.rectangle(im,(x,y),(x+w,y+h),(0,255,0),2) cv2.imshow("Show",im) cv2.imwrite("images/img5_rect.jpg", im) cv2.waitKey(0) 

Ниже приведены несколько примеров:

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

введите описание изображения здесь

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

введите описание изображения здесь

3-й пример : Невозможно найти правильные размеры на этом изображении. введите описание изображения здесь введите описание изображения здесь

4-й пример . То же самое и с этим. введите описание изображения здесь введите описание изображения здесь

2 Solutions collect form web for “Как обрезать самый большой прямоугольник из изображения”

Поскольку я ранее делал что-то подобное, я испытал с преобразованиями hough, но им было намного сложнее получить право на мой случай, чем использовать контуры. У меня есть следующие предложения, которые помогут вам начать работу:

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

     image_yuv = cv2.cvtColor(image,cv2.COLOR_BGR2YUV) image_y = np.zeros(image_yuv.shape[0:2],np.uint8) image_y[:,:] = image_yuv[:,:,0] 
  2. Текст на бумаге является проблемой. Используйте эффект размытия, чтобы (надеюсь) удалить эти высокочастотные шумы. Вы также можете использовать морфологические операции, такие как дилатация.

     image_blurred = cv2.GaussianBlur(image_y,(3,3),0) 
  3. Вы можете попытаться применить canny edge-detector, а не простой порог. Не обязательно, но может помочь вам:

      edges = cv2.Canny(image_blurred,100,300,apertureSize = 3) 
  4. Затем найдите контуры. В моем случае я использовал только экстремальные внешние контуры. Вы можете использовать флаг CHAIN_APPROX_SIMPLE для сжатия контура

     contours,hierarchy = cv2.findContours(edges,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE) 
  5. Теперь у вас должна быть куча контуров. Время найти правильные. Для каждого контура cnt сначала найдите выпуклую оболочку, затем используйте approaxPolyDP чтобы максимально упростить контур.

     hull = cv2.convexHull(cnt) simplified_cnt = cv2.approxPolyDP(hull,0.001*cv2.arcLength(hull,True),True) 
  6. Теперь мы должны использовать этот упрощенный контур, чтобы найти охватывающий четырехугольник. Вы можете экспериментировать с множеством правил, которые вы придумали. Самый простой способ – выбрать четыре самых длинных сегмента контура, а затем создать круглый четырехугольник, пересекая эти четыре линии. Основываясь на вашем случае, вы можете найти эти строки на основе контрастности линии, угла, который они делают, и подобных вещей.

  7. Теперь у вас есть куча четырехугольников. Теперь вы можете выполнить двухэтапный метод, чтобы найти нужный четырехсторонний. Сначала вы удаляете те, которые, вероятно, ошибаются. Например, один угол четырехугольника составляет более 175 градусов. Тогда вы можете выбрать тот, у которого самая большая площадь, в качестве конечного результата. Вы можете видеть оранжевый контур как один из результатов, которые я получил в этот момент: Все контуры

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

     (H,mask) = cv2.findHomography(cnt.astype('single'),np.array([[[0., 0.]],[[2150., 0.]],[[2150., 2800.]],[[0.,2800.]]],dtype=np.single)) 

    Числа предполагают проецирование на бумагу. Вы можете придумать лучшие и более умные числа для использования. Вам также необходимо изменить порядок точек контура в соответствии с порядком координат буквенной бумаги. Затем вы вызываете warpPerspective для создания окончательного изображения:

     final_image = cv2.warpPerspective(image,H,(2150, 2800)) 

    Это деформирование должно привести к чему-то вроде следующего (из моих результатов раньше): искривление

Надеюсь, это поможет вам найти подходящий подход в вашем случае.

Это довольно сложная задача, которая не может быть решена путем простого поиска контуров. Например, покрытие «Economist» показывает только 1 край магазина, который разбивает изображение пополам. Как ваш компьютер должен знать, какой из них – журнал, а какой – стол? Таким образом, вы должны добавить гораздо больше интеллекта в свою программу.

Вы можете искать линии в своем изображении. Например, преобразование Hough. Затем найдите наборы более или менее параллельных или ортогональных линий, линий определенной длины … Найдите отпечатки, проверяя типичные цвета или цвета печати, которые вы обычно не находите на столе. Поиск высококонтрастных частот, созданных печатными текстами … Представьте, как вы, как человек, узнаете печатную бумагу …

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

  • установка opencv для python на mavericks
  • может быть установлен OpenCV в виртуальной среде python на Mac Mountain Lion
  • установить pyopencv с pip на Mac OS X
  • opencv VideoWriter под OSX без вывода
  • python opencv imwrite ... не могу найти параметры
  • Плохая карта несоответствий с использованием StereoBM в OpenCV
  • Ошибка OpenCV: (-215) size.width> 0 && size.height> 0 в функции imshow
  • Как установить привязки Python 2.7 для OpenCV с помощью MacPorts
  • Упаковка OpenCV с приложением python
  • Преобразование OpenCV-Python в C ++ / Objective C
  • Захват одиночной картинки с opencv
  • Python - лучший язык программирования в мире.