失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > 计算机视觉基础:图像处理Task 02 几何变换

计算机视觉基础:图像处理Task 02 几何变换

时间:2020-01-02 18:32:23

相关推荐

计算机视觉基础:图像处理Task 02 几何变换

文章目录

理论分析1.坐标系转换2.变换形式反向映射插值函数实现(C++)平移旋转

理论分析

对于旋转和偏移,就需要3步(3次变换):

1.将输入原图图像坐标转换为笛卡尔坐标系;

2.进行旋转计算。旋转矩阵前面已经给出了;

3.将旋转后的图像的笛卡尔坐标转回图像坐标。

1.坐标系转换

对于缩放、平移可以以图像坐标原点(图像左上角为原点)为中心变换,这不用坐标系变换,直接按照一般形式计算即可。而对于旋转和偏移,一般是以图像中心为原点,那么这就涉及坐标系转换了。图像坐标的原点在图像左上角,水平向右为 X 轴,垂直向下为 Y 轴。数学课本中常见的坐标系是以图像中心为原点,水平向右为 X 轴,垂直向上为 Y 轴,称为笛卡尔坐标系。

在图像中我们的坐标系通常是AB和AC方向的,原点为A,而笛卡尔直角坐标系是DE和DF方向的,原点为D。令图像表示为M×N的矩阵,对于点A而言,两坐标系中的坐标分别是(0,0)和(-N/2,M/2),则图像某像素点(x’,y’)转换为笛卡尔坐标(x,y)转换关系为,x为列,y为行:

逆变换为:

2.变换形式

在数据图像处理中图像变换采取变换矩阵的方式,即仿射变换,仿射变换形式如下:

式中的T就是变换矩阵,其中 (v,w)为原坐标,(x,y) 为变换后的坐标,不同的变换对应不同的矩阵,一些常见的变换矩阵及作用如下表:

于是,根据前面说的3个步骤(3次变换),旋转(顺时针旋转)的变换形式就为,3次变换就有3个矩阵:

反向映射

前向映射就是根据原图用变换公式直接算出输出图像相应像素的空间位置,那么这会导致一个问题:可能会有多个像素坐标映射到输出图像的同一位置,也可能输出图像的某些位置完全没有相应的输入图像像素与它匹配,也就是没有被映射到,造成有规律的空洞(黑色的蜂窝状)。更好的一种方式是采用 反向映射(Inverse Mapping):扫描输出图像的位置(x,y),通过 Image (为T的逆矩阵)计算输入图像对应的位置 (v,w),通过插值方法决定输出图像该位置的灰度值。

插值

采用反向映射后,需通过插值方法决定输出图像该位置的值,因此需要选择插值算法。通常有最近邻插值、双线性插值,双三次插值等,OpencV默认采用双线性插值,我们也就采用双线性插值。

函数实现(C++)

平移

平移需要函数warpAffine

void boxFilter( InputArray src, OutputArray dst, int ddepth,Size ksize, Point anchor = Point(-1,-1),bool normalize = true,int borderType = BORDER_DEFAULT );

第一个参数,InputArray类型的src,输入图像,即源图像,填Mat类的对象即可。

第二个参数,OutputArray类型的dst,函数调用后的运算结果存在这里,需和源图片有一样的尺寸和类型。

第三个参数,InputArray类型的M,2×3的变换矩阵。

第四个参数,Size类型的dsize,表示输出图像的尺寸。

第五个参数,int类型的flags,插值方法的标识符。此参数有默认值INTER_LINEAR(线性插值),可选的插值方式如下: INTER_NEAREST - 最近邻插值 INTER_LINEAR - 线性插值(默认值) INTER_AREA - 区域插值 INTER_CUBIC –三次样条插值 INTER_LANCZOS4 -Lanczos插值 CV_WARP_FILL_OUTLIERS - 填充所有输出图像的象素。如果部分象素落在输入图像的边界外,那么它们的值设定为 fillval. CV_WARP_INVERSE_MAP –表示M为输出图像到输入图像的反变换,即 。因此可以直接用来做象素插值。否则, warpAffine函数从M矩阵得到反变换。

第六个参数,int类型的borderMode,边界像素模式,默认值为BORDER_CONSTANT。

第七个参数,const Scalar&类型的borderValue,在恒定的边界情况下取的值,默认值为Scalar(),即0。

cv::Mat src = cv::imread("lenna.jpg");cv::Mat dst;cv::Size dst_sz = src.size();//定义平移矩阵cv::Mat t_mat =cv::Mat::zeros(2, 3, CV_32FC1);t_mat.at<float>(0, 0) = 1;t_mat.at<float>(0, 2) = 20; //水平平移量t_mat.at<float>(1, 1) = 1;t_mat.at<float>(1, 2) = 10; //竖直平移量//根据平移矩阵进行仿射变换cv::warpAffine(src, dst, t_mat, dst_sz);//显示平移效果cv::imshow("image", src);cv::imshow("result", dst);cv::waitKey(0);return 0;

旋转

旋转需要函数getRotationMatrix2D

Mat getRotationMatrix2D(Point2f center, double angle, double scale)

第一个参数,Point2f类型的center,表示源图像的旋转中心。

第二个参数,double类型的angle,旋转角度。角度为正值表示向逆时针旋转(坐标原点是左上角)。

第三个参数,double类型的scale,缩放系数

cv::Mat src = cv::imread("lenna.jpg");cv::Mat dst;//旋转角度double angle = 45;cv::Size src_sz = src.size();cv::Size dst_sz(src_sz.height, src_sz.width);int len = std::max(src.cols, src.rows);//指定旋转中心(图像中点)cv::Point2f center(len / 2., len / 2.);//获取旋转矩阵(2x3矩阵)cv::Mat rot_mat = cv::getRotationMatrix2D(center, angle, 1.0);//根据旋转矩阵进行仿射变换cv::warpAffine(src, dst, rot_mat, dst_sz);//显示旋转效果cv::imshow("image", src);cv::imshow("result", dst);cv::waitKey(0);return 0;

如果觉得《计算机视觉基础:图像处理Task 02 几何变换》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。