Вот подход, основанный на предположении, что большая часть текста перекошена в одну сторону.Идея состоит в том, что мы можем определить угол на основе расположения основной текстовой области
- . Преобразовать изображение в оттенки серого и размытие по Гауссу
- Адаптивный порог для получения двоичного изображения
- Поиск контуров и фильтрация по области контуров
- Создание отфильтрованных контуров на маске
- Разделение изображения по горизонтали или вертикали в зависимости от ориентации
- Подсчет количества пикселей в каждой половине
После преобразования в оттенки серого и размытие по Гауссу мы адаптируем порог для получения двоичного изображения
Отсюдамы находим контуры и фильтруем, используя область контура для удаления мелких шумовых частиц и большой границы.Мы рисуем любые контуры, которые пропускают этот фильтр, на маску
Чтобы определить угол, мы разделим изображение пополам на основе размера изображения.Если width > height
, то это должно быть горизонтальное изображение, поэтому мы делим пополам по вертикали.если height > width
, то это должно быть вертикальное изображение, поэтому мы делим пополам по горизонтали
Теперь, когда мыесть две половины, мы можем использовать cv2.countNonZero()
, чтобы определить количество белых пикселей на каждой половине.Вот логика для определения угла:
if horizontal
if left >= right
degree -> 0
else
degree -> 180
if vertical
if top >= bottom
degree -> 270
else
degree -> 90
влево 9703
вправо 3975
Следовательно, изображение составляет 0 градусов.Вот результаты из других направлений
слева 3975
справа 9703
Можно сделать вывод, что изображение перевернуто на 180 градусов
Вот результаты для изображения по вертикали.Обратите внимание, что поскольку это вертикальное изображение, мы разделяем по горизонтали
сверху 3947
снизу 9550
Таким образом, результат равен 90градусы
import cv2
import numpy as np
def detect_angle(image):
mask = np.zeros(image.shape, dtype=np.uint8)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
blur = cv2.GaussianBlur(gray, (3,3), 0)
adaptive = cv2.adaptiveThreshold(blur,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV,15,4)
cnts = cv2.findContours(adaptive, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
area = cv2.contourArea(c)
if area < 45000 and area > 20:
cv2.drawContours(mask, [c], -1, (255,255,255), -1)
mask = cv2.cvtColor(mask, cv2.COLOR_BGR2GRAY)
h, w = mask.shape
# Horizontal
if w > h:
left = mask[0:h, 0:0+w//2]
right = mask[0:h, w//2:]
left_pixels = cv2.countNonZero(left)
right_pixels = cv2.countNonZero(right)
return 0 if left_pixels >= right_pixels else 180
# Vertical
else:
top = mask[0:h//2, 0:w]
bottom = mask[h//2:, 0:w]
top_pixels = cv2.countNonZero(top)
bottom_pixels = cv2.countNonZero(bottom)
return 90 if bottom_pixels >= top_pixels else 270
if __name__ == '__main__':
image = cv2.imread('1.png')
angle = detect_angle(image)
print(angle)