opencv學習(三十四)之重對映remap
阿新 • • 發佈:2019-02-03
重對映就是把一個影象中一個為之的畫素放置到另一個圖片指定位置過程。為了完成重對映過程有必要獲得一些插值作為非整數畫素座標,因為原影象與目標影象的畫素座標不是一一對應的。我們通過重對映來表達每個畫素的位置(x, y):
g(x, y)=f(h(x,y))
這裡g()是目標影象,f()是原影象,h(x,y)是作用於(x,y)的對映方法函式。假設有一幅影象I,滿足下面條件作重對映:
h(x,y)=(I.cols - x,y)
影象會按照x軸方向發生反轉,如下:
看到紅色圈關於x的位置改變(x軸水平翻轉)
opencv提供函式reman()實現簡單的重對映。remap函式原型如下:
void cv::remap ( InputArray src,
OutputArray dst,
InputArray map1,
InputArray map2,
int interpolation,
int borderMode = BORDER_CONSTANT,
const Scalar & borderValue = Scalar()
)
引數解釋
. src:輸入影象
. dst:目標影象,與原影象型別相同,與map1影象尺寸大小相等
. map1: (x, y)的第一個對映或者是CV_16SC2、CV_32FC1或CV_32FC2的x值。查詢convertMaps獲得詳細解釋。
. map2: 第二個map,表示型別為CV_16UC1、CV_32FC1的y值或空值(如果map1是用(x,y)進行表示)
. interpolation: 插值方式,在此函式中不支援INTER_AREA插值方法。插值方法如下(可通過InterpolationFlags檢視)
. borderMode: 邊界模式,有預設值BORDER_CONSTANT,表示目標影象中“離群點”的畫素值不會被此函式修改
. borderValue: 當有常數邊界時使用的值,有預設值Scalar()即0
示例程式碼
#include <iostream>
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
using namespace std;
using namespace cv;
//定義全域性變數
Mat srcImage, dstImage;
Mat map1_x, map2_y;
String windowName = "影象重對映" ;
int ind; //重對映型別選擇
void updateMap(void);
int main()
{
//初始化引數
ind = 0;
srcImage = imread("dog.jpg");
dstImage.create(srcImage.size(), srcImage.type());
map1_x.create(srcImage.size(), CV_32FC1);
map2_y.create(srcImage.size(), CV_32FC1);
//建立視窗
namedWindow(windowName, WINDOW_AUTOSIZE);
while(true)
{
int c = waitKey(1000); //延遲1000ms
if((char)c == 27)
{
break; //ESC退出
}
updateMap(); //呼叫函式,更新重對映模式
remap(srcImage, dstImage, map1_x, map2_y, INTER_LINEAR, BORDER_CONSTANT, Scalar(0, 0, 0));
imshow(windowName, dstImage);
}
return 0;
}
void updateMap(void)
{
ind = ind%4;
for(int j = 0; j < srcImage.rows; j++)
{
for(int i = 0; i < srcImage.cols; i++)
{
switch(ind)
{
//影象長寬縮小到原來的一半並居中顯示
case 0:
if(i > srcImage.cols*0.25 && i < srcImage.cols*0.75 && j > srcImage.rows*0.25 && j < srcImage.rows*0.75)
{
map1_x.at<float>(j, i) = 2*(i - srcImage.cols*0.25) + 0.5;
map2_y.at<float>(j, i) = 2*(j - srcImage.rows*0.25) + 0.5;
}
else
{
map1_x.at<float>(j, i) = 0;
map2_y.at<float>(j, i) = 0;
}
break;
//影象左右翻轉
case 1:
map1_x.at<float>(j, i) = i;
map2_y.at<float>(j, i) = srcImage.rows - j;
break;
//影象上下翻轉
case 2:
map1_x.at<float>(j, i) = srcImage.cols - i;
map2_y.at<float>(j, i) = j;
break;
//影象上下左右均翻轉
case 3:
map1_x.at<float>(j, i) = srcImage.cols - i;
map2_y.at<float>(j, i) = srcImage.rows - j;
break;
default:
break;
}
}
}
ind++;
}
執行結果
影象縮小
左右翻轉
上下翻轉