影像幾何變換是將一幅影像的座標位置,映射到新座標位置,這種幾何變換不改變像素值,只是在平面上進行像素位置的重新安排,OpenCV提供remap()來進行幾何轉換,分以下兩部分:

  • 對想要進行的空間變換,像垂直、水平鏡射,製作一個映射表,映射表是一個和輸入圖尺寸相同的影像,值代表影像每個像素的新位置。
  • 在我們進行映射轉換時,輸出圖的像素可能映射到輸入圖的非整數座標上,此時由輸入參數,決定如何計算。

OpenCV的remap()函式需要輸入mapx和mapy兩個影像,這兩個影像尺寸和輸入圖相同,分別表示新的x和y的位置,假設dst是輸出圖,則dst(x,y) = src(mapx(x,y) , mapy(x,y))。


OpenCV重映射

void remap(InputArray src, OutputArray dst, InputArray map1, InputArray map2, int interpolation, int borderMode=BORDER_CONSTANT, const Scalar& borderValue=Scalar())

  • src:輸入圖。
  • dst:輸出圖,型態和輸入圖相同。
  • map1:第一個輸入的映射表,型態可為CV_16SC2、CV_32FC1或CV_32FC2,尺寸和輸入圖相同,映射表的值代表的是輸入圖此像素位置要轉移去的新x座標。
  • map2:第二個輸入的映射表,型態可為CV_16UC1或 CV_32FC1,尺寸和輸入圖相同,映射表的值代表的是輸入圖此像素位置要轉移去的新y座標。。
  • interpolation:內插型態。
  • borderMode:邊界模式,預設為BORDER_CONSTANT。
  • borderValue:邊界外推值,預設強度為0。

以下示範remap()的用法,讓輸入圖進行左右或上下的顛倒,依據想要進行的操作,先給map_x和map_y影像像素賦值,再呼叫remap()即可將輸入圖進行想要的轉換:

#include <cstdio>
#include <opencv2/opencv.hpp>
using namespace cv;

int main(){
Mat src = imread("lena.jpg");
Mat map_x_1,map_y_1,map_x_2,map_y_2,map_x_3,map_y_3;
map_x_1.create(src.size(), CV_32FC1);
map_y_1.create(src.size(), CV_32FC1);
map_x_2.create(src.size(), CV_32FC1);
map_y_2.create(src.size(), CV_32FC1);
map_x_3.create(src.size(), CV_32FC1);
map_y_3.create(src.size(), CV_32FC1);

for(int iH=0; iH<src.rows; iH++){
for(int iW=0; iW<src.cols; iW++){
map_x_1.at<float>(iH,iW) = iW ;
map_y_1.at<float>(iH,iW) = src.rows - iH ;

map_x_2.at<float>(iH,iW) = src.cols - iW ;
map_y_2.at<float>(iH,iW) = iH ;

map_x_3.at<float>(iH,iW) = src.cols - iW ;
map_y_3.at<float>(iH,iW) = src.rows - iH ;
}
}

Mat dst1,dst2,dst3;
remap(src, dst1, map_x_1, map_y_1, CV_INTER_LINEAR);
remap(src, dst2, map_x_2, map_y_2, CV_INTER_LINEAR);
remap(src, dst3, map_x_3, map_y_3, CV_INTER_LINEAR);

imshow("origin", src);
imshow("remap_1", dst1);
imshow("remap_2", dst2);
imshow("remap_3", dst3);
waitKey(0);

return 0;
}