数字图象处理——仿射变换
来源:互联网 发布:淘宝家具沙发 编辑:程序博客网 时间:2024/05/01 06:04
在《数字图象处理》中提供了基于
图像仿射矩阵T。图像旋转、偏移变换等变换原理相同,根据这些在自己实现时,可分为三个步骤:
坐标转换
这些变换是以图像的中心为坐标原点(O’(x’,y’)),而图片原本设定是以图像左上角为坐标原点(O(x,y))。所以要进行坐标的变换。
用矩阵的方式表示:
逆运算:
图像变换
变换公式:
逆运算:- 坐标还原
因为此时,坐标原点是在图像的中心,为方便操作需要将坐标原点重新变换到图像左上角。
从旋转后到旋转前的坐标变换为:
(w’,h’是旋转后的图像的宽高);
而逆运算为:
(1)
下面是旋转的最邻近内插法和双线性内插法的实现:
其实在实现中,最重要的是求出变换后的图像宽高,再根据(1)式推出变换后的每一个像素点对应的原图像坐标。根据(1)式计算原图像像素点坐标x,y时,结果中分别会有一个常量,用dx,dy表示。
void nearestInterpolation(Mat &src, Mat &dst, float dx, float dy, double theta);int mainqqw(){ cv::Mat src = imread("D:/xitong/picture/rain.jpg"); namedWindow("orginal"); imshow("orginal", src); int srcwidth = src.cols; int srcheigh = src.rows; /*旋转角度*/ double theta = 30.0f*3.1415926 / 180.0f; /* 转换坐标原点到图像中心 ∧y | 0 | 1 | --------o--------->x | 2 | 3 | */ float srcX[4], srcY[4]; srcX[0] = (float)(-((srcwidth - 1) / 2)); srcX[1] = (float)((srcwidth - 1) / 2); srcX[2] = (float)(-(srcwidth - 1) / 2); srcX[3] = (float)((srcwidth - 1) / 2); srcY[0] = (float)((srcheigh - 1) / 2); srcY[1] = (float)((srcheigh - 1) / 2); srcY[2] = (float)(-(srcheigh - 1) / 2); srcY[3] = (float)(-(srcheigh - 1) / 2); /* 旋转后的图像坐标,此时坐标原点依然是旋转中心 */ float dstX[4], dstY[4]; for (int i = 0; i < 4; i++) { dstX[i] = cos(theta)*srcX[i] + sin(theta)*srcY[i]; dstY[i] = -sin(theta)*srcX[i] + cos(theta)*srcY[i]; } /* ==>旋转后图像长宽 */ int dstwidth = (max(fabs(dstX[3] - dstX[0]), fabs(dstX[2] - dstX[1])) + 0.5); int dstheigh = (max(fabs(dstY[3] - dstY[0]), fabs(dstY[2] - dstY[1])) + 0.5); /*Mat dst = Mat(Size(src.rows * 2, src.cols * 2), src.type(), Scalar::all(0)); nearestInterpolation(src, dst, 0.5);*/ Mat dst; dst.create(dstheigh, dstwidth, src.type()); //(1)式在运算后的常量,为运算方便提前的出结果 float dx = -0.5*dstwidth*cos(theta) - 0.5*dstheigh*sin(theta) + 0.5*srcwidth; float dy = 0.5*dstwidth*sin(theta) - 0.5*dstheigh*cos(theta) + 0.5*srcheigh; nearestInterpolation(src, dst, dx, dy, theta); waitKey(); return 0;}/* 最邻近内插旋转*/void nearestInterpolation(Mat &src, Mat &dst, float dx, float dy, double theta){ int x, y; for (int i = 0; i < dst.rows; i++) { for (int j = 0; j < dst.cols; j++) { /* 根据(1)式,推出对应原图像 像素坐标的运算结果 */ x = cvFloor(float(j)*cos(theta) + float(i)*sin(theta) + dx); y = cvFloor(float(-j)*sin(theta) + float(i)*cos(theta) + dy); if ((x < 0) || (x >= src.cols) || (y < 0) || (y >= src.rows)) { if (src.channels() == 3) dst.at<Vec3b>(i, j) = Vec3b(0, 0, 0); if (src.channels() == 1) dst.at<uchar>(i, j) = 0; } else { if (src.channels() == 3) dst.at<Vec3b>(i, j) = src.at<Vec3b>(y, x); if (src.channels() == 1) dst.at<uchar>(i, j) = src.at<uchar>(y, x); } } } namedWindow("最邻近内插旋转"); imshow("最邻近内插旋转", dst);}/* 双线性内插法旋转*/void bilinearRotate(Mat &src, Mat &dst, float dx, float dy, double theta){ float fu, fv; int x, y; Vec3b point[4]; uchar upoint[4]; for (int j = 0; j < dst.rows; j++) { for (int i = 0; i < dst.cols; i++) { fu = float(j)*cos(theta) + float(i)*sin(theta) + dx; fv = float(-j)*sin(theta) + float(i)*cos(theta) + dy; x = cvFloor(fu); y = cvFloor(fv); fu -= x; fv -= y; if ((x < 0) || (x >= src.cols-1) || (y < 0) || (y >= src.rows-1)) { if (src.channels() == 3) dst.at<Vec3b>(i, j) = Vec3b(0, 0, 0); if (src.channels() == 1) dst.at<uchar>(i, j) = 0; } else { if (src.channels() == 3) { point[0] = src.at<Vec3b>(y, x); point[1] = src.at<Vec3b>(y + 1, x); point[2] = src.at<Vec3b>(y, x + 1); point[3] = src.at<Vec3b>(y + 1, x + 1); dst.at<Vec3b>(i, j) = (1 - fu)*(1 - fv)*point[0] + (1 - fu)*(fv)*point[1] + (1 - fv)*(fu)*point[2] + fu*fv*point[3]; } if (src.channels() == 1) { upoint[0] = src.at<uchar>(y, x); upoint[1] = src.at<uchar>(y + 1, x); upoint[2] = src.at<uchar>(y, x + 1); upoint[3] = src.at<uchar>(y + 1, x + 1); dst.at<uchar>(i, j) = (1 - fu)*(1 - fv)*upoint[0] + (1 - fu)*(fv)*upoint[1] + (1 - fv)*(fu)*upoint[2] + fu*fv*upoint[3]; } } } } namedWindow("双线性内插法旋转"); imshow("双线性内插法旋转", dst);}
1 0
- 数字图象处理——仿射变换
- 图像变换——仿射变换
- 数字图象处理——简介
- Opencv——仿射变换和透视变换
- Opencv学习——仿射变换和透视变换
- opencv学习——仿射变换
- imgproc模块—仿射变换
- opencv 数字图象处理 图像平移变换
- 仿射变换&透视变换
- 几何变换 -- 仿射变换
- opencv——仿射变换的实现
- OpenCV中文网站例程——仿射变换
- Opencv学习笔记——仿射变换
- Halcon 学习总结——仿射变换
- 基础——仿射变换矩阵与warpAffine
- OpenCV—仿射变换warpAffine--旋转和缩放
- 《数字图象处理——基本的灰度变化》
- 《数字图象处理》——直方图均衡化
- 算法——排序——选择排序
- android:windowSoftInputMode属性详解
- visio2013提示“安装程序找不到office.zh-cn\branding.xml。请浏览确定有效的安装源,然后单击确定”
- android 百度地图路径规划问题(第一篇)
- Oracle server和client安装配置
- 数字图象处理——仿射变换
- 子网掩码、子网号和主机地址
- 寻找android中的设计模式(二)
- 中国SSL证书市场份额,沃通WoSign排名第一
- 简析Android的垃圾回收与内存泄露
- 检测点是否在扇形之内
- unity打包文件夹成zip格式(包括文件夹和子文件夹下的所有文件)
- matlab在一阶动态电路时域分析的应用
- Human Resource - Presentation