Не самый простой cv2.remap () тест, он же. как использовать remap () в python?
вот самый простой возможный тестовый пример для remap ():
import cv2
import numpy as np
inimg = np.arange(2*2).reshape(2,2).astype(np.float32)
inmap = np.array([[0,0],[0,1],[1,0],[1,1]]).astype(np.float32)
outmap = np.array([[10,10],[10,20],[20,10],[20,20]]).astype(np.float32)
outimg = cv2.remap(inimg,inmap,outmap,cv2.INTER_LINEAR)
print "inimg:",inimg
print "inmap:",inmap
print "outmap:",outmap
print "outimg:", outimg
и вот вывод:
inimg: [[ 0. 1.]
[ 2. 3.]]
inmap: [[ 0. 0.]
[ 0. 1.]
[ 1. 0.]
[ 1. 1.]]
outmap: [[ 10. 10.]
[ 10. 20.]
[ 20. 10.]
[ 20. 20.]]
outimg: [[ 0. 0.]
[ 0. 0.]
[ 0. 0.]
[ 0. 0.]]
Как вы можете видеть, outimg производит 0,0, и дело даже не в правильной форме. Я ожидаю изображение 20x20 или 10x10 с интерполированными значениями из диапазона от 0 до 3.
Я прочитал всю документацию. Он и все на SO заявляет, что вы вводите массив (карту) начальных точек, карту конечных точек, а затем remap () поместит все значения в img в их новые позиции, интерполируя любое пустое пространство. Я делаю это, но это не работает. Почему? Большинство примеров для C++. Он сломан в python?
1 ответов
напротив направлении от того, что я ожидал сначала.
что remap()
не сделать, это взять координаты исходного изображения, преобразовать точки, а затем интерполировать. Что?!--4--> тут do is, для каждого пикселя в назначения изображения, поиск откуда он берется в исходном изображении, а затем назначает интерполированное значение. Он должен работать таким образом, так как для интерполяции ему нужно смотреть на значения вокруг исходного изображения в каждом пикселе. Позвольте мне расширить (может повториться немного, но не поймите это неправильно).
с remap()
docs:
Карта 1 – первая карта либо
(x,y)
точки или простоx
значения типаCV_16SC2
,CV_32FC1
илиCV_32FC2
. См.convertMaps()
для получения подробной информации о преобразовании представления с плавающей запятой в фиксированную точку для скорости.map2 – вторая карта
y
значения типаCV_16UC1
,CV_32FC1
, или нет (пустая карта еслиmap1
is(x,y)
балла), соответственно.
глагол здесь на map1
с"первый карта..."несколько вводит в заблуждение. Помните, что это строго координаты того, где ваше изображение отображается С...точки отображаются С src
at map_x(x, y), map_y(x, y)
и затем в dst
at x, y
. И они должны быть той же формы изображения, которое вы хотите деформировать их до. Обратите внимание на уравнение, показанное в документах:
dst(x,y) = src(map_x(x,y),map_y(x,y))
здесь map_x(x, y)
смотрит вверх map_x
в строках и столбцы, приведенные x, y
. Затем изображение оценивается в этих точках. Он ищет отображенные координаты x, y
на src
, а затем присвоение этого значения x, y
на dst
. Если вы будете смотреть на это достаточно долго, это начнет иметь смысл. На pixel (0, 0)
в новом изображении назначения я смотрю на map_x
и map_y
которые говорят мне местоположение соответствующего пикселя в исходном изображении, а затем я могу назначить интерполированное значение в (0, 0)
в пункт назначения изображение, глядя на близкие значения в источнике. Это основная причина, почему remap()
работает таким образом; он должен знать откуда появился пиксель таким образом, он может видеть соседние пиксели для интерполяции.
img = np.uint8(np.random.rand(8, 8)*255)
#array([[230, 45, 153, 233, 172, 153, 46, 29],
# [172, 209, 186, 30, 197, 30, 251, 200],
# [175, 253, 207, 71, 252, 60, 155, 124],
# [114, 154, 121, 153, 159, 224, 146, 61],
# [ 6, 251, 253, 123, 200, 230, 36, 85],
# [ 10, 215, 38, 5, 119, 87, 8, 249],
# [ 2, 2, 242, 119, 114, 98, 182, 219],
# [168, 91, 224, 73, 159, 55, 254, 214]], dtype=uint8)
map_y = np.array([[0, 1], [2, 3]], dtype=np.float32)
map_x = np.array([[5, 6], [7, 10]], dtype=np.float32)
mapped_img = cv2.remap(img, map_x, map_y, cv2.INTER_LINEAR)
#array([[153, 251],
# [124, 0]], dtype=uint8)
так, что здесь происходит? Помните, что это индексы img
это будет отображаться на строку и столбец, в которых они расположены. В этом случае проще всего изучить матрицы:
map_y
=====
0 1
2 3
map_x
=====
5 6
7 10
таким образом, целевое изображение в (0, 0) имеет то же значение, что и исходное изображение в map_y(0, 0), map_x(0, 0) = 0, 5
и исходное изображение в строке 0 и столбце 5 равно 153. Обратите внимание, что в целевом изображении mapped_img[0, 0] = 153
. Интерполяция здесь не происходит, так как мои координаты карты являются точными целыми числами. Также я включил индекс out-of-bounds (map_x[1, 1] = 10
, который больше ширины изображения), и обратите внимание, что ему просто присваивается значение 0
когда он за пределами.
полный пример использования
вот полноценный пример кода, используя гомографию земной правды, деформируя местоположения пикселей вручную и используя remap()
чтобы затем отобразить изображение из преобразованных точек. Обратите внимание, что моя гомография преобразует true_dst
до src
. Таким образом, я создаю множество точек, сколько хочу, а затем вычисляю, где эти точки лежат в исходном изображении, преобразуясь с помощью гомографии. Тогда remap()
используется для поиска этих точек в исходном изображении и сопоставления их с целевым изображением.
import numpy as np
import cv2
# read images
true_dst = cv2.imread("img1.png")
src = cv2.imread("img2.png")
# ground truth homography from true_dst to src
H = np.array([
[8.7976964e-01, 3.1245438e-01, -3.9430589e+01],
[-1.8389418e-01, 9.3847198e-01, 1.5315784e+02],
[1.9641425e-04, -1.6015275e-05, 1.0000000e+00]])
# create indices of the destination image and linearize them
h, w = true_dst.shape[:2]
indy, indx = np.indices((h, w), dtype=np.float32)
lin_homg_ind = np.array([indx.ravel(), indy.ravel(), np.ones_like(indx).ravel()])
# warp the coordinates of src to those of true_dst
map_ind = H.dot(lin_homg_ind)
map_x, map_y = map_ind[:-1]/map_ind[-1] # ensure homogeneity
map_x = map_x.reshape(h, w).astype(np.float32)
map_y = map_y.reshape(h, w).astype(np.float32)
# remap!
dst = cv2.remap(src, map_x, map_y, cv2.INTER_LINEAR)
blended = cv2.addWeighted(true_dst, 0.5, dst, 0.5, 0)
cv2.imshow('blended.png', blended)
cv2.waitKey()
картинки и наземных homographies от группа визуальной геометрии в Оксфорде.