Обнаружение листа бумаги внутри изображения, например, приложение cam-scanner

Из изображения мне нужно извлечь лист бумаги, как это делает приложение camscanner, https://www.camscanner.com/

Я знаю, что могу сделать это, обнаружив края листа бумаги, которые я хочу обнаружить. А позже выполнить перспективное преобразование. Я использую библиотеку openCV в python. Это изображение, на котором я пытаюсь найти лист бумаги:

лист бумаги для обнаружения

Вот что я уже пробовал:

Метод 1: (с использованием порогового значения)

  1. Предварительная обработка изображения со сглаживанием изображения (размытие по Гауссу/двустороннее размытие)
  2. разделение изображения на каналы h, s, v
  3. адаптивная пороговая обработка на канале насыщения
  4. некоторые морфологические операции, такие как расширение и эрозия
  5. поиск контуров, определение самого большого контура и поиск угловых точек

Я реализовал этот метод на основе ответа stackoverflow: Обнаружение листа бумаги/Обнаружение квадрата

Я могу найти лист бумаги для некоторых изображений, но не могу найти такие изображения:

сбой обнаружения бумаги

Метод 2: (с использованием оператора градиента Собеля)

  1. Предварительная обработка изображения путем преобразования в оттенки серого, сглаживание изображения (размытие по Гауссу/двустороннее размытие)
  2. Нахождение градиентов изображения
  3. понижение и повышение разрешения изображения
  4. После этого я не знаю, как найти подходящую границу, охватывающую изображение.

Я реализовал этот метод на основе ответа stackoverflow: определить бумагу на фоне почти так же, как цвет бумаги

Вот как далеко я продвинулся с изображением:

результат градиента Собеля

Способ 3: (с использованием детектора краев)

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

  1. Предварительная обработка изображения путем преобразования в оттенки серого, сглаживание изображения (размытие по Гауссу/двустороннее размытие)
  2. Нахождение ребер с помощью canny edge
  3. некоторые морфологические операции, такие как расширение и эрозия
  4. Но края, полученные от 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. Пожалуйста, поделитесь некоторыми мыслями о том, как продвинуться дальше и получить более точные результаты. ТИА.


person Beeti Sushruth    schedule 22.08.2019    source источник
comment
Обнаружение границ обычно плохо работает для таких проблем. Предпочтите обнаружение областей, как в методе 1 (возможно, с адаптивным пороговым значением и использованием цвета, где это возможно). Для таких случаев, как i.imgur.com/S905YGL.jpg, просто отбросьте идею, ничего будет работать надежно.   -  person Yves Daoust    schedule 22.08.2019
comment
@YvesDaoust Я думал о том же, как вы можете видеть в коде, который я упомянул выше, я использовал адаптивную пороговую настройку, потому что порог меняется для каждого пикселя, вышеуказанный метод также не дает точного результата, например это изображение: i.imgur.com/XcTydIL.jpg, это пороговое изображение: i.imgur.com/e6tVjaR.png   -  person Beeti Sushruth    schedule 22.08.2019
comment
Не ждите чудес, а используйте более крупный фильтр (не ограничивайтесь одной попыткой). Также обратите внимание на другие методы сегментации.   -  person Yves Daoust    schedule 22.08.2019
comment
Пожалуйста, найдите существующие вопросы и ответы. Я чувствую, что обнаружил, что лист бумаги приносят сюда два раза в день.   -  person Piglet    schedule 22.08.2019
comment
@Piglet весь вышеприведенный код, который я написал, взят из предыдущих ответов, хотя, как я уже упоминал, ответы не подходят для некоторых изображений. Например: i.imgur.com/e6tVjaR.png. Я прошу только о дополнительной обработке, которую необходимо выполнить. Спасибо   -  person Beeti Sushruth    schedule 22.08.2019