图像的平移变换就是将图像所有的像素坐标分别加上指定的水平偏移量和垂直偏移量。平移变换根据是否改变图像大小分为两种
左边平移图像的大小发生了,在保证图像平移的同时,也保存了完整的图像信息。右边的平移图像大小没有变化,故图像右下角的部分被截除了。
平移变换原理
设dx为水平偏移量,dy为垂直偏移量,(x0,y0)为原图像坐标,(x,y)为变换后图像坐标,则平移变换的坐标映射为
这是向前映射,即将原图像的坐标映射到变换后的图像上。
其逆变换为
,向后映射,即将变换后的图像坐标映射到原图像上。在图像的几何变换中,一般使用向后映射。
下面来看看代码:
#include<opencv2\imgproc\imgproc.hpp>
#include<opencv2\core\core.hpp>
#include<opencv2\highgui\highgui.hpp>
#include<iostream>
using namespace cv;
//平移操作,图形大小不变
/*
srcImage:输入的图像
xOffset:x轴平移的大小
yOffset:y轴平移的大小
这个函数返回的是Mat类型的一张图形
*/
Mat imageTranslation1(Mat &srcImage, int xOffset, int yOffset)
{
int nRows = srcImage.rows;//新图像的高也就是行数
int nClos = srcImage.cols;//新图形的宽也就是列数
Mat resultImage(srcImage.size(), srcImage.type());//创建一张大小和类型与原始图形一样的新图形
//遍历图像
for (int i = 0; i < nRows; i++)
{
for (int j = 0; j < nClos; j++)
{
//实际上的坐标
//从变换的图形的坐标找出原图的坐标
int x = j - xOffset; //相当于是图像中的列
int y = i - yOffset;//相当于是图像中的行
//边界判断
if (x >= 0 && y >= 0 && x < nClos && y < nRows)
{
//srcImage.ptr(i)这是获取第i行的首地址
resultImage.at<Vec3b>(i, j) = srcImage.ptr<Vec3b>(y)[x];
}
}
}
return resultImage;
}
//平移操作,图片的大小改变
Mat imageTranslation2(Mat &srcImage, int xOffset, int yOffset)
{
int nRows = srcImage.rows + abs(yOffset);//新图像的高也就是行数
int nClos = srcImage.cols + abs(xOffset);//新图形的宽也就是列数
Mat resultImage(nRows, nClos, srcImage.type());//创建一张行数是nRows,列数是nClos,类型和原始图一样的新
//遍历图像
for (int i = 0; i < nRows; i++)
{
for (int j = 0; j < nClos; j++)
{
//实际上的坐标
//从变换的图形的坐标找出原图的坐标
int x = j - xOffset; //相当于是图像中的列
int y = i - yOffset;//相当于是图像中的行
//边界判断
if (x >= 0 && y >= 0 && x < nClos && y < nRows)
{
//srcImage.ptr(i)这是获取第i行的首地址
resultImage.at<Vec3b>(i, j) = srcImage.ptr<Vec3b>(y)[x];
}
}
}
return resultImage;
}
int main()
{
Mat srcImage = imread("lakeWater.jpg");
//如果读取失败
if (!srcImage.data)
{
printf("Could not load image...\n");
return -1;
}
//创建并显示原始窗口
namedWindow("srcImage", CV_WINDOW_AUTOSIZE);
imshow("srcImage", srcImage);
int xOffset = 50, yOffset = 80;
//图像左平移不改变大小
Mat resultImage1 = imageTranslation1(srcImage, xOffset, yOffset);
namedWindow("resultImage1", CV_WINDOW_AUTOSIZE);
imshow("resultImage1", resultImage1);
//图像右平移改变大小
Mat resultImage2 = imageTranslation2(srcImage, xOffset, yOffset);
namedWindow("resultImage2", CV_WINDOW_AUTOSIZE);
imshow("resultImage2", resultImage2);
waitKey(0);
return 0;
}
原图:
原图的大小不变的效果图:
原图大小改变的效果图: