重映射,就是把一幅圖像中某位置的像素放置到另一個圖片指定位置的過程。
為了完成映射過程, 我們需要獲得一些插值為非整數像素的坐標,因為源圖像與目標圖像的像素坐標不是一一對應的。
一般情況下,我們通過重映射來表達每個像素的位置 (x,y),
像這樣 : g(x,y) = f ( h(x,y) )
在這里, g( ) 是目標圖像, f() 是源圖像, 而h(x,y) 是作用於 (x,y) 的映射方法函數。
在OpenCV中,我們用函數remap( )來實現簡單重映射。
C++:
void remap(InputArray src, //輸入圖像
OutputArraydst, //輸出圖像
InputArray map1,//第一個映射
InputArray map2, //第二個映射
int interpolation, //插值
intborderMode=BORDER_CONSTANT,
const Scalar& borderValue=Scalar()
)
第三個參數,InputArray類型的map1,它有兩種可能的表示對象:
表示點(x,y)的第一個映射。
表示CV_16SC2 , CV_32FC1 或CV_32FC2類型的X值。
第四個參數,InputArray類型的map2,同樣,它也有兩種可能的表示對象,而且他是根據map1來確定表示那種對象。
若map1表示點(x,y)時。這個參數不代表任何值。
表示CV_16UC1 , CV_32FC1類型的Y值(第二個值)。
第五個參數,int類型的interpolation,插值方式,之前的resize( )函數中有講到,需要注意,resize( )函數中提到的INTER_AREA插值方式在這里是不支持的,所以可選的插值方式如下:
INTER_NEAREST - 最近鄰插值
INTER_LINEAR – 雙線性插值(默認值)
INTER_CUBIC – 雙三次樣條插值(逾4×4像素鄰域內的雙三次插值)
INTER_LANCZOS4 -Lanczos插值(逾8×8像素鄰域的Lanczos插值)
第六個參數,int類型的borderMode,邊界模式,有默認值BORDER_CONSTANT,表示目標圖像中“離群點(outliers)”的像素值不會被此函數修改。
第七個參數,const Scalar&類型的borderValue,當有常數邊界時使用的值,其有默認值Scalar( ),即默認值為0。
.pro文件
QT -= gui
CONFIG += c++11 console
CONFIG -= app_bundle
# The following define makes your compiler emit warnings if you use
# any feature of Qt which as been marked deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += main.cpp
OPENCV_ROOT_PATH = /home/yhl/software_install/opencv3.2
INCLUDEPATH += $${OPENCV_ROOT_PATH}/include \
$${OPENCV_ROOT_PATH}/include/opencv \
$${OPENCV_ROOT_PATH}/include/opencv2
LIBS += -L$${OPENCV_ROOT_PATH}/lib
LIBS += -lopencv_core \
-lopencv_highgui \
-lopencv_imgproc \
-lopencv_imgcodecs \
-lopencv_videoio \
-lopencv_calib3d
//-----------------------------------【頭文件包含部分】---------------------------------------
// 描述:包含程序所依賴的頭文件
//----------------------------------------------------------------------------------------------
#include"opencv2/highgui/highgui.hpp"
#include"opencv2/imgproc/imgproc.hpp"
#include <iostream>
//-----------------------------------【命名空間聲明部分】--------------------------------------
// 描述:包含程序所使用的命名空間
//-----------------------------------------------------------------------------------------------
using namespace cv;
//-----------------------------------【main( )函數】--------------------------------------------
// 描述:控制台應用程序的入口函數,我們的程序從這里開始執行
//-----------------------------------------------------------------------------------------------
int main( )
{
//【0】變量定義
Mat srcImage, dstImage;
Mat map_x, map_y;
//【1】載入原始圖
srcImage= imread( "/data_2/everyday/1223/dog.jpeg", 1 );
if(!srcImage.data) { printf("讀取圖片錯誤,請確定目錄下是否有imread函數指定的圖片存在~! \n"); return false; }
namedWindow("原始圖",0);
imshow("原始圖",srcImage);
//【2】創建和原始圖一樣的效果圖,x重映射圖,y重映射圖
dstImage.create(srcImage.size(), srcImage.type() );
map_x.create(srcImage.size(), CV_32FC1 );
map_y.create(srcImage.size(), CV_32FC1 );
//【3】雙層循環,遍歷每一個像素點,改變map_x & map_y的值
for(int j = 0; j < srcImage.rows;j++)
{
for(int i = 0; i < srcImage.cols;i++)
{
//改變map_x & map_y的值.
map_x.at<float>(j,i)= static_cast<float>(srcImage.cols - i);
map_y.at<float>(j,i)= static_cast<float>(j);
}
}
//【4】進行重映射操作
remap(srcImage, dstImage, map_x, map_y, CV_INTER_LINEAR, BORDER_CONSTANT, Scalar(0,0,0) );
//【5】顯示效果圖
namedWindow("remap",0);
imshow("remap", dstImage );
waitKey();
return 0;
}
測試圖片如下,治愈系的小奶狗,_