Как показать все изображение при использовании OpenCV warpPerspective
У меня есть 2 тестовых изображения здесь. Мой вопрос в том, как сопоставить квадрат на первом изображении с четырехугольником на втором изображении, не обрезая изображение.
Изображение 1:
Изображение 2:
Вот мой текущий код с использованием функции openCV warpPerspective.
import cv2
import numpy as np
img1_square_corners = np.float32([[253,211], [563,211], [563,519],[253,519]])
img2_quad_corners = np.float32([[234,197], [520,169], [715,483], [81,472]])
h, mask = cv2.findHomography(img1_square_corners, img2_quad_corners)
im = cv2.imread("image1.png")
out = cv2.warpPerspective(im, h, (800,800))
cv2.imwrite("result.png", out)
Результат:
Как вы можете видеть, из-за параметра dsize=(800 800) в функции warpPerspective я не могу получить полный просмотр изображения 1. Если я настрою dsize, квадрат не будет отображаться должным образом. Есть ли способ изменить размер выходного изображения, чтобы я мог получить полное изображение изображения 1?
3 ответа
Да, но вы должны понимать, что выходное изображение может быть очень большим. Я быстро написал следующий код Python, но даже изображение размером 3000 x 3000 не умещалось в вывод, оно слишком велико из-за преобразования. Хотя, вот мой код, надеюсь, он будет вам полезен.
import cv2
import numpy as np
import cv #the old cv interface
img1_square_corners = np.float32([[253,211], [563,211], [563,519],[253,519]])
img2_quad_corners = np.float32([[234,197], [520,169], [715,483], [81,472]])
h, mask = cv2.findHomography(img1_square_corners, img2_quad_corners)
im = cv2.imread("image1.png")
Создайте выходное изображение здесь, я использовал (3000, 3000) в качестве примера.
out_2 = cv.fromarray(np.zeros((3000,3000,3),np.uint8))
Используя старый cv
Интерфейс, я написал непосредственно к выходу, и поэтому он не обрезается. Я попробовал это с помощью cv2
интерфейс, но по какой-то причине он не работает... Может быть, кто-то может пролить свет на это?
cv.WarpPerspective(cv.fromarray(im), out_2, cv.fromarray(h))
cv.ShowImage("test", out_2)
cv.SaveImage("result.png", out_2)
cv2.waitKey()
Во всяком случае, это дает очень большое изображение, которое содержит исходное изображение 1, деформированное. Все изображение будет видно, если вы укажете, что выходное изображение будет достаточно большим. (Который может быть очень большим на самом деле!)
Я надеюсь, что этот код может помочь вам.
Мое решение состоит в том, чтобы рассчитать размер изображения результата, а затем сделать перевод.
def warpTwoImages(img1, img2, H):
'''warp img2 to img1 with homograph H'''
h1,w1 = img1.shape[:2]
h2,w2 = img2.shape[:2]
pts1 = float32([[0,0],[0,h1],[w1,h1],[w1,0]]).reshape(-1,1,2)
pts2 = float32([[0,0],[0,h2],[w2,h2],[w2,0]]).reshape(-1,1,2)
pts2_ = cv2.perspectiveTransform(pts2, H)
pts = concatenate((pts1, pts2_), axis=0)
[xmin, ymin] = int32(pts.min(axis=0).ravel() - 0.5)
[xmax, ymax] = int32(pts.max(axis=0).ravel() + 0.5)
t = [-xmin,-ymin]
Ht = array([[1,0,t[0]],[0,1,t[1]],[0,0,1]]) # translate
result = cv2.warpPerspective(img2, Ht.dot(H), (xmax-xmin, ymax-ymin))
result[t[1]:h1+t[1],t[0]:w1+t[0]] = img1
return result
dst_pts = float32([kp1[m.queryIdx].pt for m in good]).reshape(-1,1,2)
src_pts = float32([kp2[m.trainIdx].pt for m in good]).reshape(-1,1,2)
M, mask = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC, 5.0)
result = warpTwoImages(img1_color, img2_color, M)
Во-первых, следуйте более раннему решению, чтобы вычислить матрицу гомографии. После того, как у вас есть матрица гомографии, вам нужно деформировать изображение относительно матрицы гомографии. Наконец, объедините искаженное изображение.
Здесь я поделюсь другой идеей, которая может быть использована для объединения искаженных изображений. (В предыдущем ответе для наложения использовался ряд индексов, здесь я использую маскирование ROI)
Маска области интереса (ROI) и изображения с черным. Затем добавьте изображение с ROI. (См. Руководство по битовой маске OpenCV)
def copyOver(source, destination):
result_grey = cv2.cvtColor(source, cv2.COLOR_BGR2GRAY)
ret, mask = cv2.threshold(result_grey, 10, 255, cv2.THRESH_BINARY)
mask_inv = cv2.bitwise_not(mask)
roi = cv2.bitwise_and(source, source, mask=mask)
im2 = cv2.bitwise_and(destination, destination, mask=mask_inv)
result = cv2.add(im2, roi)
return result
warpedImageB = cv2.warpPerspective(imageB, H, (imageA.shape[1], imageA.shape[0]))
result = copyOver(imageA, warpedImageB)
Первое изображение:
Второе изображение: