Как найти точные угловые позиции искаженного прямоугольника от размытого изображения в питоне? - PullRequest
2 голосов
/ 06 ноября 2019

Я ищу процедуру для точного определения углов искаженного прямоугольника с помощью OpenCV в Python.

Я пробовал решение различных предложений путем поиска в Google, но с помощью синусоидальной суперпозиции прямой линии. (см. пороговое изображение) Я, вероятно, не могу определить углы. Я пытался найти findContours и HoughLines до сих пор без хороших результатов. К сожалению, я не понимаю C-код из Xu Bin в , как найти положение угла размытия с помощью opencv?

Это мое первоначальное изображение:

enter image description here

После изменения размера и порогового значения я применяю обнаружение Canny Edge, чтобы получить следующее изображение:

image

contours, hierarchy = cv2.findContours(g_mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
box = cv2.minAreaRect(contour)
box = cv2.cv.BoxPoints(box) if imutils.is_cv2() else cv2.boxPoints(box)
box = np.array(box, dtype="float")
box = perspective.order_points(box)

Я получаю только следующий результатс некоторым дополнительным рисунком:

image

Я думал, что подгонка линии будет хорошим способом решения проблемы, но, к сожалению, я не смог заставить HoughLines работать и после просмотра OpenCV Python - Как внедрить RANSAC для обнаружения прямых линий? RANSAC также кажется сложным для решения моей проблемы.

Любая помощь очень ценится.

1 Ответ

0 голосов
/ 07 ноября 2019

Для определения углов вы можете использовать cv2.goodFeaturesToTrack(). Функция принимает четыре параметра

corners = cv2.goodFeaturesToTrack(image, maxCorners, qualityLevel, minDistance)
  • image - Входное 8-битное или 32-битное одноканальное изображение в градациях серого
  • maxCorners - Максимальное количествоуглы для возврата
  • qualityLevel - минимально допустимый уровень качества углов в диапазоне 0-1. Все углы ниже уровня качества отклоняются
  • minDistance - минимально возможное евклидово расстояние между углами

Теперь, когда мы знаем, как найти углы, мы должны найти повернутый прямоугольник и применитьфункция. Вот подход:


Сначала мы увеличиваем изображение, преобразуем его в оттенки серого, применяем двусторонний фильтр, затем порог Оцу, чтобы получить двоичное изображение

image

Затем мы находим искаженный прямоугольник, находя контуры с помощью cv2.findContours(), затем получаем повернутую ограничивающую рамку, выделенную зеленым цветом. Мы рисуем эту ограничивающую рамку на маске

image image

Теперь, когда у нас есть маска, мы просто используем cv2.goodFeaturesToTrack(), чтобы найти углы на маске

image

Вот результат исходного входного изображения и (x, y) координаты для каждого угла

image

Угловые точки

(377.0, 375.0)
(81.0, 344.0)
(400.0, 158.0)
(104.0, 127.0)

Код

import cv2
import numpy as np
import imutils

# Resize image, blur, and Otsu's threshold
image = cv2.imread('1.png')
resize = imutils.resize(image, width=500)
mask = np.zeros(resize.shape, dtype=np.uint8)
gray = cv2.cvtColor(resize, cv2.COLOR_BGR2GRAY)
blur = cv2.bilateralFilter(gray,9,75,75)
thresh = cv2.threshold(blur, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1]

# Find distorted rectangle contour and draw onto a mask
cnts = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
rect = cv2.minAreaRect(cnts[0])
box = cv2.boxPoints(rect)
box = np.int0(box)
cv2.drawContours(resize,[box],0,(36,255,12),2)
cv2.fillPoly(mask, [box], (255,255,255))

# Find corners on the mask
mask = cv2.cvtColor(mask, cv2.COLOR_BGR2GRAY)
corners = cv2.goodFeaturesToTrack(mask, maxCorners=4, qualityLevel=0.5, minDistance=150)

for corner in corners:
    x,y = corner.ravel()
    cv2.circle(resize,(x,y),8,(155,20,255),-1)
    print("({}, {})".format(x,y))

cv2.imshow('resize', resize)
cv2.imshow('thresh', thresh)
cv2.imshow('mask', mask)
cv2.waitKey()
...