Я столкнулся с подобной проблемой, и вот как я решил ее (на самом деле, очень похоже на ваш метод), просто я использовал get матрицу вращения вместо гомографии:
- read image
- детектор края
грубая линия, чтобы получить все линии (с наклоном внутри определенного интервала)
lines = cv.HoughLinesP(img, 1, np.pi/180, 100, minLineLength=100, maxLineGap=10)
получить средний наклон линий, вызвать вВ моем случае у меня было много параллельных линий для использования в качестве ссылок, и таким образом я смог получить лучший результат
for line in lines:
x1,y1,x2,y2 = line[0]
if (x2-x1) != 0:
angle = math.atan((float(y2-y1))/float((x2-x1))) * 180 / math.pi
else:
angle = 90
#you can skip this test if you have no info about the lines you re looking for
#in this case offset_angle is = 0
if min_angle_threshold <= angle <= max_angle_threshold:
tot_angle = tot_angle + angle
cnt = cnt + 1
average_angle = (tot_angle / cnt) - offset_angle
применить встречное вращение
center = your rotation center - probably the center of the image
rotation_matrix = cv.getRotationMatrix2D(center, angle, 1.0)
height, width = img.shape
rotated_image = cv.warpAffine(img, rotation_matrix, (width, height))
#do whatever you want, then rotate image back
counter_rotation_matrix = cv.getRotationMatrix2D(center, -angle, 1.0)
original_image = cv.warpAffine( rotated_image, counter_rotation_matrix, (width, height))
Редактировать: см. Полный пример здесь:
import math
import cv2 as cv
img = cv.imread('C:\\temp\\test_3.jpg',0)
edges = cv.Canny(img,100,200)
lines = cv.HoughLinesP(edges[0:50,:], 1, np.pi/180, 50, minLineLength=10, maxLineGap=10)
tot_angle = 0
cnt = 0
for line in lines:
x1,y1,x2,y2 = line[0]
if (x2-x1) != 0:
angle = math.atan((float(y2-y1))/float((x2-x1))) * 180 / math.pi
else:
angle = 90
if -30 <= angle <= 30:
tot_angle = tot_angle + angle
cnt = cnt + 1
average_angle = (tot_angle / cnt)
h,w = img.shape[:2]
center = w/2, h/2
rotation_matrix = cv.getRotationMatrix2D(center, average_angle, 1.0)
height, width = img.shape
rotated_image = cv.warpAffine(img, rotation_matrix, (width, height))
cv.imshow("roto", rotated_image)
#do all your stuff here, add text and whatever
#...
#...
counter_rotation_matrix = cv.getRotationMatrix2D(center, -average_angle, 1.0)
original_image = cv.warpAffine( rotated_image, counter_rotation_matrix, (width, height))
cv.imshow("orig", original_image)
повернуто
] 1
counter_rotated
] 2
РЕДАКТИРОВАТЬ:
в случае, если вы хотите применить гомографию (отличается от простопростой поворот, потому что он также применяет перспективное преобразование), ниже кода, чтобы заставить его работать:
#very basic example, similar to your code with fixed terms
l = np.array([(11,32),(43,215),(142,1),(205,174)])
lt = np.array([(43,32),(43,215),(205,32),(205,215)])
h, status = cv.findHomography(l,lt)
im_out = cv.warpPerspective(img, h, (img.shape[1],img.shape[0]))
Чтобы сделать это программно - для «l»: просто используйтеКроме того, наберите 4 угла, затем добавьте их
для «lt»: найдите «пункт назначения» для всех 4 точек, например, используйте нижние углы в качестве ссылки
lines = cv.HoughLinesP(edges, 1, np.pi/180, 100, minLineLength=150, maxLineGap=5)
l = []
for line in lines:
x1,y1,x2,y2 = line[0]
if (x2-x1) != 0:
angle = math.atan((float(y2-y1))/float((x2-x1))) * 180 / math.pi
else:
angle = 90
# consider only vertical edges
if 60 <= angle:
l.append((x1,y1))
l.append((x2,y2))
x_values.append(max(x1,x2))
if len(y_values) == 0:
y_values.append(y1)
y_values.append(y2)
l = np.array(l)
lt = np.array([(x_values[0],y_values[0]),(x_values[0],y_values[1]),(x_values[1],y_values[0]),(x_values[1],y_values[1])])
, затем вызовите findhomography, как сделано выше. Надеюсь, это достаточно ясно!
3