[opencv] 将摄像头图像做镜像变换(split, merge, 矩阵相乘)
来源:互联网 发布:软件功能过期怎么办 编辑:程序博客网 时间:2024/06/18 05:14
摄像头采集到的图像进行镜像变换,最简单的方法是逐点扫描然后重新赋值给一个新的矩阵。但是一张普通质量的图像也有十万级个像素点,这种方式做镜像变换,速度应该会很慢。
但是如果可以以矩阵的方式进行处理,访问图像更快,程序执行的速度也就更快。
以矩阵的方式操作原理如下:
比如有矩阵A,
想要将A镜像变换成B:
只需要在A右侧乘以一个反对角矩阵T:
所以,在程序中先生成一张反对角矩阵,然后在每一帧图像右乘它,就可以了。但是在代码实现时,要注意矩阵相乘要保证数据类型一致(opencv要求CV_32FC1, CV_64FC1等等),可以用Mat::convertTo()来实现。而且图像采集进来是三通道的,我们要把三个通道分别处理以后,再重新组合成一张彩色图。这就需要用到split()和merge()函数。
#include <opencv2/opencv.hpp>#include <iostream>using namespace std;using namespace cv;int main(){ //生成右乘矩阵 Mat inverse(300,300,CV_32F); for(int i=0;i<inverse.rows;i++){ for(int j=0;j<inverse.cols;j++){ if(i+j==inverse.rows-1) inverse.at<float>(i,j)=1; else inverse.at<float>(i,j)=0; } } VideoCapture capture(0); capture.set(CAP_PROP_FRAME_WIDTH,300); capture.set(CAP_PROP_FRAME_HEIGHT,180); Mat frame(180,300,CV_32FC3); Mat frameDisp(800,1440,CV_32FC3); vector<Mat> fms; cout<<"inverse matrix created!"<<endl; if(!capture.isOpened()) { cout<<"fail to open"<<endl; return -1; } namedWindow("frames"); //CV_WINDOW_NORMAL CV_WINDOW_AUTOSIZE //CV_WINDOW_FULLSCREEN //CV_WINDOW_FREERATIO CV_WINDOW_KEEPRATIO setWindowProperty("frames",CV_WND_PROP_FULLSCREEN,CV_WINDOW_FULLSCREEN); //CV_WND_PROP_FULLSCREEN CV_WND_PROP_AUTOSIZE CV_WND_PROP_ASPECTRATIO while(1){ capture>>frame; frame.convertTo(frame,CV_32FC3,1/255.0); //转换成可以相乘的矩阵数据类型 split(frame,fms); fms.at(0)=fms.at(0)*inverse; fms.at(1)=fms.at(1)*inverse; fms.at(2)=fms.at(2)*inverse; merge(fms,frame); resize(frame,frameDisp,frameDisp.size()); cout<<"frame channels : "<<frame.channels()<<endl; imshow("frames",frameDisp); if(waitKey(5)==' ') return 0; } return 0;}
Tips:
- Mat::convertTo()函数使用时,把彩色图像(CV_8UC3)转换成(CV_32FC3)时应该注意,convertTo()的第三个参数应该设置转换比例,此处是1/255.0(如果是反向转换,则应是255.0)。这是因为,imshow()函数显示(CV_8UC3)类型的图像时,数据范围是0~255,但是显示(CV_32FC3)时,数据范围是0~1.0。convertTo()第三个参数如果不设置,会把0~255的(CV_8UC3)图像转换成0~255.0(CV_32FC3),这样显示出来就是一片白色。
- 右乘的那个矩阵数据类型要选(CV_32F或者CV_32FC1)
- split()函数第二个参数,数据类型是
vector<mat>
- 显示窗口我还没有调出全屏效果,不知什么原因,有待研究。
补充:
在opencv里面,有一个flip()函数,可以进行图像的翻转。
其描述如下:
C++: void flip(InputArray src, OutputArray dst, int flipCode)Python: cv2.flip(src, flipCode[, dst]) → dstC: void cvFlip(const CvArr* src, CvArr* dst=NULL, int flip_mode=0 )Python: cv.Flip(src, dst=None, flipMode=0) → NoneParameters: src – input array. dst – output array of the same size and type as src. flipCode – a flag to specify how to flip the array; 0 means flipping around the x-axis and positive value (for example, 1) means flipping around y-axis. Negative value (for example, -1) means flipping around both axes (see the discussion below for the formulas).
0 0
- [opencv] 将摄像头图像做镜像变换(split, merge, 矩阵相乘)
- OpenCV 学习 (Split 和 Merge)
- opencv split merge
- opencv 矩阵相乘
- opencv图像旋转--矩阵旋转和仿射变换相比较
- 【OpenCV笔记 08】OpenCV中分离颜色通道split()和图像通道混合merge()
- opencv split和merge操作
- opencv split和merge操作
- 【OpenCV】 split和merge操作
- opencv split和merge操作
- opencv split和merge操作
- opencv split和merge操作
- opencv split和merge操作
- 将OpenCV:Mat矩阵图像转换为MFC:CImage图像
- opencv读取摄像头图像
- 【OpenCV】获取摄像头图像
- 图像处理-矩阵变换
- 将对称矩阵压缩存储,实现矩阵相乘,输出相乘后结果(用二维数组)
- swift之方法(Methods)
- POJ 1459 Power Network DINIC
- 封装
- (十一)洞悉linux下的Netfilter&iptables:iptables命令行工具源码解析【上】
- Java基础——Java的抽象机制,抽象方法抽象类和接口
- [opencv] 将摄像头图像做镜像变换(split, merge, 矩阵相乘)
- shader - 属性
- uboot Makefile 分析
- (十二)洞悉linux下的Netfilter&iptables:iptables命令行工具源码解析【下】
- 指令 机器指令 汇编指令 指令系统 汇编指令的基本构成 操作数
- iOS之系列设备的分辨率
- Git 分支 - 分支的新建与合并
- 强连通分量(模板)
- Android SwipeRefreshLayout:谷歌官方SDK包中的下拉刷新