重映射Remapping
void cv::remap ( InputArray src, OutputArray dst,
InputArray map1, InputArray map2,
int interpolation, int borderMode = BORDER_CONSTANT,
const Scalar & borderValue = Scalar()
)
说明
src: 源图像
dst: 目标图像,与 src 相同大小
map_x: x方向的映射参数. 它相当于方法 h(i,j) 的第一个参数
map_y: y方向的映射参数. 注意 map_y 和 map_x 与 src 的大小一致。
CV_INTER_LINEAR: 非整数像素坐标插值标志. 这里给出的是默认值(双线性插值)。
BORDER_CONSTANT: 默认
代码示例
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"
#include <iostream>
using namespace cv;
using namespace std;
Mat src, dst;
Mat map_x, map_y;
char* remap_window = "Remap Demo";
int ind = 0;
void update_map(void);
int main(int argc, char** argv)
{
CommandLineParser parser(argc, argv, "{@image | ../data/lena.jpg | input image}");
string filename = parser.get<string>(0);
src = imread(filename, IMREAD_COLOR);
dst.create(src.size(), src.type());
map_x.create(src.size(), CV_32FC1); // 32位浮点型单通道矩阵
map_y.create(src.size(), CV_32FC1);
while (true)
{
char c = (char)waitKey(1000);
if (c == 27) { break; }
update_map();
remap(src, dst, map_x, map_y, INTER_LINEAR, BORDER_CONSTANT, Scalar(0, 0, 0)); // 重映射
imshow(remap_window, dst);
}
return 0;
}
void update_map(void)
{
ind = ind % 4;
for(int j =0;j<src.rows;j++)
for (int i = 0; i < src.cols; i++)
{
switch (ind)
{
case 0: // 图像宽高缩小一半,并显示在中间
if (i > src.cols*0.25 && i < src.cols*0.75 && j > src.rows*0.25 && j < src.rows*0.75)
{
map_x.at<float>(j, i) = 2 * (i - src.cols*0.25f) + 0.5f;
map_y.at<float>(j, i) = 2 * (j - src.rows*0.25f) + 0.5f;
}
else
{
map_x.at<float>(j, i) = 0;
map_y.at<float>(j, i) = 0;
}
break;
case 1: // 图像上下颠倒
map_x.at<float>(j, i) = (float)i;
map_y.at<float>(j, i) = (float)(src.rows - j);
break;
case 2: // 图像左右颠倒
map_x.at<float>(j, i) = (float)(src.cols - i);
map_y.at<float>(j, i) = (float)j;
break;
case 3: // 同时执行b和c的操作
map_x.at<float>(j, i) = (float)(src.cols - i);
map_y.at<float>(j, i) = (float)(src.rows - j);
break;
}
}
ind++;
}
运行结果
仿射变换Affine Transformations
void cv::warpAffine ( InputArray src, OutputArray dst,
InputArray M, Size dsize,
int flags = INTER_LINEAR,int borderMode = BORDER_CONSTANT,
const Scalar & borderValue = Scalar()
)
说明
src: 输入源图像
dst: 输出图像
M : 仿射变换矩阵
dsize: 输出图像的尺寸
代码示例
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"
#include <iostream>
using namespace cv;
using namespace std;
char* source_window = "Source image";
char* warp_window = "Warp";
char* warp_rotate_window = "Warp + Rotate";
int main(int, char** argv)
{
Point2f srcTri[3]; // 三角形三个顶点
Point2f dstTri[3];
Mat rot_mat(2, 3, CV_32FC1);
Mat warp_mat(2, 3, CV_32FC1);
Mat src, warp_dst, warp_rotate_dst;
char* filename = "../data/lena.jpg";
src = imread(filename, IMREAD_COLOR);
warp_dst = Mat::zeros(src.rows, src.cols, src.type());
srcTri[0] = Point2f(0, 0); // 图像左上角
srcTri[1] = Point2f(src.cols - 1.f, 0); // 图像右上角
srcTri[2] = Point2f(0, src.rows - 1.f); // 图像左下角
dstTri[0] = Point2f(src.cols*0.0f, src.rows*0.33f);
dstTri[1] = Point2f(src.cols*0.85f, src.rows*0.25f);
dstTri[2] = Point2f(src.cols*0.15f, src.rows*0.7f);
warp_mat = getAffineTransform(srcTri, dstTri); // 得到仿射矩阵
warpAffine(src, warp_dst, warp_mat, warp_dst.size()); // 仿射变换
Point center = Point(warp_dst.cols / 2, warp_dst.rows / 2);
double angle = -50.0;
double scale = 0.6;
rot_mat = getRotationMatrix2D(center, angle, scale);
warpAffine(warp_dst, warp_rotate_dst, rot_mat, warp_dst.size()); // 旋转仿射变换
imshow(source_window, src);
imshow(warp_window, warp_dst);
imshow(warp_rotate_window, warp_rotate_dst);
waitKey(0);
return 0;
}
运行结果