Я создаю приложение, которое использует ручную калибровку для выравнивания двух изображений. Я пытаюсь выровнять их почти идеально по пикселям, поэтому я не полагаюсь на автоматическую калибровку, так как она не сработала наилучшим образом для этого сценария. Я делаю это вручную, выбирая пиксели. Однако результат не тот, на который я рассчитывал, и я не знаю, где я ошибаюсь. Я чувствую, что вычисленные точки должны размещать изображение точно поверх другого, но по какой-то причине это не так. Что я делаю не так?
Результаты гомографии:
[[ 7.43200521e-01 -1.79170744e-02 -1.76782990e+02]
[ 1.00046389e-02 7.84106136e-01 -3.22549155e+01]
[ 5.10695284e-05 -8.48641135e-05 1.00000000e+00]]
Точки, выбранные вручную: RGB:
[[ 277 708]
[1108 654]
[ 632 545]
[ 922 439]
[ 874 403]
[ 398 376]
[ 409 645]
[ 445 593]
[ 693 342]
[ 739 244]
[ 505 234]
[ 408 275]
[ 915 162]
[1094 126]
[ 483 115]
[ 951 366]
[ 517 355]]
Термальный:
[[ 8 549]
[634 491]
[282 397]
[496 318]
[461 289]
[113 269]
[122 479]
[148 438]
[325 236]
[360 162]
[194 156]
[121 188]
[484 106]
[621 67]
[178 62]
[515 261]
[203 253]]
def manual_calibration(self, rgb: cv2.UMat, thermal: cv2.UMat) -> Tuple[cv2.UMat, Tuple[int, int, int, int]]:
rgb_gray = cv2.cvtColor(rgb, cv2.COLOR_BGR2GRAY)
thermal_gray = cv2.cvtColor(thermal, cv2.COLOR_BGR2GRAY)
h_rgb, w_rgb = rgb_gray.shape
h_th, w_th = thermal_gray.shape
thermal_gray = cv2.copyMakeBorder(thermal_gray, 0, h_rgb - h_th, 0, 0, cv2.BORDER_CONSTANT, value=[0, 0, 0])
merged = cv2.hconcat((rgb_gray, thermal_gray))
self.merged = cv2.cvtColor(merged, cv2.COLOR_GRAY2RGB)
def point_validation(ix, iy):
if ix > w_rgb:
ix -= w_rgb
return ix, iy
self.points_left = np.array([])
self.points_right = np.array([])
self.label = True
def select_point(event, x, y, flags, param):
if event == cv2.EVENT_LBUTTONDOWN: # captures left button double-click
ix, iy = x, y
cv2.circle(img=self.merged, center=(x,y), radius=5, color=(0,255,0),thickness=-1)
ix, iy = point_validation(ix, iy)
pt = np.array([ix, iy])
if self.label:
# self.points_left = np.vstack((self.points_left, pt))
self.points_left = np.vstack((self.points_left, pt)) if self.points_left.size else pt
self.label = False
else:
# self.points_right = np.vstack((self.points_right, pt))
self.points_right = np.vstack((self.points_right, pt)) if self.points_right.size else pt
self.label = True
print(ix, iy)
cv2.namedWindow('calibration')
cv2.setMouseCallback('calibration', select_point)
while True:
cv2.imshow("calibration", self.merged)
if cv2.waitKey(20) & 0xFF == 27:
break
cv2.destroyAllWindows()
print(self.points_left)
print(self.points_right)
### EDIT NEW POINT VALIDATION
rgb_gray_check = rgb_gray
thermal_gray_check = thermal_gray
for point in self.points_left:
cv2.circle(img=rgb_gray_check, center=point, radius=5, color=(0,255,0),thickness=-1)
for point in self.points_right:
cv2.circle(img=thermal_gray_check, center=point, radius=5, color=(0,255,0),thickness=-1)
cv2.imshow('rgb', rgb_gray_check)
cv2.imshow('thermal', thermal_gray_check)
cv2.waitKey(0)
### EDIT NEW POINT VALIDATION
# Compute homography
# 0 - a regular method using all the points
# CV_RANSAC - RANSAC-based robust method
# CV_LMEDS - Least-Median robust method
matrix, mask = cv2.findHomography(self.points_left, self.points_right, 0)
print(matrix)
# matrix[0][3] += (w_th/2)
# matrix[1][3] += (h_th/2)
warp_src = cv2.warpPerspective(thermal, matrix, (rgb.shape[1], rgb.shape[0]))
alpha = 0.5
beta = (1.0 - alpha)
dst_warp_blended = cv2.addWeighted(rgb, alpha, warp_src, beta, 0.0)
cv2.imshow('Blended destination and warped image', dst_warp_blended)
cv2.waitKey(0)
Исходные изображения:
Мой результат:
@Micka Я пробовал четыре и даже больше. Кажется, это никогда не работает. Я подозреваю, что это связано с разными разрешениями, но я чувствую, что гомография должна решить эту проблему. Так что я думаю, что это из-за кода... но я понятия не имею, что это такое
Разрешение не важно, пока вы переходите к целевому разрешению. Если найду время, завтра подробно проверю ваши пункты.
Так я понял это!
Я случайно перевернул параметры в функции findHomography. Так и должно быть
matrix, mask = cv2.findHomography(self.points_right, self.points_left, 0)
И, конечно же, удалите смещение для матрицы гомографии.
Хорошо, что я некоторое время возился с этим и получил несколько странных изображений.
Можете ли вы попробовать использовать только 4 соответствия? Если они не идеально выравниваются после деформации, что-то в вашем коде не так. Если деформация подходит для этих 4 точек, скорее всего, что-то не так с некоторыми из ваших точек или с общей настройкой (деформация перспективы не может решить все виды преобразований изображения в изображение, такие как искажение объектива или произвольное движение сенсора).