Обрезать изображение с изображения с Edge Detection - PullRequest
1 голос
/ 29 марта 2020

Так что в основном у меня есть изображение с пробелами и текст выше. На выходе должна быть только картинка. Без текста и пробелов. Лучшим примером, вероятно, будет мем:

like this

Я считаю, что мне нужно было бы получить угловые координаты, а затем использовать что-то вроде подушки * Image.crop(corner_coordinates).

Как я мог это реализовать?

Редактировать: Итак, я попробовал немного. Я использовал алгоритм обнаружения краев Canny (opencv). Теперь я получаю нужные края, а также края текста. Было бы хорошо, если бы кто-то мог помочь мне:)

1 Ответ

1 голос
/ 29 марта 2020

Вы можете найти ограничивающий прямоугольник самого большого контура, который не является белым.

Я предлагаю использовать следующие этапы:

  • Преобразование изображения из BGR в серый.
  • Преобразование из серого в двоичное изображение.
    Использовать автоматы c Порог (используйте cv2.THRESH_OTSU флаг) и инвертированную полярность.
    В результате получается белый цвет, где исходное изображение темное, и черный, где изображение яркое.
  • Поиск контуров с помощью cv2.findContours() (как прокомментировал Марк Сетчелл).
    Найти внешний контур проще, чем обнаруживать края.
  • Найти ограничивающий прямоугольник контура с максимальной площадью.
  • Обрезать ограничивающий прямоугольник из входного изображения.
    Я использовал NumPy нарезку массива вместо подушки.

Вот код:

import cv2

# Read input image
img = cv2.imread('img.jpg')

# Convert from BGR to Gray.
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# Convert to binary image using automatic threshold and invert polarity
_, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)

# Find contours on thresh
cnts = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)[-2]  # Use index [-2] to be compatible to OpenCV 3 and 4

# Get contour with maximum area
c = max(cnts, key=cv2.contourArea)

x, y, w, h = cv2.boundingRect(c)

# Crop the bounding rectangle (use .copy to get a copy instead of slice).
crop = img[y:y+h, x:x+w, :].copy()


# Draw red rectangle for testing
cv2.rectangle(img, (x, y), (x+w, y+h), (0, 0, 255), thickness = 2)

# Show result
cv2.imshow('img', img)
cv2.imshow('crop', crop)
cv2.waitKey(0)
cv2.destroyAllWindows()

Результат:

crop:
enter image description here

img:
enter image description here

thresh:
enter image description here

...