OpenCV3入门(九)图像几何变换
1、图像缩放
假设图像x轴的缩放因子Sx, y轴方向的缩放因子Sy,相应的变换表达式为:
函数原型为:
CV_EXPORTS_W void resize( InputArray src, OutputArray dst,
Size dsize, double fx = , double fy = ,
int interpolation = INTER_LINEAR );
示例程序如下。
img = imread("D:\\WORK\\5.OpenCV\\LeanOpenCV\\pic_src\\pic9.bmp");
imshow("原图", img);
resize(img, img2, Size(), 0.5, 0.5);
imshow("缩放图1", img2);
resize(img, img3, Size(), 0.8, 0.5);
imshow("缩放图2", img3);
运行效果如下图。
resize(img, img2, Size(), 1.2, 1.2);
2、图像平移
假设图像x轴的平移量Tx, y轴方向的平移量Ty,相应的变换表达式为:
仿射变换的原理为:
dst(x,y)=src(M11x+M12y+M13,M21x+M22y+M23)
平移操作可以使用OpenCV的仿射变换函数来实现,使用的变换矩阵为:
函数原型为:
CV_EXPORTS_W void warpAffine( InputArray src, OutputArray dst,
InputArray M, Size dsize,
int flags = INTER_LINEAR,
int borderMode = BORDER_CONSTANT,
const Scalar& borderValue = Scalar());
图像平移示例。
img = imread("D:\\WORK\\5.OpenCV\\LeanOpenCV\\pic_src\\pic9.bmp", IMREAD_GRAYSCALE);
imshow("原图", img); // x轴平移20,y轴平移10, 2 * 3矩阵
Mat M = Mat::zeros(, , CV_32FC1);
M.at<float>(, ) = ;
M.at<float>(, ) = ;
M.at<float>(, ) = ;
M.at<float>(, ) = ;
warpAffine(img, img2, M, img.size());
imshow("平移图", img2);
3、图像旋转
假设点P0(x0,y0),角度为a,令L=|OP|=sqrt(x*x + y*y).
P0旋转b度到P1(x1,y1),则
x1=L*cos(a+b)=L* cos(a)*cos(b) – L*sin(a)*sin(b) = x0*cos(b) - y0*sin(b)
y1=L*sin(a+b)=L* sin(a)*cos(b) + L*cos(a)*sin(b) = y0*cos(b) + x0*sin(b)
OpenCV内置仿射变换的旋转函数,支持任意点为中心的图像旋转,函数原型为:
CV_EXPORTS_W Mat getRotationMatrix2D( Point2f center, double angle, double scale );
示例代码如下。
img = imread("D:\\WORK\\5.OpenCV\\LeanOpenCV\\pic_src\\pic9.bmp");
imshow("原图", img); Point center = Point(img.cols / , img.rows / );
Mat m1= getRotationMatrix2D(center, , 1.0);
Mat m2 = getRotationMatrix2D(center, , 0.7);
Mat m3 = getRotationMatrix2D(center, , 1.2);
warpAffine(img, img1, m1, img.size());
warpAffine(img, img2, m2, img.size());
warpAffine(img, img3, m3, img.size());
imshow("img1", img1);
imshow("img2", img2);
imshow("img3", img3);
修改旋转角度效果如下图。
Mat m1= getRotationMatrix2D(center, 180, 1.0);
Mat m2 = getRotationMatrix2D(center, 270, 0.7);
如果旋转点的坐标原点不在图片中心,则图片绕着指定点旋转。
Point center = Point(, ); Mat m1= getRotationMatrix2D(center, , 1.0); Mat m2 = getRotationMatrix2D(center,-, 1.0);
对应的矩阵为:
m1=
[0.8660254037844387, 0.4999999999999999, 0;
-0.4999999999999999, 0.8660254037844387, 0]
m2=
[0.7071067811865476, -0.7071067811865476, 0;
0.7071067811865476, 0.7071067811865476, 0]
输出效果如下图。
4、图像重映射
重映射就是把一个图像中一个为之的像素放置到另一个图片指定位置过程。由于映射后的图像在原图中可能没有对应的整数坐标点像素,所以为了完成重映射需要做一些插值作为非整数像素坐标。我们通过重映射来表达每个像素的位置(x, y):g(x, y)=f(h(x,y))
OpenCV使用remap函数完成重映射功能,函数原型为:
CV_EXPORTS_W void remap( InputArray src, OutputArray dst,
InputArray map1, InputArray map2,
int interpolation, int borderMode = BORDER_CONSTANT,
const Scalar& borderValue = Scalar());
测试代码如下。
void update_map(int ind, Mat &map_x, Mat &map_y)
{
for (int i = ; i < map_x.rows; i++)
{
for (int j = ; j < map_x.cols; j++)
{
switch (ind)
{
case :
if (j > map_x.cols*0.25 && j < map_x.cols*0.75 && i > map_x.rows*0.25 && i < map_x.rows*0.75)
{
map_x.at<float>(i, j) = * (j - map_x.cols*0.25f) + 0.5f;
map_y.at<float>(i, j) = * (i - map_x.rows*0.25f) + 0.5f;
}
else
{
map_x.at<float>(i, j) = ;
map_y.at<float>(i, j) = ;
}
break;
case :
map_x.at<float>(i, j) = (float)j;
map_y.at<float>(i, j) = (float)(map_x.rows - i);
break;
case :
map_x.at<float>(i, j) = (float)(map_x.cols - j);
map_y.at<float>(i, j) = (float)i;
break;
case :
map_x.at<float>(i, j) = (float)(map_x.cols - j);
map_y.at<float>(i, j) = (float)(map_x.rows - i);
break;
default:
break;
} // end of switch
}
}
} int main() {
Mat src = imread("D:\\WORK\\5.OpenCV\\LeanOpenCV\\pic_src\\pic9.bmp");
imshow("原图", src); Mat dst(src.size(), src.type());
Mat map_x(src.size(), CV_32FC1);
Mat map_y(src.size(), CV_32FC1); update_map(, map_x, map_y);
remap(src, img1, map_x, map_y, INTER_LINEAR, BORDER_CONSTANT, Scalar(, , ));
imshow("img1", img1); update_map(, map_x, map_y);
remap(src, img2, map_x, map_y, INTER_LINEAR, BORDER_CONSTANT, Scalar(, , ));
imshow("img2", img2); update_map(, map_x, map_y);
remap(src, img3, map_x, map_y, INTER_LINEAR, BORDER_CONSTANT, Scalar(, , ));
imshow("img3", img3); update_map(, map_x, map_y);
remap(src, img4, map_x, map_y, INTER_LINEAR, BORDER_CONSTANT, Scalar(, , ));
imshow("img4", img4); waitKey();
}
输入图像:
代码实现四种remap效果。
remap后的图像:
例子2:x轴不压缩,y轴按照一元二次曲线进行压缩,对称抽为src.rows / 2。当y= src.rows / 2,对应变换前的图坐标src.rows,所以图像被压缩。当y=[ src.rows / 2,src.rows]时,y轴被反转。
for (int i = ; i < src.rows; i++)
{
for (int j = ; j < src.cols; j++)
{
map_x.at<float>(i, j) = j;
map_y.at<float>(i, j) = (float)((- * pow(i- src.rows / , ) / pow(src.rows / , )) + ) * src.rows;
}
}
5、参考文献
1、《OpenCV3 编程入门》,电子工业出版社,毛星雨著
2、《学习OpenCV》,清华大学出版社,Gary Bradski, Adrian kaehler著
3、Remapping
https://docs.opencv.org/3.4/d1/da0/tutorial_remap.html
4、OpenCV图像旋转
https://www.cnblogs.com/konglongdanfo/p/9135501.html
技术博客,转载请注明。
最新文章
- [LeetCode] Delete Node in a Linked List 删除链表的节点
- git学习:多人协作,标签管理
- ThinkPHP魔术方法
- 单片机TM4C123学习(七):I2C模块(温度传感器)
- ffmpeg编译x264, 这个libffmpeg即可解码又可以h264编码
- shell脚本等的操作
- windows CE 6.0编译报BLDDEMO: There were errors building MY283错误解决办法
- anaconda在linux下的安装注意事项
- [ZOJ 3622] Magic Number
- oracle审计
- Keil C51中函数指针的使用
- java中classPath和Xpath问题
- 题目要求:建立一个类Str,将一个正整数转换成相应的字符串,例如整数3456转换为字符串";3456";.
- 小程序input输入框获取焦点时,文字会出现闪动
- 微信公众号_订阅号_access_token_创建菜单_菜单name+表情
- BZOJ 3224 - 普通平衡树 - [Treap][Splay]
- sql 数据类型转换
- EasyARM-iMX283A的Linux 开发环境构建
- 有关ADO.NET基础中的基础的熟悉过程
- 使用libmagic确定文件MIME类型【示例】【转】