Ответ 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]
-
Текст на бумаге является проблемой. Используйте эффект размытия, чтобы (надеюсь) удалить эти высокочастотные шумы. Вы также можете использовать морфологические операции, такие как дилатация.
image_blurred = cv2.GaussianBlur(image_y,(3,3),0)
-
Вы можете попытаться применить canny edge-detector, а не простой порог. Не обязательно, но может помочь вам:
edges = cv2.Canny(image_blurred,100,300,apertureSize = 3)
-
Затем найдите контуры. В моем случае я использовал только экстремальные внешние контуры. Вы можете использовать флаг CHAIN_APPROX_SIMPLE для сжатия контура
contours,hierarchy = cv2.findContours(edges,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
-
Теперь у вас должна быть куча контуров. Время найти правильные. Для каждого контура
cnt
сначала найдите выпуклую оболочку, затем используйтеapproaxPolyDP
, чтобы максимально упростить контур.hull = cv2.convexHull(cnt) simplified_cnt = cv2.approxPolyDP(hull,0.001*cv2.arcLength(hull,True),True)
-
Теперь мы должны использовать этот упрощенный контур, чтобы найти охватывающий четырехугольник. Вы можете экспериментировать с множеством правил, которые вы придумали. Самый простой способ - выбрать четыре самых длинных сегмента контура, а затем создать круглый четырехугольник, пересекая эти четыре линии. Основываясь на вашем случае, вы можете найти эти строки на основе контрастности линии, угла, который они создают, и подобных вещей.
-
Теперь у вас есть куча четырехугольников. Теперь вы можете выполнить двухэтапный метод, чтобы найти нужный четырехсторонний. Сначала вы удаляете те, которые, вероятно, ошибаются. Например, один угол четырехугольника составляет более 175 градусов. Тогда вы можете выбрать тот, у которого самая большая площадь, в качестве конечного результата. Вы можете видеть оранжевый контур как один из результатов, которые я получил в этот момент:
-
Последний шаг после нахождения (надеюсь) правого четырехугольника, превращается обратно в прямоугольник. Для этого вы можете использовать
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))
Это деформирование должно привести к чему-то вроде следующего (из моих результатов раньше):
Надеюсь, это поможет вам найти подходящий подход в вашем случае.