抚州网站开发,百度贴吧官网app下载,网站开发质保,微信小程序设计几何空间变换【1】几何变换#xff08;空间变换#xff09;简述【2】变换矩阵知识简述齐次坐标的概念几何运算矩阵【3】图像的仿射变换1、平移变换2、比例缩放3、旋转4、对称变换#xff08;不做展示#xff09;1、关于X轴变换2、关于Y轴变换3、关于直线YX变换4、关于直线Y…
几何空间变换【1】几何变换空间变换简述【2】变换矩阵知识简述齐次坐标的概念几何运算矩阵【3】图像的仿射变换1、平移变换2、比例缩放3、旋转4、对称变换不做展示1、关于X轴变换2、关于Y轴变换3、关于直线YX变换4、关于直线Y-X变换5、错切变换6、复合变换【4】图像的投影变换【5】应用【6】Opencv自带的变换函数Opencv中仿射变换的函数warpAffine()函数Opencv中计算二维旋转变换矩阵: getRotationMatrix2D()函数【1】几何变换空间变换简述 图像的几何变换又称空间变换,是图形处理的一个方面是各种图形处理算法的基础。它将一幅图像中的坐标位置映射到另一幅图像中的新坐标位置,其实质是改变像素的空间位置,估算新空间位置上的像素值。 几何变换算法一般包括空间变换运算和插值算法。 【2】变换矩阵知识简述
齐次坐标的概念
图像一般是二维的坐标形式为(x,y)。 这里我们将其扩展为3维形式的齐次坐标。形式如下 第三个参数是尺度参数控制尺度缩放。1的时候表示尺度不变 齐次坐标使用n1维来表示n维的坐标。它的优点如下所示 ●统一坐标的加法运算和乘法运算, 运算时提高效率。 ●表示无穷远的点。 当z0的时候,表示无穷远的点。 ( x,y,z) -----( x/z, y/z) ;齐次坐标和二维坐标的换算 如(2,2,1)(4,4,2 )表示同样的点。 几何运算矩阵 最左边是变换后的齐次坐标中间的是原图点的其次坐标最右边是变换矩阵有9个参数分为4个子矩阵每个子矩阵具有特殊意义。 T1:比例、旋转、对称、错切 T2:平移 T3:投影 T4整体缩放通常我们通过T1实现缩放所以这里通常为1 所谓的仿射变换其实就是通过T1、T2进行变换。 所谓的投影变换就是在仿射变换上多用到了T3。 这里我们忽略T4。
【3】图像的仿射变换
为了能够直观地了解参数对于变换的各种影响我编写了一个程序通过滑动条来控制参数同时显示参数改变后的图像。 这里的参数我都是设的正的你把滑动条从正最大移到0就相当于是逆操作了。 代码如下
#include opencv2/opencv.hpp
#include iostream
#include windows.h
#include stdio.h
#define WINDOW_NAME 【程序窗口】 //为窗口标题定义的宏using namespace cv;
using namespace std;//*--------------------------【全局变量声明】-------------------------------------*///*--------------------------【T1】-------------------------------------*/
int g_nValueA 100;
int g_nValueB 0;
int g_nValueC 0;
int g_nValueD 100;
//*--------------------------【T2】-------------------------------------*/
int g_nValueL 50;
int g_nValueM 50;
//*--------------------------【T3】-------------------------------------*/
int g_nValueP 0;
int g_nValueQ 0;
//*--------------------------【T4】-------------------------------------*/
int I_max 400;
int g_nValueS 100;
int theta 0;
int change_switch 0;
int center_x I_max / 2;
int center_y I_max / 2;
Mat g_srcImage,g_dstImage;void on_change(int, void*); //回调函数int main()
{SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_GREEN); //字体为绿色//原图仿射变换后的图旋转变换后的图g_srcImage Mat::zeros(I_max, I_max, CV_8UC1);g_dstImage Mat::zeros(I_max, I_max, CV_8UC1);for (int i I_max/2;i I_max/250;i) //行循环{for (int j I_max / 2;j I_max / 2 50;j) //列循环{//-------【开始处理每个像素】---------------g_srcImage.atuchar(i, j) 255;//-------【处理结束】---------------}}namedWindow(WINDOW_NAME, WINDOW_NORMAL);//WINDOW_NORMAL允许用户自由伸缩窗口imshow(原图, g_srcImage);//【4】创建滑动条来控制阈值createTrackbar(a, WINDOW_NAME, g_nValueA,150, on_change);createTrackbar(b, WINDOW_NAME, g_nValueB, 150, on_change);createTrackbar(c, WINDOW_NAME, g_nValueC, 150, on_change);createTrackbar(d, WINDOW_NAME, g_nValueD, 150, on_change);createTrackbar(l, WINDOW_NAME, g_nValueL, 150, on_change);createTrackbar(m, WINDOW_NAME, g_nValueM, 150, on_change);createTrackbar(p, WINDOW_NAME, g_nValueP, 150, on_change);createTrackbar(q, WINDOW_NAME, g_nValueQ, 150, on_change);createTrackbar(s, WINDOW_NAME, g_nValueS, 150, on_change);createTrackbar(角度, WINDOW_NAME, theta, 360, on_change);createTrackbar(switch, WINDOW_NAME, change_switch, 1, on_change);on_change(0,0); //初始化回调函数//【7】轮询等待用户按键如果ESC键按下则退出程序while (1){if (waitKey(10) 27) break; //按下Esc 退出}return 0;}
//*--------------------------【on_Threshold 函数】-------------------------------------*/
void on_change(int, void*)
{g_dstImage Mat::zeros(I_max, I_max, CV_8UC1);float a g_nValueA * 0.01;float b g_nValueB * 0.01;float c g_nValueC * 0.01;float d g_nValueD * 0.01;int l g_nValueL;int m g_nValueM;float p g_nValueP * 0.0005;float q g_nValueQ * 0.0005;float s g_nValueS * 0.01;int x_change, y_change;//将参数进行处理//计算坐标if (change_switch 0){for (int x I_max / 2;x I_max / 2 50;x) //行循环{for (int y I_max / 2;y I_max / 2 50;y) //列循环{x_change (a * x c * y l) / (p * x q * y 1);y_change (b * x d * y m) / (p * x q * y 1);//限幅 if (x_change I_max) x_change I_max - 1;else if (x_change 0) x_change 0;else{}if (y_change I_max) y_change I_max - 1;else if (y_change 0) y_change 0;else{}g_dstImage.atuchar(x_change, y_change) 255;}}}else{a cos(theta);b sin(theta);c -1 * sin(theta);d cos(theta);for (int x I_max / 2;x I_max / 2 50;x) //行循环{for (int y I_max / 2;y I_max / 2 50;y) //列循环{x_change (x - center_x) * cos(theta) - (y - center_y) * sin(theta) center_x;y_change (x - center_x) * sin(theta) (y - center_y) * cos(theta) center_y;//限幅 if (x_change I_max) x_change I_max - 1;else if (x_change 0) x_change 0;else{}if (y_change I_max) y_change I_max - 1;else if (y_change 0) y_change 0;else{}g_dstImage.atuchar(x_change, y_change) 255;}}}//更新效果图imshow(效果图, g_dstImage);
}原图如下 接下来看具体变换
1、平移变换 效果展示
2、比例缩放 效果展示
3、旋转 这里的旋转是以原点为中心点的当我们以center_xcenter_y为中点则需要修改公式为 X’(X-center_x)*cos(theta)-(Y-center_y)*sin(theta) center_x; Y’(X-center_x)*sin(theta)(Y-center_y)*cos(theta) center_y ; 效果展示
4、对称变换不做展示
1、关于X轴变换 2、关于Y轴变换 3、关于直线YX变换 4、关于直线Y-X变换 5、错切变换 效果展示
6、复合变换 【4】图像的投影变换 点共线特性原本是一条直线变换后还是一条直线 效果展示
【5】应用 由原理可知变换的本质就是通过对应点组的坐标来求解方程。一个变换是否理想在公式不做调整的情况下就要看对应点的选择。 这里我们一般选择图像的特征点。这些知识会在以后展开讲哲理不做过多扩展。像上面的二维码变换我们选取的特征点考虑那三个定位点当然还要再找一个特征点。以后掌握了这方面知识再补充。
【6】Opencv自带的变换函数
Opencv中仿射变换的函数warpAffine()函数
公式依据 C: void warpAffine (InputArray src, OutputArray dst, InputArray M, Size dsize, int flagsINTER_LINEARintborderModeBORDER_CONSTANT const Scalar borderValueScalar() ) 第一个参数InputArray 类型的src输入图像即源图像填Mat类的对 象即可。 第二个参数OutputArray 类型的dst 函数调用后的运算结果存在这里 需和源图片有一样的尺寸和类型。 第三个参数InputArray 类型的M2x3 的变换矩阵。 第四个参数Size 类型的dsize,表示输出图像的尺寸。 第五个参数int 类型的flags 插值方法的标识符。此参数有默认值 INTER_ LINEAR(线性插值)可选的插值方式如下图所示。 第六个参数int类型的borderMode边界像素模式默认值为 BORDER CONSTANT。 第七个参数const Scalar类型的borderValue 在恒定的边界情况下取的 值默认值为Scalar(), 即0。 Opencv中计算二维旋转变换矩阵: getRotationMatrix2D()函数 C: Mat getRotationMatrix2D (Point2fcenter, double angle, double scale) 第一个参数Point2f 类型的center,表示源图像的旋转中心。 第二个参数double类型的angle,旋转角度。角度为正值表示向逆时针旋转(坐标原点是左上角)。 第三个参数double 类型的scale,缩放系数。 int main()
{SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_GREEN); //字体为绿色//【1】参数准备//定义两组点代表两个三角形Point2f srcTriangle[3];Point2f dstTriangle[3];//定义Mat变量变换矩阵Mat rotMat(2, 3, CV_32FC1); //CV_32FC1代表多少Mat warpMat(2, 3, CV_32FC1); //CV_32FC1代表多少Mat srcImage, dstImage_warp, dstImage_warp_roate;//原图仿射变换后的图旋转变换后的图srcImage imread(D:\\opencv_picture_test\\形态学操作\\黑白.jpg);//判断图像是否加载成功if (srcImage.empty()){cout 图像加载失败! endl;return -1;}elsecout 图像加载成功! endl endl;dstImage_warp Mat::zeros(srcImage.rows, srcImage.cols, srcImage.type()); //转换图和原图像类型一样大小一样//【2】利用三组对应点来计算参数srcTriangle[0] Point2f(0, 0); //这些选择自己决定srcTriangle[1] Point2f(0, 0);srcTriangle[2] Point2f(0, 0);dstTriangle[0] Point2f(0, 0);dstTriangle[1] Point2f(0, 0);dstTriangle[2] Point2f(0, 0);//【3】求得仿射变换参数warpMat getAffineTransform(srcTriangle, dstTriangle); //利用对应点求得6个参数//【4】对原图进行仿射变换warpAffine(srcImage,dstImage_warp,warpMat,dstImage_warp.size());//【5】获取旋转信息Point center Point(dstImage_warp.cols / 2, dstImage_warp.rows / 2); //中心点double angle -30.0; //顺时针30度double scale 0.8;//【6】通过上面的旋转细节信息求得旋转矩阵rotMat getRotationMatrix2D(center, angle,scale);//【7】对缩放后的图像进行旋转warpAffine(dstImage_warp,dstImage_warp_roate, rotMat,dstImage_warp.size());//【8】显示结果namedWindow(原图像, WINDOW_NORMAL); //定义窗口显示属性imshow(原图像, srcImage);namedWindow(缩放图, WINDOW_NORMAL); //定义窗口显示属性imshow(缩放图, dstImage_warp);namedWindow(缩放旋转图, WINDOW_NORMAL); //定义窗口显示属性imshow(缩放旋转图, dstImage_warp_roate);//创建三个窗口waitKey(0);return 0;
}效果 PPT是盗用的我们李竹老师的嘿嘿。