У меня есть 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?
Да, но вы должны понимать, что выходное изображение может быть очень большим. Я быстро написал следующий код 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. (См. Учебное пособие по Bitmask 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)
Первое изображение:
Второе изображение:
Сшитое изображение: