Как показать все изображение при использовании OpenCV warpPerspective

15

У меня есть 2 тестовых изображения. Я задаюсь вопросом, как отобразить квадрат в первом изображении на четырехугольник во втором изображении без обрезки изображения.

Изображение 1: Изображение 33645

Изображение 2: Изображение 33646

Вот мой текущий код, используя функцию 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)

Результат: Изображение 33647

Как вы можете видеть из-за параметра dsize = (800,800) в функции warpPerspective, я не могу получить полный вид изображения 1. Если я отрегулирую dsize, квадрат не будет правильно отображаться. Есть ли способ изменить размер выходного изображения, чтобы я мог получить полную картину изображения 1?

  • 0
    Не могли бы вы уточнить: «Если я настрою размер, квадрат не будет отображаться правильно»? Это деформировано? в переводе? масштабируется? ЭСТ. Было бы полезно другое изображение
Теги:
opencv
image-processing
numpy
computer-vision

3 ответа

8
Лучший ответ

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

Я надеюсь, что этот код может вам помочь.

  • 0
    Сначала я собирался добавить фактор перевода в гомографию, получить виды различных областей преобразованного изображения, а затем объединить их. Но ваше решение кажется лучше! Спасибо!
  • 0
    Нет проблем, я рад, что мое решение помогло вам.
27

Мое решение состоит в том, чтобы вычислить размер изображения результата, а затем выполнить перевод.

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)

Изображение 136105

1

Сначала следуйте более раннему решению вычислить матрицу гомографии. После того, как у вас есть матрица гомографии, вам нужно деформировать изображение по отношению к матрице гомографии. Наконец, объедините искаженное изображение.

Здесь я расскажу о другой идее, которая может быть использована для слияния искаженных изображений. (Более ранний ответ использует диапазон индексов для наложения, здесь я использую маскирование 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)

Первое изображение:

Изображение 136106

Второе изображение:

Изображение 136107

Сшитое изображение: Изображение 136108

  • 0
    Существует ли автоматический способ удаления лишних «черных» областей для сшиваемого изображения? Или деформируйте сшитое изображение, чтобы заполнить всю область изображения?
  • 0
    @MarkToledo Я не пробовал, но, возможно, вы могли бы попытаться найти самый большой ограничивающий прямоугольник и обрезать его. Хотя я не пробовал, но могу предвидеть, что это не легко.
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню