opencv中提供重映射等操作,其中重映射就是把一幅图像中某位置的像素放置到另一个图片指定位置的过程。为了完成映射过程,需要获得一些插值为非整数像素的坐标。对于原图像和目标图像,满足下式:
G(x,y)=f(h(x,y))
G()是目标图像,f()是源图像,而h(x,y)是作用于(x,y)的映射方法函数。
函数原型如下:
Void remap(InputArray src,OutputArray dst,InputArray map1,InputArray map2, int interpolation,int borderMode=BORDER_CONSTANT,const Scalar&borderValue=Scalar())
- src: 源图像
- dst: 目标图像,与 src 相同大小
- map1: x坐标
- map2: y坐标
- interpolation: 表示插值方法
- borderMode:表示边界插值类型
- borderValue:表示插值数值
#include<opencv2/imgproc/imgproc.hpp> #include<opencv2/core/core.hpp> #include<opencv2/highgui/highgui.hpp> #include<iostream> using namespace cv; using namespace std; int main() { cv::Mat srcImage = cv::imread("test1.jpg"); if (!srcImage.data) return -1; cout << "图像大小:" <<srcImage.size() << endl; cout << "图像类型:" << srcImage.type() << endl; //输出矩阵定义 cv::Mat resultImage(srcImage.size(), srcImage.type()); //x与y方向矩阵 cv::Mat xMapImage(srcImage.size(), CV_32FC1); cv::Mat yMapImage(srcImage.size(), CV_32FC1); //取图像的宽高 int rows = srcImage.rows; int cols = srcImage.cols; //生成映射表 //图像遍历-生成映射表 for (int j = 0; j < rows; j++) { for (int i = 0; i < cols; i++) { //x与y均翻转 xMapImage.at<float>(j, i) = cols - i; //上下翻转 yMapImage.at<float>(j, i) = rows - j; //左右翻转 } } //版本1 代替remap 图像遍历-读取映射表生成图像 //待解决问题: 1如果有倾斜变化需要插值 2更换指针访问加速 3根据图像通道类型进行自动化更改 int tempx; int tempy; for (int j = 0; j < rows; j++) { for (int i = 0; i < cols; i++) { //x与y均翻转 tempx = int(xMapImage.at<float>(j, i))-1; //上下翻转 tempy = int(yMapImage.at<float>(j, i))-1; //左右翻转 //cout << tempx << "---"<< tempy << endl; resultImage.at<Vec3b>(j, i)[0] = srcImage.at<Vec3b>(tempy, tempx)[0]; resultImage.at<Vec3b>(j, i)[1] = srcImage.at<Vec3b>(tempy, tempx)[1]; resultImage.at<Vec3b>(j, i)[2] = srcImage.at<Vec3b>(tempy, tempx)[2]; } } //重映射操作 //remap(srcImage, resultImage, xMapImage, yMapImage, CV_INTER_LINEAR, cv::BORDER_CONSTANT, cv::Scalar(0, 0, 0)); //输出结果 namedWindow("srcImage",0); cv::imshow("srcImage", srcImage); namedWindow("resultImage", 0); cv::imshow("resultImage", resultImage); cv::waitKey(0); return 0; }