图像的几何变换是基本但是也是常用到的一些操作,下面简单做一下总结:
1.放缩图像resize()函数:
//图像缩放(resize函数)
Mat srcImg = imread("D:/2.jpg");
Mat dstImg;
resize(srcImg,dstImg,Size(),0.5,0.5);//将原图像宽高缩放为0.5.
// resize(srcImg,dstImg,Size(srcImg.cols/2,srcImg.rows/2),0,0);//同样将图像缩小为0.5
//dsize和fx、fy不能同时为0。fx、fy是沿x轴和y轴的缩放系数;
//@param dsize output image size; if it equals zero, it is computed as:
//\f[\texttt{dsize = Size(round(fx*src.cols), round(fy*src.rows))}\f]
imshow("src", srcImg);
imshow("dst", dstImg);
// imwrite("D:/q1.jpg", dstImg); //保存图片
waitKey(0);
效果如下:
2.图像平移,其中一种方法是将原图的像素点置换到对应保存图像的内点+x值图像
代码如下:
//图像平移
Mat srcImg = imread("D:/2.jpg");
int xOffset=100;
int yOffset=20;
int rows = srcImg.rows; //
int cols = srcImg.cols;//
Mat dstImg = Mat::zeros(srcImg.size(), srcImg.type()); //创建全黑目标图像,同源图像一样大
for (int i = 0; i < rows; i++)//遍历式平移
{
for (int j = 0; j < cols; j++)
{
int x = j + xOffset;
int y = i +yOffset;
if (x >= 0 && y >= 0 && x < cols && y < rows)//溢出保护
{
dstImg.at<Vec3b>(y, x) = srcImg.at<Vec3b>(i, j);
}
}
}
imshow("src", srcImg);
imshow("dst", dstImg);
//imwrite("D:/q2.jpg", dstImg); //保存结果图片
waitKey(0);
效果如下:
3.图像旋转,一要通过getRotationMatrix2D()获得旋转矩阵,然后通过warpAffine()仿射变换将图像移动到指定中心,也就是说warpAffine()也可平移图像,当然具体什么是仿射变换可以网上搜索了解更详细的;
下面是代码:
//图像旋转(getRotationMatrix2D函数和warpAffine函数配合使用)
//利用getRotationMatrix2D函数获得二维旋转矩阵,再用warpAffine设置目标图像大小完成旋转
//仿射变换”就是:“线性变换”+“平移”
Mat srcImg = imread("D:/2.jpg");
// Point2f center = Point2f(srcImg.cols/2, srcImg.rows/2); //定义旋转中心坐标
Point2f center = Point2f(400, 100); //定义旋转中心坐标
double angle = 30; //旋转角度
double scale = 0.8; //缩放比例
Mat roateM;
roateM = getRotationMatrix2D(center, angle, scale); // 获得旋转矩阵
Mat dstImg;
warpAffine(srcImg, dstImg, roateM, Size(500, 500)); // 仿射变换
imshow("src", srcImg);
imshow("dst", dstImg);
// imwrite("D:/q3.jpg", dstImg); //保存结果图片
waitKey(0);
效果:
4.置换和镜像操作flip()函数:
//转置和镜像(转置用transpose函数,镜像用flip函数)
Mat srcImg = imread("D:/2.jpg");
Mat dstImg;
//下两行结合可达到逆时针旋转90度的效果
transpose(srcImg, dstImg); //转置(行列互换)
flip(dstImg, dstImg, 0); //镜像,0代表沿X轴翻转;>0代表沿Y轴反转;<0代表沿中心翻转
imshow("src", srcImg);
imshow("dst", dstImg);
waitKey(0);
效果:
5.重映射操作remap()函数,有点类似前面的平移操作,但是mat上存储并操作,函数帮助处理了一些溢出等操作;简单说就是遍历操作的数据存储在mat里,然后通过remap(),重新合成;类似平移放缩等操作均可以这样操作了;
代码如下:
//重映射(remap函数)
Mat srcImage = imread("D:/2.jpg");
Mat dstImage,map_x,map_y;
//创建和原始图像一样的效果图,x重映射图,y重映射图
dstImage.create(srcImage.size(),srcImage.type());
map_x.create(srcImage.size(),CV_32FC1); // map_x=Mat::zeros(srcImage.size(), CV_32FC1);
map_y.create(srcImage.size(),CV_32FC1); // map_y=Mat::zeros(srcImage.size(), CV_32FC1);
//双层循环,遍历每一个像素点,改变map_x和map_y的值
for (int i = 0; i < srcImage.rows; i++)
{
for (int j = 0; j <srcImage.cols; j++)
{
//1.Y坐标.波浪效果.
map_x.at<float>(i, j) = j; //X坐标.保持列不变,
map_y.at<float>(i, j) = i + 10 * sin(j/10.0);//Y坐标.波浪效果.
// //2.水平对称
// map_x.at<float>(i,j) = j;
// map_y.at<float>(i,j) = srcImage.rows-i;//关于x轴对称的效果
// //3.垂直对称
// map_x.at<float>(i,j) =srcImage.cols- j;
// map_y.at<float>(i,j) = i;
// //4.上下左右对称
// map_x.at<float>(i,j) =srcImage.cols- j;
// map_y.at<float>(i,j) =srcImage.rows-i;
// //5.缩小图像
// if( i > srcImage.cols*0.25 && i < srcImage.cols*0.75 && j > srcImage.rows*0.25 && j <srcImage.rows*0.75 )
// {
// map_x.at<float>(j,i) = 2*( i - srcImage.cols*0.25 ) + 0.5 ;
// map_y.at<float>(j,i) = 2*( j - srcImage.rows*0.25 ) + 0.5 ;
// }
}
}
//进行重映射操作
remap(srcImage,dstImage,map_x,map_y,CV_INTER_LINEAR,BORDER_CONSTANT,Scalar(0,0,0));
//显示效果图
imshow("dst",dstImage);
imshow("src",srcImage);
// imwrite("D:/q4.jpg", dstImage); //保存结果图片
waitKey(0);
效果如下: