通過映射改變圖像,實現翻轉放大和縮小
API
cv::remap ( InputArray src, OutputArray dst, InputArray map1, InputArray map2, int interpolation, int borderMode = BORDER_CONSTANT, const Scalar borderValue = Scalar() )
第一個參數,InputArray類型的src,輸入圖像,即源圖像,填Mat類的對象即可,且需為單通道8位或者浮點型圖像。
第二個參數,OutputArray類型的dst,函數調用后的運算結果存在這里,即這個參數用於存放函數調用后的輸出結果,需和源圖片有一樣的尺寸和類型
第三個參數,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。
demo,通過按鍵1234實現水平翻轉,垂直翻轉,水平垂直翻轉和縮小
#include"pch.h" #include<iostream> #include<opencv2\opencv.hpp> using namespace std; using namespace cv; #define INPUT_TITLE "input image" #define OUTPUT_TITLE "remap image" Mat img, src;//img 輸入圖像 ; src 最終輸出的圖像 Mat map_x, map_y; int index = 0; void updata_map(); int main() { img = imread("b.jpg"); if (!img.data) { cout << "ERROR : could not load image."; return -1; } namedWindow(INPUT_TITLE, CV_WINDOW_AUTOSIZE); namedWindow(OUTPUT_TITLE, CV_WINDOW_AUTOSIZE); imshow(INPUT_TITLE, img); //建立映射表 map_x.create(img.size(), CV_32FC1); map_y.create(img.size(), CV_32FC1); int c = 0; while (true) { c = waitKey(500); index = c % 4; if ((char)c == 27) { break; } updata_map(); remap(img, src, map_x, map_y, INTER_LINEAR, BORDER_CONSTANT, Scalar(0, 0, 255)); imshow(OUTPUT_TITLE, src); } return 0; } void updata_map() { for (int row = 0; row < img.rows; row++) { for (int col = 0; col < img.cols; col++) { switch (index) { //index = 0 ,圖像的行跟列為為原來的1/2。 //index = 1,為左右翻轉(列變換,行不變) //index = 2,為上下翻轉(行變換,列不變) //index = 3,為中心旋轉 case 0: if (col > (img.cols*0.25) && col<(img.cols*0.75) && row>(img.rows*0.25) && row < (img.rows*0.75)) { map_x.at<float>(row, col) = 2 * (col - (img.cols*0.25)); map_y.at<float>(row, col) = 2 * (row - (img.rows*0.25) - 0.25); } else { map_x.at<float>(row, col) = 0; map_y.at<float>(row, col) = 0; } break; case 1: map_x.at<float>(row, col) = (img.cols - col - 1); map_y.at<float>(row, col) = row; break; case 2: map_x.at<float>(row, col) = col; map_y.at<float>(row, col) = (img.rows - row - 1); break; case 3: map_x.at<float>(row, col) = (img.cols - col - 1); map_y.at<float>(row, col) = (img.rows - row - 1); break; default: break; } } } }
其中縮小的mapx和mapy仍沒有搞清楚,我覺得大圖映射到小圖應該是: 大圖的像素點/2+0.25*大圖尺寸,和demo的公式正好是反過來的
1
2
3
4