什么是重映射?
重映射(Remapping)是圖像處理中的一種操作,用于將圖像中的像素從一個(gè)位置映射到另一個(gè)位置。重映射可以實(shí)現(xiàn)圖像的平移、旋轉(zhuǎn)、縮放和透視變換等效果。它是一種基于像素級(jí)的圖像變換技術(shù),可以通過定義映射關(guān)系來改變圖像的幾何形狀和外觀。
在重映射中,我們需要定義一個(gè)映射表(Map),這個(gè)映射表指定了源圖像中每個(gè)像素點(diǎn)在目標(biāo)圖像中的位置。對(duì)于每個(gè)像素點(diǎn) (x, y),映射表告訴我們?cè)谀繕?biāo)圖像中的新位置 (x’, y’)。通過對(duì)所有像素點(diǎn)進(jìn)行映射,我們就可以得到經(jīng)過重映射變換后的新圖像。
在OpenCV中,可以使用 cv2.remap() 函數(shù)來執(zhí)行重映射操作。cv2.remap() 接受輸入圖像和一個(gè)表示映射關(guān)系的兩個(gè)浮點(diǎn)型數(shù)組(map_x 和 map_y)。數(shù)組 map_x 和 map_y 的大小必須與輸入圖像的大小相同,并且每個(gè)元素 (x, y) 表示源圖像中的像素點(diǎn) (x, y) 在目標(biāo)圖像中的新位置 (x’, y’)。
重映射應(yīng)用場(chǎng)景?
重映射在圖像處理和計(jì)算機(jī)視覺領(lǐng)域有許多應(yīng)用場(chǎng)景。以下是一些常見的重映射應(yīng)用場(chǎng)景:
圖像畸變校正:相機(jī)鏡頭引起的畸變(如透視畸變、魚眼畸變等)會(huì)導(dǎo)致圖像中的直線彎曲或形狀失真。通過重映射技術(shù),可以校正這些畸變,使圖像看起來更加自然和真實(shí)。
圖像配準(zhǔn):在多幅圖像中找到對(duì)應(yīng)點(diǎn),并將它們對(duì)齊,使得它們?cè)谙嗤暯腔蜃鴺?biāo)系下表現(xiàn)一致。這在圖像拼接、全景圖像合成和多視角圖像處理中非常有用。
圖像穩(wěn)定:在視頻處理中,當(dāng)相機(jī)存在抖動(dòng)或運(yùn)動(dòng)時(shí),可以使用重映射技術(shù)來穩(wěn)定視頻,保持圖像內(nèi)容相對(duì)穩(wěn)定,減少抖動(dòng)效應(yīng)。
視角變換:通過重映射,可以改變圖像的視角,實(shí)現(xiàn)縮放、旋轉(zhuǎn)、平移和透視等效果,從而得到不同角度或大小的圖像。
增強(qiáng)現(xiàn)實(shí) (AR) 應(yīng)用:在AR應(yīng)用中,通過對(duì)現(xiàn)實(shí)世界圖像進(jìn)行重映射,將虛擬物體或信息疊加到真實(shí)世界中,實(shí)現(xiàn)真實(shí)與虛擬的交互效果。
圖像處理與濾波:重映射技術(shù)可以應(yīng)用于圖像處理中的濾波、圖像增強(qiáng)和特效處理,從而實(shí)現(xiàn)各種圖像變換和處理效果。
視頻流處理:在實(shí)時(shí)視頻流處理中,可以使用重映射技術(shù)對(duì)圖像進(jìn)行實(shí)時(shí)變換和校正,以滿足特定的需求。
這些只是重映射在圖像處理和計(jì)算機(jī)視覺中的一些常見應(yīng)用場(chǎng)景。實(shí)際上,重映射技術(shù)非常靈活和強(qiáng)大,可以在許多不同的領(lǐng)域中發(fā)揮重要作用,幫助我們處理和改善圖像數(shù)據(jù)。
映射參數(shù)的理解
OpenCV 內(nèi)的重映射函數(shù) cv2.remap()提供了更方便、更自由的映射方式,其語法格式如下:
dst = cv2.remap( src, map1, map2, interpolation[, borderMode[, borderValue]] )
式中:
? dst 代表目標(biāo)圖像,它和 src 具有相同的大小和類型。
? src 代表原始圖像。
? map1 參數(shù)有兩種可能的值:
? 表示(x,y)點(diǎn)的一個(gè)映射。
? 表示 CV_16SC2 , CV_32FC1, CV_32FC2 類型(x,y)點(diǎn)的 x 值。
? map2 參數(shù)同樣有兩種可能的值:
? 當(dāng) map1 表示(x,y)時(shí),該值為空。
? 當(dāng) map1 表示(x,y)點(diǎn)的 x 值時(shí),該值是 CV_16UC1, CV_32FC1 類型(x,y)點(diǎn)的 y 值。
? Interpolation 代表插值方式
? borderMode 代表邊界模式。當(dāng)該值為 BORDER_TRANSPARENT 時(shí),表示目標(biāo)圖像內(nèi)
的對(duì)應(yīng)源圖像內(nèi)奇異點(diǎn)(outliers)的像素不會(huì)被修改。
? borderValue 代表邊界值,該值默認(rèn)為 0。
重映射通過修改像素點(diǎn)的位置得到一幅新圖像。在構(gòu)建新圖像時(shí),需要確定新圖像中每個(gè)像素點(diǎn)在原始圖像中的位置。因此,映射函數(shù)的作用是查找新圖像像素在原始圖像內(nèi)的位置。該過程是將新圖像像素映射到原始圖像的過程,因此被稱為反向映射。在函數(shù) cv2.remap()中,參數(shù) map1 和參數(shù) map2 用來說明反向映射,map1 針對(duì)的是坐標(biāo) x,map2 針對(duì)的是坐標(biāo) y。
需要說明的是,map1 和 map2 的值都是浮點(diǎn)數(shù)。因此,目標(biāo)圖像可以映射回一個(gè)非整數(shù)的值,這意味著目標(biāo)圖像可以“反向映射”到原始圖像中兩個(gè)像素點(diǎn)之間的位置(當(dāng)然,該位置是不存在像素值的)。這時(shí),可以采用不同的方法實(shí)現(xiàn)插值,函數(shù)中的 interpolation 參數(shù)可以控制插值方式。正是由于參數(shù) map1 和參數(shù) map2 的值是浮點(diǎn)數(shù),所以通過函數(shù) cv2.remamp()所能實(shí)現(xiàn)的映射關(guān)系變得更加隨意,可以通過自定義映射參數(shù)實(shí)現(xiàn)不同形式的映射。
需要注意的是,函數(shù) cv2.remap()中參數(shù) map1 指代的是像素點(diǎn)所在位置的列號(hào),
參數(shù) map2 指代的是像素點(diǎn)所在位置的行號(hào)。例如,我們想將目標(biāo)圖像(映射結(jié)果圖像)中某個(gè)點(diǎn) A 映射
為原始圖像內(nèi)處于第 0 行第 3 列上的像素點(diǎn) B,那么需要將 A 點(diǎn)所對(duì)應(yīng)的參數(shù) map1 對(duì)應(yīng)位置上的值設(shè)為 3,參數(shù) map2 對(duì)應(yīng)位置上的值設(shè)為 0。
所以,通常情況下,我們將 map1 寫為 mapx,并且將 map2 寫成 mapy,以方便理解。
同樣,如果想將目標(biāo)圖像(映射結(jié)果圖像)中所有像素點(diǎn)都映射為原始圖像內(nèi)處于第 0 行
第 3 列上的像素點(diǎn) B,那么需要將參數(shù) map1 內(nèi)的值均設(shè)為 3,將參數(shù) map2 內(nèi)的值均設(shè)為 0。
實(shí)驗(yàn):
使用 cv2.remap()完成數(shù)組映射,將目標(biāo)數(shù)組內(nèi)的所有像素點(diǎn)都映射為原始圖像內(nèi)第 0 行第 3 列上的像素點(diǎn),以此來了解函數(shù) cv2.remap()內(nèi)參數(shù) map1 和 map2 的使
用情況。
根據(jù)題目要求,可以確定:
? 用來指定列的參數(shù) map1(mapx)內(nèi)的值均為 3。
? 用來指定行的參數(shù) map2(mapy)內(nèi)的值均為 0。
import cv2
import numpy as np
img=np.random.randint(0,256,size=[4,5],dtype=np.uint8)
rows,cols=img.shape
mapx = np.ones(img.shape,np.float32)*3
mapy = np.ones(img.shape,np.float32)*0
rst=cv2.remap(img,mapx,mapy,cv2.INTER_LINEAR)
print("img=\n",img)
print("mapx=\n",mapx)
print("mapy=\n",mapy)
print("rst=\n",rst)
運(yùn)行結(jié)果:
img=
[[253 90 32 65 181]
[187 184 148 12 212]
[157 229 255 138 115]
[156 38 62 89 241]]
mapx=
[[3. 3. 3. 3. 3.]
[3. 3. 3. 3. 3.]
[3. 3. 3. 3. 3.]
[3. 3. 3. 3. 3.]]
mapy=
[[0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0.]]
rst=
[[65 65 65 65 65]
[65 65 65 65 65]
[65 65 65 65 65]
[65 65 65 65 65]]
通過觀察上述結(jié)果可知,目標(biāo)圖像(數(shù)組)dst 內(nèi)的所有值都來源于原始圖像中第 0 行第 3
列上的像素值 65。
復(fù)制
為了更好地了解重映射函數(shù) cv2.remap()的使用方法,本節(jié)介紹如何通過該函數(shù)實(shí)現(xiàn)圖像的復(fù)制。在映射時(shí),將參數(shù)進(jìn)行如下處理:
? 將 map1 的值設(shè)定為對(duì)應(yīng)位置上的 x 軸坐標(biāo)值。
? 將 map2 的值設(shè)定為對(duì)應(yīng)位置上的 y 軸坐標(biāo)值。
通過上述處理后,可以讓函數(shù) cv2.remap()實(shí)現(xiàn)圖像復(fù)制。下面通過一個(gè)例題來觀察實(shí)現(xiàn)復(fù)
制時(shí),如何設(shè)置函數(shù) cv2.remap()內(nèi)的 map1 和 map2 參數(shù)的值。
使用函數(shù) cv2.remap()完成數(shù)組復(fù)制,了解函數(shù) cv2.remap()內(nèi)參數(shù) map1和 map2 的使用情況。
這里為了方便理解,將參數(shù) map1 定義為 mapx,將參數(shù) map2 定義為 mapy。后續(xù)程序中都采用了這種定義方式,后面不再重復(fù)說明。
import cv2
import numpy as np
img=np.random.randint(0,256,size=[4,5],dtype=np.uint8)
rows,cols=img.shape
mapx = np.zeros(img.shape,np.float32)
mapy = np.zeros(img.shape,np.float32)
for i in range(rows):
for j in range(cols):
mapx.itemset((i,j),j)
mapy.itemset((i,j),i)
rst=cv2.remap(img,mapx,mapy,cv2.INTER_LINEAR)
print("img=\n",img)
print("mapx=\n",mapx)
print("mapy=\n",mapy)
print("rst=\n",rst)
運(yùn)行程序,出現(xiàn)如下結(jié)果:
img=
[[151 137 24 88 216]
[ 8 112 205 130 44]
[ 78 106 1 134 85]
[190 55 135 56 64]]
mapx=
[[0. 1. 2. 3. 4.]
[0. 1. 2. 3. 4.]
[0. 1. 2. 3. 4.]
[0. 1. 2. 3. 4.]]
mapy=
[[0. 0. 0. 0. 0.]
[1. 1. 1. 1. 1.]
[2. 2. 2. 2. 2.]
[3. 3. 3. 3. 3.]]
rst=
[[151 137 24 88 216]
[ 8 112 205 130 44]
[ 78 106 1 134 85]
[190 55 135 56 64]]
通過本例可以觀察到,參數(shù) mapx 和參數(shù) mapy 分別設(shè)置了 x 軸方向的坐標(biāo)和 y 軸方向的
坐標(biāo)。函數(shù) cv2.remap()利用參數(shù) mapx、mapy 所組成的數(shù)組構(gòu)造的映射關(guān)系實(shí)現(xiàn)了圖像的復(fù)制。
例如,rst 中的像素點(diǎn)[3,4]在 src 內(nèi)的 x、y 軸坐標(biāo)如下:
? x 軸坐標(biāo)取決于 mapx 中 mapx[3,4]的值,為 4。
? y 軸坐標(biāo)取決于 mapy 中 mapy[3,4]的值,為 3。
這說明 rst[3,4]來源于原始圖像 src 的第 4 列(x 軸方向,由 mapx[3,4]決定)、第 3 行(y
軸方向,由 mapy[3,4]決定),即 rst[3,4]=src[3,4]。原始對(duì)象 src[3,4]的值為 64,所以目標(biāo)對(duì)象
rst[3,4]的值為 64。
像繞 x 軸的翻轉(zhuǎn)
import cv2
import numpy as np
img=cv2.imread("lena.png")
rows,cols=img.shape[:2]
mapx = np.zeros(img.shape[:2],np.float32)
mapy = np.zeros(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)
rst=cv2.remap(img,mapx,mapy,cv2.INTER_LINEAR)
cv2.imshow("original",img)
cv2.imshow("result",rst)
cv2.waitKey()
cv2.destroyAllWindows()
,左圖是原始圖像,右圖是翻轉(zhuǎn)結(jié)果圖像文章來源:http://www.zghlxwxcb.cn/news/detail-611573.html
還有繞Y 翻轉(zhuǎn),繞X,Y 軸翻轉(zhuǎn),更多操作多動(dòng)作試試文章來源地址http://www.zghlxwxcb.cn/news/detail-611573.html
到了這里,關(guān)于opencv-26 圖像幾何變換04- 重映射-函數(shù) cv2.remap()的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!