Из изображения мне нужно извлечь лист бумаги, как это делает приложение camscanner, https://www.camscanner.com/
Я знаю, что могу сделать это, обнаружив края листа бумаги, которые я хочу обнаружить. А позже выполнить перспективное преобразование. Я использую библиотеку openCV в python. Это изображение, на котором я пытаюсь найти лист бумаги:
Вот что я уже пробовал:
Метод 1: (с использованием порогового значения)
- Предварительная обработка изображения со сглаживанием изображения (размытие по Гауссу/двустороннее размытие)
- разделение изображения на каналы h, s, v
- адаптивная пороговая обработка на канале насыщения
- некоторые морфологические операции, такие как расширение и эрозия
- поиск контуров, определение самого большого контура и поиск угловых точек
Я реализовал этот метод на основе ответа stackoverflow: Обнаружение листа бумаги/Обнаружение квадрата
Я могу найти лист бумаги для некоторых изображений, но не могу найти такие изображения:
Метод 2: (с использованием оператора градиента Собеля)
- Предварительная обработка изображения путем преобразования в оттенки серого, сглаживание изображения (размытие по Гауссу/двустороннее размытие)
- Нахождение градиентов изображения
- понижение и повышение разрешения изображения
- После этого я не знаю, как найти подходящую границу, охватывающую изображение.
Я реализовал этот метод на основе ответа stackoverflow: определить бумагу на фоне почти так же, как цвет бумаги
Вот как далеко я продвинулся с изображением:
Способ 3: (с использованием детектора краев)
Судя по сообщениям, которые я читал в этом сообществе, кажется, что все предпочитают метод осторожных краев для извлечения краев, но в моем случае результаты неудовлетворительны. Вот что я сделал:
- Предварительная обработка изображения путем преобразования в оттенки серого, сглаживание изображения (размытие по Гауссу/двустороннее размытие)
- Нахождение ребер с помощью canny edge
- некоторые морфологические операции, такие как расширение и эрозия
- Но края, полученные от canny, действительно не на должном уровне.
Я реализовал этот метод на основе ответа stackoverflow: Обнаружение листа бумаги/Обнаружение квадрата, также я не именно то, что он делает, перебирая несколько каналов в этом ответе. Вот как далеко я продвинулся с изображением:
Вот некоторый код в методе1 (пороговое значение):
#READING IMAGE INTO BGR SPACE
image = cv2.imread("./images/sheet3.png")
#BILATERAL FILTERING TO SMOOTHEN THE IMAGE BUT NOT THE EDGES
img = cv2.bilateralFilter(image,20,75,75)
#CONVERTING BGR TO HSV
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
#SPLITTING THE HSV CHANNELS
h,s,v = cv2.split(hsv)
#DOUBLING THE SATURATION CHANNEL
gray_s = cv2.addWeighted(cv2.cvtColor(img, cv2.COLOR_BGR2GRAY), 0.0, s, 2.0, 0)
#THRESHOLDING USING ADAPTIVETHRESHOLDING
threshed = cv2.adaptiveThreshold(gray_s, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY_INV, 109, 10)
#APPLYING MORPHOLOGICAL OPERATIONS OF DILATION AND EROSION
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (2, 2))
morph = cv2.morphologyEx(threshed, cv2.MORPH_OPEN, kernel)
#FINDING ALL THE CONTOURS
cnts = cv2.findContours(morph, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)[-2]
canvas = img.copy()
#SORTING THE CONTOURS AND TAKING THE LARGEST CONTOUR
cnts = sorted(cnts, key = cv2.contourArea)
cnt = cnts[-1]
#FINDING THE PERIMETER OF THE CONTOUR
arclen = cv2.arcLength(cnt, True)
#FINDING THE END POINTS OF THE CONTOUR BY APPROX POLY DP
approx = cv2.approxPolyDP(cnt, 0.02* arclen, True)
cv2.drawContours(canvas, [cnt], -1, (255,0,0), 1, cv2.LINE_AA)
cv2.drawContours(canvas, [approx], -1, (0, 0, 255), 1, cv2.LINE_AA)
cv2.imwrite("detected.png", canvas)
Я новичок в обработке изображений и openCV. Пожалуйста, поделитесь некоторыми мыслями о том, как продвинуться дальше и получить более точные результаты. ТИА.