Вот подход, основанный на предположении, что большая часть текста перекошена в одну сторону.Идея состоит в том, что мы можем определить угол на основе расположения основной текстовой области
- . Преобразовать изображение в оттенки серого и размытие по Гауссу
- Адаптивный порог для получения двоичного изображения
- Поиск контуров и фильтрация по области контуров
- Создание отфильтрованных контуров на маске
- Разделение изображения по горизонтали или вертикали в зависимости от ориентации
- Подсчет количества пикселей в каждой половине
После преобразования в оттенки серого и размытие по Гауссу мы адаптируем порог для получения двоичного изображения
![enter image description here](https://i.stack.imgur.com/EnxLc.png)
Отсюдамы находим контуры и фильтруем, используя область контура для удаления мелких шумовых частиц и большой границы.Мы рисуем любые контуры, которые пропускают этот фильтр, на маску
![enter image description here](https://i.stack.imgur.com/xVFYi.png)
Чтобы определить угол, мы разделим изображение пополам на основе размера изображения.Если width > height
, то это должно быть горизонтальное изображение, поэтому мы делим пополам по вертикали.если height > width
, то это должно быть вертикальное изображение, поэтому мы делим пополам по горизонтали
![enter image description here](https://i.stack.imgur.com/aS8ko.png)
Теперь, когда мыесть две половины, мы можем использовать 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 градусов.Вот результаты из других направлений
![enter image description here](https://i.stack.imgur.com/2uuux.png)
слева 3975
справа 9703
Можно сделать вывод, что изображение перевернуто на 180 градусов
Вот результаты для изображения по вертикали.Обратите внимание, что поскольку это вертикальное изображение, мы разделяем по горизонтали
![enter image description here](https://i.stack.imgur.com/MlNBz.png)
![enter image description here](https://i.stack.imgur.com/GC676.png)
сверху 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)