1. 假设两个摄像头平行固定,所拍摄的图像视差很小,可以通过“柱面投影+模板匹配+渐入渐出融合”的解决方案实现视频拼接。
  2. 这种视频拼接的方法仅仅是使用模板匹配的方法,划定一个需要匹配的区域,然后水平和垂直方向查找相同的区域,然后对两张图片进行融合。
  3. 本文相机拼接的程序只是使用前3帧图像进行拼接,后面通过前三帧的匹配地方进行机械的拼接。
#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <opencv2/opencv.hpp>
#include<iostream>using namespace cv;
using namespace std;//以下3个函数,与系列文章:图像拼接(一)...中的函数,相同
//柱面投影//首先使用前3帧计算平移变量,然后使用固定的平移变量进行拼接Mat cylinder(Mat imgIn, int f);
//计算两幅图像之间的平移量
Point2i getOffset(Mat img, Mat img1);
//线性融合
Mat linearFusion(Mat img, Mat img1, Point2i a);int main()
{//VideoCapture cap1(0);VideoCapture cap2(1);//VideoCapture cap2;//if (!cap2.open("rtsp://admin:haikang123456@192.168.1.103/h264/ch1/main/av_stream"))//{//    std::cout << "Error opening video stream or file" << std::endl;//    return -1;//}VideoCapture cap2("./video/left_1.mp4");VideoCapture cap1("./video/right_2.mp4");double rate = 60;int delay = 1000 / rate;bool stop(false);Mat frame1;Mat frame2;Mat frame;Point2i a;//存储偏移量int k = 0;namedWindow("cam1", WINDOW_AUTOSIZE);namedWindow("cam2", WINDOW_AUTOSIZE);namedWindow("stitch", WINDOW_AUTOSIZE);if (cap1.isOpened() && cap2.isOpened()){cout << "*** ***" << endl;cout << "摄像头已启动!" << endl;}else{cout << "*** ***" << endl;cout << "警告:摄像头打开不成功或者未检测到有两个摄像头!" << endl;cout << "程序结束!" << endl << "*** ***" << endl;return -1;}cap1.set(CAP_PROP_FRAME_WIDTH, 1280);cap1.set(CAP_PROP_FRAME_HEIGHT, 720);cap2.set(CAP_PROP_FRAME_WIDTH, 1280);cap2.set(CAP_PROP_FRAME_HEIGHT, 720);cap1.set(CAP_PROP_FOCUS, 0);cap2.set(CAP_PROP_FOCUS, 0);while (!stop){if (cap1.read(frame1) && cap2.read(frame2)){imshow("cam1", frame1);imshow("cam2", frame2);//彩色帧转灰度cvtColor(frame1, frame1, COLOR_RGB2GRAY);cvtColor(frame2, frame2, COLOR_RGB2GRAY);//柱面投影变换//frame1 = cylinder(frame1, 1005);//frame2 = cylinder(frame2, 1005);//匹配和拼接/*视频拼接通过while循环实现,下面这个判断的意思是,有两*种情形才计算平移参数,一是程序启动时,前3个循环内;二*是按下回车键时。这样在场景和摄像头相对固定时,避免了平*移量的重复计算,提高了拼接的实时性*/if (k < 3 || waitKey(delay) == 13)//按回车键{cout << "正在匹配..." << endl;a = getOffset(frame1, frame2);}frame = linearFusion(frame1, frame2, a);imshow("stitch", frame);k++;}else{cout << "----------------------" << endl;cout << "waitting..." << endl;}//按下ESC键,退出循环,程序结束if (waitKey(1) == 27){stop = true;cout << "程序结束!" << endl;cout << "*** ***" << endl;}}return 0;
}//计算平移参数
Point2i getOffset(Mat img, Mat img1)
{Mat templ(img1, Rect(0, 0.4 * img1.rows, 0.2 * img1.cols, 0.2 * img1.rows));Mat result(img.cols - templ.cols + 1, img.rows - templ.rows + 1, CV_8UC1);//result存放匹配位置信息matchTemplate(img, templ, result, TM_CCORR_NORMED);            //这个是模板匹配函数,找到最匹配的位置normalize(result, result, 0, 1, NORM_MINMAX, -1, Mat());       //对匹配结果进行归一化double minVal; double maxVal; Point minLoc; Point maxLoc; Point matchLoc;minMaxLoc(result, &minVal, &maxVal, &minLoc, &maxLoc, Mat());       //在一个数组中找到全局最小值和全局最大值matchLoc = maxLoc;//获得最佳匹配位置int dx = matchLoc.x;int dy = matchLoc.y - 0.4 * img1.rows;//右图像相对左图像的位移Point2i a(dx, dy);return a;
}//线性(渐入渐出)融合
Mat linearFusion(Mat img, Mat img1, Point2i a)
{int d = img.cols - a.x;//过渡区宽度int ms = img.rows - abs(a.y);//拼接图行数int ns = img.cols + a.x;//拼接图列数Mat stitch = Mat::zeros(ms, ns, CV_8UC1);//拼接Mat_<uchar> ims(stitch);Mat_<uchar> im(img);Mat_<uchar> im1(img1);if (a.y >= 0){Mat roi1(stitch, Rect(0, 0, a.x, ms));img(Range(a.y, img.rows), Range(0, a.x)).copyTo(roi1);Mat roi2(stitch, Rect(img.cols, 0, a.x, ms));img1(Range(0, ms), Range(d, img1.cols)).copyTo(roi2);for (int i = 0; i < ms; i++)for (int j = a.x; j < img.cols; j++)ims(i, j) = uchar((img.cols - j) / float(d) * im(i + a.y, j) + (j - a.x) / float(d) * im1(i, j - a.x));}else{Mat roi1(stitch, Rect(0, 0, a.x, ms));img(Range(0, ms), Range(0, a.x)).copyTo(roi1);Mat roi2(stitch, Rect(img.cols, 0, a.x, ms));img1(Range(-a.y, img.rows), Range(d, img1.cols)).copyTo(roi2);for (int i = 0; i < ms; i++)for (int j = a.x; j < img.cols; j++)ims(i, j) = uchar((img.cols - j) / float(d) * im(i, j) + (j - a.x) / float(d) * im1(i + abs(a.y), j - a.x));}return stitch;
}//柱面投影校正
Mat cylinder(Mat imgIn, int f)
{int colNum, rowNum;colNum = 2 * f * atan(0.5 * imgIn.cols / f);//柱面图像宽rowNum = 0.5 * imgIn.rows * f / sqrt(pow(f, 2)) + 0.5 * imgIn.rows;//柱面图像高Mat imgOut = Mat::zeros(rowNum, colNum, CV_8UC1);Mat_<uchar> im1(imgIn);Mat_<uchar> im2(imgOut);//正向插值int x1(0), y1(0);for (int i = 0; i < imgIn.rows; i++)for (int j = 0; j < imgIn.cols; j++){x1 = f * atan((j - 0.5 * imgIn.cols) / f) + f * atan(0.5 * imgIn.cols / f);y1 = f * (i - 0.5 * imgIn.rows) / sqrt(pow(j - 0.5 * imgIn.cols, 2) + pow(f, 2)) + 0.5 * imgIn.rows;if (x1 >= 0 && x1 < colNum && y1 >= 0 && y1 < rowNum){im2(y1, x1) = im1(i, j);}}return imgOut;
}

双摄像头实时视频拼接(平移模型)相关推荐

  1. 图像拼接(十一):双摄像头实时拼接+stitching_detailed

    OpenCV自带的stitching模块在追求拼接质量方面已经做得很好了,但是实时性不够,即使是拼接两幅图像.比如源程序拼接两幅640*480分辨率的图像,拼接时间为4.78″. 对stitching ...

  2. 全景视频拼接(二):双摄像头获取视频

    项目要求:利用双摄像头同时采集两个视频,离线拼接,将两个视频拼接成一个视频. 该部分代码实现功能: 利用双摄像头获取视频 #include <iostream> #include < ...

  3. 手机双摄像头原理及产业解析----转载

    这个文章写得很好,特此转载,并致谢! 原文见于: https://blog.csdn.net/piaoxuezhong/article/details/79053974#comments 前记:本篇是 ...

  4. Camera--(7)手机双摄像头原理及产业解析

    本篇是对手机双摄原理及应用现状,未来布局的汇总. 为什么会出现双摄像头手机? 智能手机市场一直都是群雄争霸,竞争非常激烈.随着时代的发展,各大手机厂商的竞争焦点从以前的硬件军备竞赛逐渐延伸到影音娱乐领 ...

  5. 双摄像头测距的OpenCV实现

    虽然最近注意力已经不可遏制地被神经科学.大脑记忆机制和各种毕业活动吸引过去了,但是还是觉得有必要把这段时间双目视觉方面的进展总结一下.毕竟从上一篇博文发表之后,很多同仁发E-mail来与我讨论,很多原 ...

  6. 双眼可以测距和建立立体环境,双摄像头可以吗?

    编辑丨3D视觉工坊 点击进入->3D视觉工坊学习交流群 观点一 作者|robot9野生程序猿 https://www.zhihu.com/question/23418797/answer/395 ...

  7. 智能手机双摄像头产业链、工艺、及原理

    智能手机双摄像头产业链.工艺.及原理 http://www.tbqw.com/art/116192.html 栏目:科技数码   发布时间:2017/03/16   来源:光电与显示   编辑:TPD ...

  8. 双摄像头立体成像(三)-畸变矫正与立体校正

    双摄像头立体成像(三)-畸变矫正与立体校正 畸变矫正是上一篇博文的遗留问题,当畸变系数和内外参数矩阵标定完成后,就应该进行畸变的矫正,以达到消除畸变的目的,此其一. 在该系列第一部分的博文中介绍的立体 ...

  9. 基于改进SURF算法的实时视频拼接

    Journal of Image and Signal Processing Vol.04 No.04(2015), Article ID:16229,9 pages 10.12677/JISP.20 ...

  10. camera (14)---智能手机双摄像头原理解析:RGB +Depth

    智能手机双摄像头原理解析:RGB +Depth 智能手机摄像头中:普通彩色相机(RGB) + 深度相机(Depth)的技术原理. 首先来解释一下什么是深度相机吧. 深度相机 顾名思义,深度相机就是可以 ...

最新文章

  1. 数据结构7.6_最短路径
  2. 1371. Find the Longest Substring Containing Vowels in Even Counts
  3. 面试造飞机,工作拧螺丝。
  4. JavaScript(一)js简单介绍
  5. WF4.0 基础篇 (二十五)(补充) ActivityFunc 与 InvokeFunc
  6. mysql水平分表实践记录_MYSQL 分表实践
  7. 我的世界1.12.2java下载_我的世界1.12.2电脑版下载
  8. 解析:深度学习框架Caffe源码
  9. 怎么用计算机控制打印机扫描,打印机怎么设置扫描到电脑 打印机设置扫描的步骤方法...
  10. base64编码和解码算法
  11. 计算机键盘上的2个定位键,电脑键盘上Tab 键的神奇之处!(用途详解)
  12. [转载]乔布斯十大经典语录
  13. html微信分享没有图片不显示,微信分享网页链接缩略图不显示解决方法
  14. dede标签帮助手册参考
  15. php ECShop form,在ecshop中添加页面并且实现后台管理
  16. oracle计算本月天数,oracle中计算某月的天数
  17. xeon e7系列服务器cpu,英特尔10核CPU降临,Xeon E7系列处理器正式发布
  18. Source Insight 4.0 序列号 license文件
  19. 红米note4出厂系统版本_红米Note4发布!出厂就有MIUI8黑科技
  20. Autosar E2E功能安全算法实现

热门文章

  1. C++ -Pointer指针总结(一)
  2. idea报错解决办法:Error executing Maven. The specified user settings file does not exist: C:\Users\Gmx\.m2\
  3. 最好的时光在路上,最美的风景在远方
  4. qq号被盗是什么原理_手机被盗之前(和之后)应该做什么
  5. 网络编程——CS模型(总结)
  6. 电子商务计算机和英语作文,电子商务的优缺点英语作文_电子商务英语作文
  7. 2011-6-14 - 晨间日志
  8. 详解Unity中的生命周期函数
  9. 日记:2019新年计划,每日计划的思维导图
  10. WIN10专业版无法隐藏任务栏图标