1.22【OpenCV圖像處理】像素重映射
重映射remap()、左右、上下、全部對調、縮小
1.21.1 像素重映射
像素重映射原理:簡單點說就是把輸入圖像中各個像素按照一定的規則映射到另外一張圖像的對應位置上去,形成一張新的圖像。
我們通過重映射來表達每個像素的位置 :
假設有映射函數 ,圖像會按照X軸方向發生翻轉:
1.21.2 API介紹
remap(
InputArray src,// 輸入圖像
OutputArray dst,// 輸出圖像
InputArray map1,// x方向映射表 -CV_32FC1/CV_32FC2 它相當於方法 的第一個參數
InputArray map2,// y方向映射表 注意 map_y 和 map_x 與 src 的大小一致。
int interpolation,// 選擇的插值方法,常見線性插值,可選擇雙線性、立方等
int borderMode,// 默認常數邊界-BORDER_CONSTANT
const Scalar borderValue// color
)
remap(src, dst, map_x, map_y, INTER_LINEAR, BORDER_CONSTANT, Scalar(0, 255, 255)); //重映射,x方向映射表,y向映射表,線性插值,常數邊界,填充顏色n
1.21.3 映射規則
我們將分別使用4種不同的映射規則:
(1)圖像寬高縮小一半,並顯示在中間:
所有成對的參數(i,j)處理後都符合:
和
(2)Y方向對調,圖像上下顛倒:
(3)X方向對調,圖像左右顛倒:
(4)XY方向同時對調,同時執行2和3的操作:
完整程序:
/*1.22 像素重映射*/n#include <opencv2/opencv.hpp>n#include <iostream> n#include <math.h>nusing namespace cv;nusing namespace std;nnMat src, dst;nvoid update_map(void);nMat map_x, map_y;nint index = 0;nnint main(int argc, char** argv) {n src = imread("E:/OpenCV/testimage/test7.jpg");nif (src.empty()) {n printf("could not load image...n");nreturn -1;n }nchar input_title[] = "input image";n namedWindow(input_title, CV_WINDOW_AUTOSIZE);n imshow(input_title, src);nn map_x.create(src.size(), CV_32FC1); //建立x方向映射表,大小跟輸入圖一樣,32位單通道圖像n map_y.create(src.size(), CV_32FC1); //建立y方向映射表,大小跟輸入圖一樣,32位單通道圖像 nint c = 0;nwhile (true) { //建立一個間隔500毫秒的循環,每次循環執行更新映射矩陣參數並對源圖像進行重映射處理n c = waitKey(500); nif ((char)c == 27) { //ESCnbreak;n } n index = c % 4;n update_map();n remap(src, dst, map_x, map_y, INTER_LINEAR, BORDER_CONSTANT, Scalar(0, 255, 255)); //重映射,x方向映射表,y向映射表,線性插值,常數邊界,填充顏色n imshow("output_title", dst);n }nn waitKey(0);nreturn 0;n}n/*像素映射*/nvoid update_map(void) {nfor (int row = 0; row < src.rows; row++) {nfor (int col = 0; col < src.cols; col++) {nswitch (index)n {ncase 0: //圖像寬高縮小一半,並顯示在中間nif (col>src.cols * 0.25 && col<src.cols * 0.75 && row>src.rows * 0.25 && row<src.rows * 0.75) //建立映射規則,中間部分n {n map_x.at<float>(row, col) = 2 * (col - (src.cols*0.25)); //線性插值找位置,映射一半n map_y.at<float>(row, col) = 2 * (row - (src.rows*0.25));n }nelse //非中間部分為0n {n map_x.at<float>(row, col) = 0;n map_y.at<float>(row, col) = 0;n }nbreak;ncase 1: //2鍵,列變,行不變,左右對調n map_x.at<float>(row, col) = (src.cols - col- 1); //線性插值找位置,映射一半n map_y.at<float>(row, col) = row;nbreak;ncase 2: //3鍵,列不變,行變,上下翻轉n map_x.at<float>(row, col) = col;n map_y.at<float>(row, col) =(src.rows - row - 1);nbreak;ncase 3: //4鍵,行、列都變,上下左右全對調(順時針旋轉180度)n map_x.at<float>(row, col) = (src.cols - col - 1);n map_y.at<float>(row, col) = (src.rows - row - 1);nbreak;n }nn }n }n}n
運行結果:
推薦閱讀: