Вместо того, чтобы находить линии, я предлагаю найти цветную область.
Если область находится на правой стороне изображения, изображение необходимо повернуть.
Нахождение цветной области можно выполнить следующим образом:
- Вычислить абсолютную разницу между каждыми двумя цветными каналами и суммировать результат.
Результат имеет высокие значения, где есть цвет (не черный / белый). - Применить порог - значения ниже порога будут равны нулю (считается черно-белым), а порог выше 255 (цветные пиксели).
- Найдите самый большой кластер в пороговом изображении, используя connectedComponentsWithStats .
- Если центр наибольшего белого кластера находится справа, поверните изображение.
Вот пример кода:
import numpy as np
import cv2
im = cv2.imread("rotate_me1.png", cv2.IMREAD_UNCHANGED);
# Compute difference between each two color channels for finding colored pixels.
cdiff = cv2.absdiff(im[:,:,0], im[:,:,1])//3 + cv2.absdiff(im[:,:,0], im[:,:,2])//3 + cv2.absdiff(im[:,:,1], im[:,:,2])//3;
ret, cmask = cv2.threshold(cdiff, 10, 255, cv2.THRESH_BINARY)
# Find clusters.
# https://answers.opencv.org/question/194566/removing-noise-using-connected-components/
nlabel,labels,stats,centroids = cv2.connectedComponentsWithStats(cmask, connectivity=8)
# Find second largest cluster (the largest is the background?):
stats[np.argmax(stats[:, cv2.CC_STAT_AREA])] = 0
idx_max_size = np.argmax(stats[:, cv2.CC_STAT_AREA])
center = centroids[idx_max_size]
# True if the center of the centroid is at the right side of the image
is_center_at_right_side = center[0] > im.shape[1]//2
if is_center_at_right_side:
rotated_im = im[::-1, ::-1, :].copy() # Reverse left/right and up/down
cv2.imshow('rotated_im', rotated_im)
# Draw green circle at the center (for testing)
cv2.circle(im, (int(center[0]), int(center[1])), 10, (0, 255, 0), thickness=10)
cv2.imshow('cmask', cmask)
cv2.imshow('im', im)
cv2.waitKey(0)
cv2.destroyAllWindows()
Пример для cmask
:
Маркировочный центр самого большого скопления с зеленым кружком:
Повернутое изображение:
Обновление:
Поворот на 90 градусов:
Результат: