什么是重映射
把一副圖像內(nèi)的像素點放置到另一幅圖像內(nèi)的指定位置,這個過程我們稱為重映射。簡單點理解,也就是copy一個圖像到另一個圖像中。
在OpenCV中,它給我們提供了cv2.remap()函數(shù)作為重映射,其定義如下:
def remap(src, map1, map2, interpolation, dst=None, borderMode=None, borderValue=None):
src:代表原始圖像
map1:可以表示(x,y)點的一個映射,也可以表示CV_16SC2、CV_32FC1、CV_32FC2類型(x,y)點的x值
map2:當前map1表示(x,y)點的一個映射時,該值為空。當map1表示CV_16SC2、CV_32FC1、CV_32FC2類型(x,y)點的x值時,該值時CV_16UC1、CV_32FC1類型(x,y)點的y值。
interpolation,borderMode,borderValue與前文類似。
需要注意,map1指代的是像素點所在位置的列號,map2指代的是像素點所在位置的行號。
copy像素點
現(xiàn)在我們假設(shè)有一個需求,將目標圖像內(nèi)的所有像素點都映射為原始圖像內(nèi)的第100行,200列上的像素點。具體實現(xiàn)如下:
import cv2
import numpy as np
img = cv2.imread("4.jpg")
rows, cols, ch = img.shape
mapx = np.ones(img.shape[:2], np.float32) * 200
mapy = np.ones(img.shape[:2], np.float32) * 100
result_img = cv2.remap(img, mapx, mapy, cv2.INTER_LINEAR)
cv2.imshow("img", img)
cv2.imshow("result_img", result_img)
cv2.waitKey()
cv2.destroyAllWindows()
如上面代碼所示,我們將所有像素點都設(shè)置為原始圖像(100,200)點的像素點,會得到一個非常純色的圖像,效果如下所示:

copy整個圖像
那么既然能copy某個像素點,那么也肯定能copy整個圖像。下面,我們將上圖左邊的圖像全部copy到右邊,具體代碼如下:
import cv2
import numpy as np
img = cv2.imread("4.jpg")
rows, cols, ch = img.shape
mapx = np.ones(img.shape[:2], np.float32)
mapy = np.ones(img.shape[:2], np.float32)
for i in range(rows):
for j in range(cols):
mapx.itemset((i,j),j)#設(shè)置每個點映射原圖的Y坐標
mapy.itemset((i,j),i)#設(shè)置每個點映射原圖的X坐標
result_img = cv2.remap(img, mapx, mapy, cv2.INTER_LINEAR)
cv2.imshow("img", img)
cv2.imshow("result_img", result_img)
cv2.waitKey()
cv2.destroyAllWindows()
這里,我們將所有點映射到所有點,每個像素點一一對應(yīng),就完成了copy原圖像。運行之后,效果如下所示:

繞X軸翻轉(zhuǎn)
通過cv2.remap()函數(shù),我們不僅可以重映射像素點,還可以翻轉(zhuǎn)過來映射,也就是通過它實現(xiàn)X軸的翻轉(zhuǎn)效果,只要保證X軸不變,并且Y坐標值以X軸為對稱進行交換即可。
修改上面代碼中的某一行,代碼如下:
import cv2
import numpy as np
img = cv2.imread("4.jpg")
rows, cols, ch = img.shape
mapx = np.ones(img.shape[:2], np.float32)
mapy = np.ones(img.shape[:2], np.float32)
for i in range(rows):
for j in range(cols):
mapx.itemset((i,j),j)
mapy.itemset((i,j),rows-1-i)#修改這一行即可,對稱
result_img = cv2.remap(img, mapx, mapy, cv2.INTER_LINEAR)
cv2.imshow("img", img)
cv2.imshow("result_img", result_img)
cv2.waitKey()
cv2.destroyAllWindows()
運行之后,我們得到了繞X軸翻轉(zhuǎn)的圖像,效果如下:

繞Y軸翻轉(zhuǎn)
既然我們可以通過cv2.remap()函數(shù)繞X翻轉(zhuǎn),那么肯定的也可以繞Y軸翻轉(zhuǎn),只要將X坐標值以Y軸為對稱進行交換即可。
話不多說,直接上代碼:
import cv2
import numpy as np
img = cv2.imread("4.jpg")
rows, cols, ch = img.shape
mapx = np.ones(img.shape[:2], np.float32)
mapy = np.ones(img.shape[:2], np.float32)
for i in range(rows):
for j in range(cols):
mapx.itemset((i,j),cols-1-j)#修改這一行即可
mapy.itemset((i,j),i)#
result_img = cv2.remap(img, mapx, mapy, cv2.INTER_LINEAR)
cv2.imshow("img", img)
cv2.imshow("result_img", result_img)
cv2.waitKey()
cv2.destroyAllWindows()
運行之后,我們得到繞Y軸翻轉(zhuǎn)的圖像:

繞XY軸翻轉(zhuǎn)
那么繞XY軸一起翻轉(zhuǎn)呢?這里二行代碼一起更改:
import cv2
import numpy as np
img = cv2.imread("4.jpg")
rows, cols, ch = img.shape
mapx = np.ones(img.shape[:2], np.float32)
mapy = np.ones(img.shape[:2], np.float32)
for i in range(rows):
for j in range(cols):
mapx.itemset((i,j),cols-1-j)
mapy.itemset((i,j),rows-1-i)
result_img = cv2.remap(img, mapx, mapy, cv2.INTER_LINEAR)
cv2.imshow("img", img)
cv2.imshow("result_img", result_img)
cv2.waitKey()
cv2.destroyAllWindows()
運行之后,效果如下所示:

壓縮一半
也就是將原圖縮小一般,按將Y軸縮小一般,只需要將X軸設(shè)置為2倍即可。具體代碼如下所示:
import cv2
import numpy as np
img = cv2.imread("4.jpg")
rows, cols, ch = img.shape
mapx = np.ones(img.shape[:2], np.float32)
mapy = np.ones(img.shape[:2], np.float32)
for i in range(rows):
for j in range(cols):
mapx.itemset((i,j),j)
mapy.itemset((i,j),2*i)#修改這行代碼即可
result_img = cv2.remap(img, mapx, mapy, cv2.INTER_LINEAR)
cv2.imshow("img", img)
cv2.imshow("result_img", result_img)
cv2.waitKey()
cv2.destroyAllWindows()
運行之后,效果顯示如下:

既然能壓縮,意味著也可以實現(xiàn)縮小,縮小的具體實現(xiàn),可以當作訓練的習題,方便大家鞏固掌握,博主在這里就不在贅述了。