图像运动专题-镜像专题
1.图像处理前后结果展示
图像处理前
图像处理后
水平镜像
垂直镜像
2.镜像原理
用opencv实现图像的水平镜像和竖直镜像,可以事先确定中轴线,也可以不使用中轴线进行变换。
图像镜像变换分为水平镜像和竖直镜像。水平镜像是将图像左半部分和右半部分以图像竖直中轴线为中心轴进行兑换;而竖直镜像是将上半部分和下半部分以图像水平中轴线为中心轴进行兑换,如下图所示,
下面对代码展示中的代码进行进一步说明。
需要注意的是,图像中点的坐标是从0开始的,在表示图像点的坐标范围以及确定变换中轴线时,都要注意这一点。在竖直镜像变换时,变换是按列进行的,使用了两种变换方法,两种方法的不同在于确定中轴线的方式和下半部分坐标的的表示方式的差别。
第一种方法是分别为上半部分和下半部分定义一个变量表示y坐标,分别是从0递增和从最后一个点递减,当表示上半部分的y坐标大于下半部分的时候,说明到达了中轴线,停止变换。
第二种方法是,先确定中轴线,但是奇数个点和偶数个点的中轴线是不同的。假设y1表示列起始点的y坐标,y2表示一列最后一个点的y坐标,用y2/2表示中轴线,当点数为奇数时中轴线时正确的,而当点数是偶数时确定的中轴线时错误的。为了弥补这种错误,在第二种方法中,在变换过程中使用y2-y1确定下半部分要变换的点的位置。
3.代码展示
#include <vector>
#include <opencv2\core\core.hpp>
#include <opencv2\highgui\highgui.hpp>
using namespace std;
using namespace cv;
int main()
{
Mat image = imread("C:\\Users\\DELL\\Desktop\\HGY.jpg");
Mat src=image.clone();
int W=image.cols;
int L=image.rows;
Vec3b temp;
//竖直镜像
for (int x=0;x<W;x++)
{
//下面两种变换方法有所不同
//变换方法一
// for (int y1=0,y2=L-1;y2-y1>0;y1++,y2--)
// {
// temp = image.at<Vec3b>(y1,x);
// image.at<Vec3b>(y1,x)=image.at<Vec3b>(y2,x);
// image.at<Vec3b>(y2,x)=temp;
// }
//变换方法二
for (int y1=0,y2=L-1;y1<=y2/2;y1++)
{
temp = image.at<Vec3b>(y1,x);
image.at<Vec3b>(y1,x)=image.at<Vec3b>(y2-y1,x);
image.at<Vec3b>(y2-y1,x)=temp;
}
}
imwrite("C:\\Users\\DELL\\Desktop\\HGY_VerticalMirroring.jpg", image);
//水平镜像
for (int y=0;y<L;y++)
{
for (int x1=0,x2=W-1;x1<x2;x1++,x2--)
{
temp=src.at<Vec3b>(y,x1);
src.at<Vec3b>(y,x1)=src.at<Vec3b>(y,x2);
src.at<Vec3b>(y,x2)=temp;
}
}
imwrite("C:\\Users\\DELL\\Desktop\\HGY_HorizontalMirroring.jpg", src);
system("pause");
return 0;
}