重映射

重映射就是把一幅图像中某个位置的像素放置到另一个图片中指定位置的过程。

用一个数学公式来表示就是:

其中的 f 就是映射方式,也就说,像素点在另一个图像中的位置是由 f 来计算的。

在OpenCV中,用的是remap函数实现重映射。

基本重映射

#include <iostream>
#include <opencv2\opencv.hpp>
#include <opencv2\imgproc\imgproc.hpp>
#include <opencv2\highgui\highgui.hpp>using namespace cv;
using namespace std;//基本重映射实验int main()
{Mat srcImage = imread("2.jpg");if (!srcImage.data){cout << "找不到这张图片!" << endl;return -1;}imshow("Src Pic", srcImage);Mat dstImage, map_x, map_y;dstImage.create(srcImage.size(), srcImage.type());//创建和原图一样的效果图map_x.create(srcImage.size(), CV_32FC1);map_y.create(srcImage.size(), CV_32FC1);//遍历每一个像素点,改变map_x & map_y的值,实现翻转180度for (int j = 0; j < srcImage.rows; j++){for (int i = 0; i < srcImage.cols; i++){map_x.at<float>(j, i) = static_cast<float>(i);map_y.at<float>(j, i) = static_cast<float>(srcImage.rows - j);}}//进行重映射操作remap(srcImage, dstImage, map_x, map_y, INTER_LINEAR, BORDER_CONSTANT, Scalar(0, 0, 0));imshow("重映射效果图", dstImage);  waitKey();return 0;
}

map_x与map_y分别代表目标图中的(x,y)点在原图中的x坐标(由map_x提供)与y坐标(由map_y提供)。

运行效果,图像翻转了。

仿射变换

仿射变换指的是一个向量空间进行一次线性变换并接上一个平移,变换为另一个向量空间的过程。

图像进行仿射变换后,有以下几个特点:
二维图形之间的相对位置关系保持不变,平行线依旧是平行线,且直线上的点的位置顺序保持不变。

一个任意的仿射变换都可以表示为乘以一个矩阵(线性变换)接着再加上一个向量(平移)的形式。

三种常见形式:

  • 旋转,rotation(线性变换)
  • 平移,translation(向量加)
  • 缩放,scale(线性变换)

仿射变换本质是一个2* 3的矩阵M乘上原图的每个坐标,得到目标图的对应点坐标。2*3矩阵M中的2表示目标点坐标的x与y,3中的第三维是平移分量。因此需要做的就是找到矩阵M,OpenCV提供 getAffineTransform 求出仿射变换, getRotationMatrix2D 来获得旋转矩阵。

这里简单说说仿射变换是怎么做到的。

现在有两幅图像(如下图),图像二是图像一经过放射变化得来的。那问题来了,我们怎么从这两个图像信息里挖掘出两图之间的映射关系?

很简单,只要在图像一种拿出三个点(1,2,3),图像二也拿出对应的三个点(1,2,3),就可以求出两图间的映射关系!

OpenCV通过两个函数的组合使用来实现仿射变换:

  • 使用warpAffine来实现简单重映射
  • 使用getRotationMatrix2D来获得旋转矩阵

#include<iostream>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>  using namespace std;
using namespace cv;
//仿射变换实验
int main()
{Mat src = imread("lol9.jpg");Mat dst_warp, dst_warpRotateScale;Point2f srcPoints[3];//原图中的三点  Point2f dstPoints[3];//目标图中的三点  //第一种仿射变换的调用方式:三点法//三个点对的值,上面也说了,只要知道你想要变换后图的三个点的坐标,就可以实现仿射变换  srcPoints[0] = Point2f(0, 0);srcPoints[1] = Point2f(0, src.rows - 1);srcPoints[2] = Point2f(src.cols - 1, 0);//映射后的三个坐标值dstPoints[0] = Point2f(0, src.rows*0.3);dstPoints[1] = Point2f(src.cols*0.25, src.rows*0.75);dstPoints[2] = Point2f(src.cols*0.75, src.rows*0.25);Mat M1 = getAffineTransform(srcPoints, dstPoints);//由三个点对计算变换矩阵  warpAffine(src, dst_warp, M1, src.size());//仿射变换  //第二种仿射变换的调用方式:直接指定角度和比例                                          //旋转加缩放  Point2f center(src.cols / 2, src.rows / 2);//旋转中心  double angle = 45;//逆时针旋转45度  double scale = 0.5;//缩放比例  Mat M2 = getRotationMatrix2D(center, angle, scale);//计算旋转加缩放的变换矩阵  warpAffine(dst_warp, dst_warpRotateScale, M2, src.size());//仿射变换  imshow("原始图", src);imshow("仿射变换1", dst_warp);imshow("仿射变换2", dst_warpRotateScale);waitKey(0);return 0;
}

两种仿射变换的效果如下。

有没有发现图片进行仿射变换后的背景被填充为黑色了?其实这个背景色是可以调的,像这样:

    warpAffine(dst_warp, dst_warpRotateScale, M2, src.size(), 1, 0, Scalar(11,111, 211));//利用Scalar来填充不同颜色背景

然后背景色就变成这样子了:

最后写一个对图片旋转任何角度的代码。

#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>using namespace cv;
using namespace std;#define PIC_BEGIN_NUM 100  //这里定义你的起始图片编号
#define ANGLE_START -45  //旋转角度的开始
#define ANGLE_END  0  //旋转角度的结束
#define ANGLE_STEP 2 //旋转角度步长int main(int argc, char **argv)
{//Read a single-channel imageconst char* filename = "lol9.jpg";Mat srcImg = imread(filename, 1);imshow("source", srcImg);Point center(srcImg.cols / 2, srcImg.rows / 2); //图片中心为旋转点char file[20];int count = PIC_BEGIN_NUM; Mat tmpimg; for (int tmp = ANGLE_START; tmp < ANGLE_END; tmp += ANGLE_STEP){Mat rotMatS = getRotationMatrix2D(center, tmp, 0.5); //图片缩小到原来的0.5倍warpAffine(srcImg, tmpimg, rotMatS, srcImg.size(), 1, 0, Scalar(0, 0, 0));//填充黑色背景                                                                           sprintf(file, "%d.jpg", count++);  //旋转图片以1.jpg  2.jpg 的名字格式保存imwrite(file, tmpimg);}waitKey(0);return 0;
}

这里的代码实现对图片旋转2度、4度...45度的功能,并将这些旋转后的图像保存先来。
然后文件夹下就出现旋转好的图片了!

OpenCV精进之路(七):图像变换——重映射与仿射变换相关推荐

  1. OpenCV探索之路(八):重映射与仿射变换

    重映射 重映射就是把一幅图像中某个位置的像素放置到另一个图片中指定位置的过程. 用一个数学公式来表示就是: 其中的 f 就是映射方式,也就说,像素点在另一个图像中的位置是由 f 来计算的. 在Open ...

  2. OpenCV精进之路(十六):图像分解和融合技术——图像拼接和图像融合技术

    图像拼接在实际的应用场景很广,比如无人机航拍,遥感图像等等,图像拼接是进一步做图像理解基础步骤,拼接效果的好坏直接影响接下来的工作,所以一个好的图像拼接算法非常重要. 再举一个身边的例子吧,你用你的手 ...

  3. OpenCV:remap()简单重映射

    学习自:[OpenCV入门教程之十七]OpenCV重映射 重映射,就是把一幅图像中某位置的像素放置到另一个图片指定位置的过程. 为了完成映射过程, 我们需要获得一些插值为非整数像素的坐标,因为源图像与 ...

  4. opencv mat赋值_【3】OpenCV图像处理模块(18)重映射

    本例中使用OpenCV的remap()函数实现简单的图像重映射(remapping). 什么是重映射? 将一幅图像中的像素,改变位置得到一副新的图像,如图像缩放.翻转等. 因为源图像和新图像之间不一定 ...

  5. 【OpenCV】重映射及仿射变换

    重映射Remapping void cv::remap ( InputArray src, OutputArray dst,InputArray map1, InputArray map2,int i ...

  6. 边缘检测、霍夫变换、重映射、仿射变换、直方图均衡化

    文章目录 1.基于 OpenCV 的边缘检测 1.1 边缘检测的一般步骤 1.2 canny 算子 1.2.1 canny 边缘检测的步骤 1.2.2 Canny 边缘检测:Canny() 函数 1. ...

  7. OpenCV精进之路(二十三):实例——Bag of Features(BoF)图像分类实践

    在深度学习在图像识别任务上大放异彩之前,词袋模型Bag of Features一直是各类比赛的首选方法.首先我们先来回顾一下PASCAL VOC竞赛历年来的最好成绩来介绍物体分类算法的发展. 从上表我 ...

  8. OpenCV精进之路(二十二):实例——皮肤检测技术

    好久没写博客了,因为最近都忙着赶项目和打比赛==| 好吧,今天我打算写一篇关于使用opencv做皮肤检测的技术总结.那首先列一些现在主流的皮肤检测的方法都有哪些: RGB color space Yc ...

  9. OpenCV精进之路(十九):工具——程序打包发布

    我们经常遇到这样的需求:我们在VS写好的程序,需要在一个没有装opencv甚至没有装vs的电脑下运行,跑出效果.比如,你在你的电脑用opencv+vs2015写出一个程序,然后老师叫你把程序发给他,他 ...

最新文章

  1. Cannot change version of project facet Dynamic Web Module to 2.5 问题的解决方法
  2. Cordova:安卓启动页图片变形
  3. db2 replace函数的用法_SQL基础知识:常用字符处理函数
  4. Apache web服务
  5. 台式电脑主板测试/升级BIOS
  6. 【简便解法】1078 字符串压缩与解压 (20分)_42行代码AC
  7. java 微信支付实现
  8. 阅读react-redux源码(五) - connectAdvanced中store改变的事件转发、ref的处理和pure模式的处理
  9. python代替shell脚本_python的简洁是shell无法代替的
  10. 如何浅显得理解风控模型中的特征筛选|附实操细节(全)
  11. GIVE root password for maintenance
  12. 线性表的链式存储结构-----链表
  13. QLabel显示QImage时报错
  14. 苹果录屏没声音_iPhone XR突然没声音如何解决?西安苹果售后维修点教你几招方法...
  15. 如何写出一篇好的A-Level历史 essay?
  16. Carlife Iphone IAP2连接与认证过程
  17. SQLI DUMB SERIES-1-2
  18. 类似ftp文件服务器有哪些,FTP的替代品有哪些,你知道吗?
  19. MayaToUE4之影视动画制作流程
  20. 小米推送 java demo_XiaomiPushDemo【小米推送集成,基于V3.6.12版本】

热门文章

  1. 【汇编语言与计算机系统结构笔记10】C语言数组的汇编访问:连续存储、代码优化、无边界检查;结构对齐要求 #简洁笔记形式
  2. SSH框架总结(框架分析+环境搭建+实例源码下载)
  3. root用户重置其他密码
  4. ISE_FIFO_IP核接口测试(二)
  5. EDA实验课课程笔记(八 )——PT(Prime Time)简介(附录静态时序分析)
  6. EDA实验课课程笔记(三)——TCL脚本语言的学习1
  7. oracle10g 安装手册 linux,oracle10g在x86linux上的安装步骤
  8. pytorch 入门学习反向传播-4
  9. MySQL WorkBench中文教程
  10. Shell in AIX Web端 自动远程执行重启tomcat服务命令