读书笔记-opencv-投影变换

原理解析

​ 透视变换是将图片投影到一个新的视平面,也称作投影映射.它是二维(x,y)到三维(X,Y,Z),再到另一个二维(x′,y′)空间的映射.相对于仿射变换,它提供了更大的灵活性,将一个四边形区域映射到另一个四边形区域(不一定是平行四边形).它不止是线性变换.但也是通过矩阵乘法实现的,使用的是一个3x3的矩阵,矩阵的前两行与仿射矩阵相(m11,m12,m13,m21,m22,m23),也实现了线性变换和平移,第三行用于实现透视变换

​ 在公式两边同时除以m33,得到一个有关8个未知数的方程组,只需要四个点就可以求出相关系数。
具体的推理过程,可以参见单应性变换,透视变换相关帖子。

代码示例

​ opencv提供相关的函数:

cv2.getPerspectiveTransform(src, dst)

​ 其中src是变换前坐标,dst是变换后的坐标,返回33的矩阵src和dst是4 * 2的二维ndarry,数据必须为32位浮点型

python实例

src_points = np.array([[165., 270.], [835., 270.], [360., 125.], [615., 125.]], np.float32)
dst_points = np.array([[165., 270.], [835., 270.], [165., 30.], [835., 30.]], dtype = "float32")
M = cv2.getPerspectiveTransform(src_points, dst_points)print(M)

​ 返回矩阵M是float64的数据类型

​ 对图片进行处理

if __name__ == "__main__":image_path = "c:\\users\\pictures\\saved pictures\\1.jpg"image = cv2.imread(image_path)#原图的宽高h,w = image.shape[:2]#原图的四个点与投影变换对应的点src = np.array([[0.0, 0.0],[w-1, 0], [0, h-1], [w-1, h-1]], np.float32)dst = np.array([[50, 50], [w/3, 50], [50, h-1], [w-1, h-1]], np.float32)#计算投影变换矩阵p = cv2.getPerspectiveTransform(src, dst)#利用计算出来的投影变换矩阵计算图像的投影变换r = cv2.warpPerspective(image, p, (w,h), borderValue=125)#显示原图和投影效果cv2.imshow("image", image);cv2.imshow("warpPersperctive", r)cv2.waitKey(0)cv2.destroyAllWindows()

​ 结果处理的图片:

C++实例

//method 1
//原矩阵Point2f src[] = { Point2f(0,0), Point2f(200.0, 0), Point2f(0,200.0), Point2f(200.0, 200.0) };//投影变换后的矩阵Point2f dst[] = { Point2f(100.0, 20.0), Point2f(200.0, 20.0), Point2f(50, 70), Point2f(250.0, 70.0) };//投影变换矩阵Mat M = getPerspectiveTransform(src, dst);//method 2
//原矩阵Mat src = (Mat_<float>(4, 2) << 0, 0, 200, 0, 0, 200, 200, 200);//投影变换后的矩阵Mat dst = (Mat_<float>(4, 2) << 100, 20, 200, 20, 50, 70, 250, 70);//投影变换矩阵Mat M = getPerspectiveTransform(src, dst);

对图片进行处理:

#include<opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui_c.h>
#include<iostream>
#include<string>
using namespace cv;/************************************************************************/
/* 注意CV_EVENT_LBUTTONDOWN需要加载头文件 <opencv2/highgui/highgui_c.h>
void circle(Mat & img, Point center, int radius, const Scalar & color, int thickness = 1, int lineType = 8, int shift = 0
该函数在途中用来画圆, img 代表输入图像, center代表圆心,color代表颜色, thickness代表线条的粗细, linetype线的类型,
opencv还提供rectangle, ellipse,line在图上画相应的线段*/
/************************************************************************/Mat InitImage;                    //原图
Mat convertImage;               //转换后的图像Point2f IPoint, pIPoint;
int i = 0, j = 0;
Point2f src[4];                 //存储原坐标
Point2f dst[4];                 //存储对应的变换的坐标//通过以下鼠标事件,在要原图上面取四个坐标
/**
* @鼠标点击事件
* @return void
*/
void mouse_I(int event, int x, int y, int flags, void *param)
{switch (event){//记录左键case CV_EVENT_LBUTTONDOWN:IPoint = Point2f(x, y);                    //记录坐标break;case CV_EVENT_LBUTTONUP:src[i] = IPoint;circle(InitImage, src[i], 7, Scalar(0), 3);        //标记i += 1;break;default:break;}
}//通过以下鼠标事件,在要输出的画布上面取四个对应坐标
/**
* @鼠标点击事件,在要输出的画布上面取四个对应坐标
* @return void
*/
void mouse_pI(int event, int x, int y, int flags, void *param)
{switch (event){case CV_EVENT_LBUTTONDOWN:pIPoint = Point2f(x, y);break;case CV_EVENT_LBUTTONUP:dst[j] = pIPoint;circle(convertImage, dst[j], 7, Scalar(0), 3);j += 1;break;default:break;}
}int main()
{//加载图片,imread(),第二个参加代表以何种方式加载,具体可以看Opencv的imread()函数解析std::string iamgePath = "C:\\Users\\huangxin\\Pictures\\Saved Pictures\\1.jpg";InitImage = imread(iamgePath, 1);if (!InitImage.data){return -1;}//输出图像convertImage = 255 * Mat::ones(InitImage.size(), CV_8UC1);//在原图定义,鼠标事件namedWindow("InitImage", 1);setMouseCallback("InitImage", mouse_I, NULL);//在输出窗口定义,鼠标事件namedWindow("ConvertImage", 1);setMouseCallback("ConvertImage", mouse_pI, NULL);imshow("InitImage", InitImage);imshow("ConvertImage", convertImage);while (!(i == 4 && j == 4)){imshow("InitImage", InitImage);imshow("ConvertImage", convertImage);if (waitKey(50) == 'q'){break;}}imshow("InitImage", InitImage);imshow("ConvertImage", convertImage);//移除鼠标事件setMouseCallback("InitImage", NULL, NULL);setMouseCallback("ConvertImage", NULL, NULL);//计算投影变换矩阵Mat p = getPerspectiveTransform(src, dst);//投影变化Mat resultMat;warpPerspective(InitImage, resultMat, p, convertImage.size());imshow("result: ", resultMat);waitKey(0);return 0;}

​ 在原图点击四个点,作为输入矩阵,在convertImage上面点击四个点作为输出矩阵,通过两个矩阵建立投影变换矩阵。

​ 处理的结果图片:

读书笔记-opencv-投影变换相关推荐

  1. Practical Python and OpenCV 3rd Edition读书笔记_Chapter8_Smoothing and Blurring平滑与模糊_思维导图

    <Practical Python and OpenCV 3rd Edition>真的是一本非常棒的入门书籍. 它也很薄,只有166页,虽然是纯英文的,如果静下心来认真看一两天就可以读完. ...

  2. 《Master Opencv...读书笔记》非刚性人脸跟踪 II

    上一篇博文中,我们了解了系统的功能和模块,明确了需要采集哪些类型的样本点及利用类的序列化的保存方式.这次将介绍几何约束模块,通过统计形态分析法(Statistical Shape Analysis, ...

  3. WPF,Silverlight与XAML读书笔记第三十九 - 可视化效果之3D图形

    原文:WPF,Silverlight与XAML读书笔记第三十九 - 可视化效果之3D图形 说明:本系列基本上是<WPF揭秘>的读书笔记.在结构安排与文章内容上参照<WPF揭秘> ...

  4. 《Hands-On Machine Learning with Scikit-Learn TensorFlow》读书笔记(三):分类

    最近有时间看书了,把以前想看的书捡一下,翻译中顺便加上自己的理解,写个读书笔记. 注意:下面的"数字+s"表示的是数字的类别,加上s是和纯数字区别开. 在上上篇中,我们提到最常见的 ...

  5. CVPR读书笔记[5]:Gabor特征提取之Gabor核的实现

    朱金华  jinhua1982@gmail.com   2014.08.09 本文參考http://blog.csdn.net/njzhujinhua/article/details/38460861 ...

  6. 机器视觉算法与应用读书笔记(算法)

    机器视觉算法与应用读书笔记(算法) 1.数据结构 2.图像增强 1. 灰度值变换 2. 辐射标定 3. 图像平滑 1. 时域去噪法 2. 空间域去噪法 均值滤波器 递归线性滤波器:将上次计算得到的值带 ...

  7. 《第6讲 非线性优化 》读书笔记

    本文是<视觉SLAM十四讲>第6讲的个人读书笔记,为防止后期记忆遗忘写的. 本节知识脉络 对状态估计问题,通过概率论中贝叶斯公式,求解后验概率等价于求解最大似然函数.求解最大似然函数等价于 ...

  8. 计算机图形学 读书笔记(一) 基础概念

    写个读书笔记,一来作为字典以后可以查,二来记录自己的理解. 并没有对每个知识点的详细解释,大部分只有主观的定性的解释. 大量的配图用的清华大学的PPT里的图,会不会有版权问题呀....让我删我就删.. ...

  9. 读书笔记 -《Python 黑帽子》 ( 三 )

    读书笔记系列文章 一直都在读书,读了忘,忘了再读.不如把每次学到的东西都写下来 第四章 Scapy: 网络的掌控者 Scapy 的十分强大的,前两章的东西可以用 Scapy 用简单的几行代码就能实现. ...

最新文章

  1. L1-039. 古风排版
  2. Eclipse——Java可视化开发环境配置
  3. c# rar解压大小_C#利用WinRAR实现压缩和解压缩
  4. LeetCode 1768. 交替合并字符串
  5. 京东商品及评论爬虫(selenium)
  6. 请给出linux中查看系统已经登录用户的命令?
  7. 计算机原理基础-原反补
  8. 14.jQuery常用方法
  9. 5G浪潮推动 射频产业风起云涌
  10. C++万能头文件(真心佩服!)
  11. 饿了么UI库--Vue开发必备神器--让你轻松设计出好看的页面
  12. 删除ubuntu双系统后,开机出现grub黑屏,删除双系统引导项解决
  13. 最小径集的算法_最小割集Stoer-Wagner算法 | 学步园
  14. [转]Cryengine渲染引擎剖析
  15. 微信卡包是属于什么服务器,微信卡包有哪些会员卡
  16. CSDN程序员过中秋,那是一个热闹
  17. python-requests官网_Python-Requests1-批量登录获取uid
  18. 小红伞命令行工具ScanCL使用安装
  19. 在Idea解决找不到sun.misc.BASE64Encoder及sun.misc.BASE64Decoder找不到包
  20. 亲测UEFI启动模式的电脑安装Win10和Ubuntu双系统(dell笔记本和hp笔记本)

热门文章

  1. Cucumber-java初使用
  2. 【青少年编程】【Scratch】01 运动模块
  3. 计算机视觉(CV)概述
  4. 前端基础速成day02--tabel的相关属性
  5. 供应商管理及评审制度
  6. linux中vi和vim的区别
  7. 计算机开始按钮作用,电脑“WIN”键的这些功能,你都知道么?
  8. 教学科研上云,中国地质大学携手EasyStack打造智慧校园
  9. [英语阅读]德国:经济危机下恢复圣诞真谛
  10. C#打开摄像头后获取图片,调用face_recognition进行人脸识别