【opencv】教程代码 —videoio(2)将两个视频的每一帧逐一读取并计算其PSNR 和MSSIM...

本教程开始介绍的源代码将对每一帧执行PSNR测量,并且只对PSNR低于输入值的帧进行SSIM测量。为了可视化的目的,我们在OpenCV窗口中展示两幅图像,并将PSNR和MSSIM值打印到控制台。期望看到如下内容:

16ab19844294d9c88f0cbdb1598fc49e.png

video-input-psnr-ssim.cpp  将两个视频的每一帧逐一读取并计算其峰值信号噪声比(PSNR) 和 结构相似性指标(MSSIM)

4abe1f8f4cde8991df5f902cc8ecfb37.png

#include <iostream> // 标准输入输出流
#include <string>   // 字符串操作库
#include <iomanip>  // 输入输出流格式控制
#include <sstream>  // 字符串与数字转换#include <opencv2/core.hpp>     // OpenCV基础结构 (cv::Mat, Scalar)
#include <opencv2/imgproc.hpp>  // 高斯模糊处理
#include <opencv2/videoio.hpp>
#include <opencv2/highgui.hpp>  // OpenCV窗口输入输出using namespace std;
using namespace cv;double getPSNR(const Mat& I1, const Mat& I2); // 声明计算PSNR值的函数
Scalar getMSSIM(const Mat& I1, const Mat& I2); // 声明计算MSSIM值的函数static void help() // 帮助文本输出函数
{cout<< "------------------------------------------------------------------------------" << endl<< "This program shows how to read a video file with OpenCV. In addition, it "<< "tests the similarity of two input videos first with PSNR, and for the frames "<< "below a PSNR trigger value, also with MSSIM."                                   << endl<< "Usage:"                                                                         << endl<< "./video-input-psnr-ssim <referenceVideo> <useCaseTestVideo> <PSNR_Trigger_Value> <Wait_Between_Frames> " << endl<< "--------------------------------------------------------------------------"     << endl<< endl;
}int main(int argc, char *argv[]) // 主函数
{help(); // 显示帮助文本if (argc != 5) // 检查输入参数数量{cout << "Not enough parameters" << endl;return -1;}stringstream conv; // 创建字符串流const string sourceReference = argv[1], sourceCompareWith = argv[2]; // 引用视频和待比较视频路径int psnrTriggerValue, delay; // PSNR阈值和帧间延迟conv << argv[3] << endl << argv[4]; // 将参数放入字符串流conv >> psnrTriggerValue >> delay; // 从字符串流提取参数值int frameNum = -1; // 帧计数器VideoCapture captRefrnc(sourceReference), captUndTst(sourceCompareWith); // 创建视频捕捉对象if (!captRefrnc.isOpened()) // 检查引用视频文件是否成功打开{cout  << "Could not open reference " << sourceReference << endl;return -1;}if (!captUndTst.isOpened()) // 检查待比较视频文件是否成功打开{cout  << "Could not open case test " << sourceCompareWith << endl;return -1;}Size refS = Size((int) captRefrnc.get(CAP_PROP_FRAME_WIDTH),(int) captRefrnc.get(CAP_PROP_FRAME_HEIGHT)),uTSi = Size((int) captUndTst.get(CAP_PROP_FRAME_WIDTH),(int) captUndTst.get(CAP_PROP_FRAME_HEIGHT)); // 获取视频的尺寸if (refS != uTSi) // 检查两个视频的尺寸是否一致{cout << "Inputs have different size!!! Closing." << endl;return -1;}const char* WIN_UT = "Under Test"; // 待测视窗名称const char* WIN_RF = "Reference"; // 参考视窗名称// 创建窗口namedWindow(WIN_RF, WINDOW_AUTOSIZE);namedWindow(WIN_UT, WINDOW_AUTOSIZE);moveWindow(WIN_RF, 400, 0);         moveWindow(WIN_UT, refS.width, 0);         // 输出参考帧分辨率和视频帧数cout << "Reference frame resolution: Width=" << refS.width << "  Height=" << refS.height<< " of nr#: " << captRefrnc.get(CAP_PROP_FRAME_COUNT) << endl;// 输出PSNR阈值信息cout << "PSNR trigger value " << setiosflags(ios::fixed) << setprecision(3)<< psnrTriggerValue << endl;Mat frameReference, frameUnderTest; // 创建存储参考帧和待测帧的Mat对象double psnrV; // PSNR值Scalar mssimV; // MSSIM值for(;;) // 无限循环,用于显示视频帧并处理{captRefrnc >> frameReference; // 读取参考帧captUndTst >> frameUnderTest; // 读取待测帧if (frameReference.empty() || frameUnderTest.empty()) // 如果读取为空,则表明视频结束{cout << " < < <  Game over!  > > > ";break;}++frameNum; // 增加帧数cout << "Frame: " << frameNum << "# ";// 计算PSNR值psnrV = getPSNR(frameReference,frameUnderTest);cout << setiosflags(ios::fixed) << setprecision(3) << psnrV << "dB";// 如果PSNR值低于阈值,并且非零,则计算MSSIM值if (psnrV < psnrTriggerValue && psnrV){mssimV = getMSSIM(frameReference, frameUnderTest);// 输出MSSIM的RGB通道值cout << " MSSIM: "<< " R " << setiosflags(ios::fixed) << setprecision(2) << mssimV.val[2] * 100 << "%"<< " G " << setiosflags(ios::fixed) << setprecision(2) << mssimV.val[1] * 100 << "%"<< " B " << setiosflags(ios::fixed) << setprecision(2) << mssimV.val[0] * 100 << "%";}cout << endl;// 显示参考帧和待测帧imshow(WIN_RF, frameReference);imshow(WIN_UT, frameUnderTest);// 等待按键,如果按下ESC键,则退出循环char c = (char)waitKey(delay);if (c == 27) break;}return 0; // 返回0,表明程序正常退出
}// 计算PSNR值的函数
double getPSNR(const Mat& I1, const Mat& I2)
{Mat s1;absdiff(I1, I2, s1);       // 计算I1和I2的绝对差值 |I1 - I2|s1.convertTo(s1, CV_32F);  // 将结果转换为32位浮点数,因为不能在8位上进行平方运算s1 = s1.mul(s1);           // 计算差值的平方 |I1 - I2|^2Scalar s = sum(s1);        // 计算每个通道的元素和double sse = s.val[0] + s.val[1] + s.val[2]; // 将通道的和加起来if (sse <= 1e-10) // 如果值很小,则返回0return 0;else{double mse = sse / (double)(I1.channels() * I1.total()); // 计算均方误差MSEdouble psnr = 10.0 * log10((255 * 255) / mse); // 根据MSE计算PSNR值return psnr;}
}// 计算MSSIM值的函数
Scalar getMSSIM(const Mat& i1, const Mat& i2)
{const double C1 = 6.5025, C2 = 58.5225; // 定义常数C1和C2/***************************** 初始化 **********************************/int d = CV_32F;Mat I1, I2;i1.convertTo(I1, d);          // 将图像转换为32位浮点数进行计算i2.convertTo(I2, d);Mat I2_2 = I2.mul(I2);        // 计算I2的平方Mat I1_2 = I1.mul(I1);        // 计算I1的平方Mat I1_I2 = I1.mul(I2);       // 计算I1和I2的乘积/**************************** 结束初始化 *******************************/Mat mu1, mu2;                 // 预先计算GaussianBlur(I1, mu1, Size(11, 11), 1.5); // 计算均值mu1GaussianBlur(I2, mu2, Size(11, 11), 1.5); // 计算均值mu2Mat mu1_2 = mu1.mul(mu1);Mat mu2_2 = mu2.mul(mu2);Mat mu1_mu2 = mu1.mul(mu2);Mat sigma1_2, sigma2_2, sigma12;GaussianBlur(I1_2, sigma1_2, Size(11, 11), 1.5); // 计算标准差sigma1_2sigma1_2 -= mu1_2;GaussianBlur(I2_2, sigma2_2, Size(11, 11), 1.5); // 计算标准差sigma2_2sigma2_2 -= mu2_2;GaussianBlur(I1_I2, sigma12, Size(11, 11), 1.5); // 计算协方差sigma12sigma12 -= mu1_mu2;/ 计算公式 Mat t1, t2, t3;t1 = 2 * mu1_mu2 + C1;t2 = 2 * sigma12 + C2;t3 = t1.mul(t2);              // t3 = ((2*mu1_mu2 + C1).*(2*sigma12 + C2))t1 = mu1_2 + mu2_2 + C1;t2 = sigma1_2 + sigma2_2 + C2;t1 = t1.mul(t2);              // t1 =((mu1_2 + mu2_2 + C1).*(sigma1_2 + sigma2_2 + C2))Mat ssim_map;divide(t3, t1, ssim_map);     // ssim_map =  t3./t1;Scalar mssim = mean(ssim_map); // 计算ssim_map的平均值return mssim;
}

此代码是一个用于比较两个视频文件的相似性的C++程序,它使用OpenCV库来读取和处理视频帧。首先,程序通过计算峰值信噪比(PSNR)来比较每对视频帧。如果PSNR值低于某个阈值,程序额外使用结构相似性指数(MSSIM)进行比较。结果随着视频播放实时显示,并通过命令行参数控制一些基本设置,如PSNR阈值和帧间等待时间。程序还能够在窗口中实时显示参考视频和待测视频的帧。

6215dbd56266f022a934acb7c3ca7417.png

613bd52d8f773321c88cc73e38dfa2c1.png

4d6a88e6c5b6857d32a11394ad234794.png

 cout << setiosflags(ios::fixed) << setprecision(3) << psnrV << "dB";

15e4568dfa8e933d3152ad222fc2d10d.png

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/295123.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【“状态机” 解析UART不定长度的协议帧】

【“状态机” 解析UART不定长度的协议帧】 1. 数据帧格式2. 状态机原理3. 代码实现 通信设计中考虑协议的灵活性&#xff0c;经常把协议设计成“不定长度”。如果一个系统接收上述“不定长度”的协议帧&#xff0c;将会有一个挑战–如何高效接收与解析。一个实例如下图&#xf…

Linux (Ubuntu)- mysql8 部署

1.基本部署 01》》先查看OS类型&#xff0c;如果是Ubuntu在往下边看 rootspray:/etc/mysql/mysql.conf.d# lsb_release -a LSB Version: core-11.1.0ubuntu2-noarch:security-11.1.0ubuntu2-noarch Distributor ID: Ubuntu Description: Ubuntu 20.04.6 LTS Release: …

Spring AOP + 自定义注解 实现公共字段的填充

Spring AOP 自定义注解 实现公共字段的填充 代码冗,不利于后期维护. 定义操作这些字段的方法类型 实现步骤&#xff1a; 自定义注解AutoFill,用于表示操作这些公共字段的方法自定义切面类AutoFillAspect,统一拦截&#xff0c;通过反射获取方法入参&#xff0c;并填充公共字段…

springboot之MybatisPlus

文章目录 一、ORM二、mybatis实际操作三、mybatis-plus 一、ORM 简单来说ORM就是一个能够帮我们把java中Bean类映射到数据库中。 使用mybatis-plus。 配置架包 <!-- MyBatisPlus依赖 --><dependency><groupId>com.baomidou</groupId><art…

多态--下

文章目录 概念多态如何实现的指向谁调谁&#xff1f;例子分析 含有虚函数类的大小是多少&#xff1f;虚函数地址虚表地址多继承的子类的大小怎么计算&#xff1f;练习题虚函数和虚继承 概念 优先使用组合、而不是继承; 继承会破坏父类的封装、因为子类也可以调用到父类的函数;…

MyBatis-Plus04(条件构造器)

条件构造器和常用接口 wrapper介绍 Wrapper &#xff1a; 条件构造抽象类&#xff0c;最顶端父类 AbstractWrapper &#xff1a; 用于查询条件封装&#xff0c;生成 sql 的 where 条件 QueryWrapper &#xff1a; 查询条件封装 UpdateWrapper &#xff1a; Update 条件封装 A…

源支付V7开源版2.99,修复各种提示错误

源支付V7开源版2.99&#xff0c;修复各种提示错误 加密说明&#xff1a;200拿来的&#xff0c;只有8.1这个文件加密&#xff0c;其他文件无任何加密&#xff0c;已修复各种提示错误 测试其他开源版安装提示错误&#xff0c;有几个文件是加密的 注&#xff1a;开发不易&#…

【更新】上市公司-ZF环保补贴、补助数据(2008-2022年)

01、数据简介 环保补贴&#xff0c;又称绿色补贴&#xff0c;是ZF在环保领域实施的一种特定补贴。它主要针对那些在经济主体意识上存在偏差或由于资金私有制而无法有效进行环保投资的企业。环保补贴的目的是解决环保问题&#xff0c;帮助企业改进环保设备和工艺&#xff0c;以…

职场新军—网络安全,这个行业的实际情况你知道吗?

作为IT行业的香饽饽&#xff0c;网络安全工程师可谓是金字塔尖上的摇钱树。这专业近几年的薪资一直狂飙&#xff0c;简直就是职业版的“月薪过万”&#xff01;但别急着入坑&#xff0c;毕竟不是每个学了网络安全的都能在金钱雨中舞蹈&#xff0c;有时候还得小心不被淘汰。 听…

基本电路理论入门讲解系列-电路和电路模型

&#x1f308;个人主页&#xff1a;会编程的果子君 &#x1f4ab;个人格言:“成为自己未来的主人~” 电路 电路概念&#xff1a;把若干个电气设备和电气元件按照一定的方式组合起来&#xff0c;构成电流的通路&#xff0c;此路径的总体称为电路。在电子通信&#xff0c;自…

Oracle 中 where 和 on 的区别

1.Oracle 中 where 和 on 的区别 on&#xff1a;会先根据on后面的条件进行筛选&#xff0c;条件为真时返回该行&#xff0c;由于on的优先级高于left join&#xff0c;所以left join关键字会把左表中没有匹配的所有行也都返回&#xff0c;然后生成临时表返回,执行优先级高于…

遥感动态监测技术

很多人对动态监测和动态检测两个名词有疑惑。我们可以这样理解&#xff0c;动态监测是一个广义的名词&#xff0c;泛指数据预处理、变化信息发现与提取、变化信息挖掘与应用等&#xff0c;以对整个流程的叙述。动态检测是一个狭义的名词&#xff0c;主要指部分数据预处理、变化…

项目:USB键盘和鼠标的复合设备

我们的复合设备使用一个物理设备就可以完成多个功能。 使用复合设备同时完成USB键盘和鼠标功能&#xff0c;它的主要实现方式有两种&#xff0c; 第一个就是我们将多个设备描述符合并成一个&#xff0c;这个相对比较简单&#xff0c;我们只要根据相应的报告描述符处理数据就可…

vue3+vite 模板vue3-element-admin框架如何关闭当前页面跳转 tabs

使用模版: 有来开源组织 / vue3-element-admin 需要关闭的.vue 页面增加以下方法 //setup 里import {LocationQuery, useRoute, useRouter} from "vue-router"; const router useRouter(); function close() {console.log(|--router.currentRoute.value, router.cur…

C++入门:命名空间namespace,cin,cout,缺省参数,函数的重载

namespace本质上是定义了一个命名空间域 通过创建命名空间域可以预防变量的冲突问题 命名冲突时,编译器会首先从局部中找,然后从全局中找,但是不会从命名空间中找 eg. ::符号和命名空间 :: 是域作用限定符 就可以访问namespace bit中的rand了,否则就默认找局部或全局的ran…

2024年全新靠谱的FTP替代升级解决方案

随着企业规模的扩大和业务的多元化&#xff0c;传统的TCP协议在数据传输效率上逐渐显现出局限性。TCP协议虽然以其稳定性和可靠性被广泛应用&#xff0c;但在面对大规模数据传输时&#xff0c;其性能瓶颈逐渐成为企业发展的阻碍。同时&#xff0c;基于TCP的应用协议如Telnet、F…

如何设计一个通用的 Excel 导入导出功能?

以JSON配置的方式去实现通用性和动态调整&#xff0c;当然&#xff0c;这个通用仍然存在一定的局限性&#xff0c;每个项目的代码风格都不同。 想要写出一个适合所有项目的通用性模块并不容易&#xff0c;这里的通用局限于其所在项目&#xff0c;所以该功能代码如果不适用于自…

【ReadPapers】A Survey of Large Language Models

LLM-Survey的llm能力和评估部分内容学习笔记——思维导图 思维导图 参考资料 A Survey of Large Language Models论文的github仓库

深度学习(四)笔记1

0.前提 往后我会以我的笔记形式来发布我的文章&#xff08;每3次笔记为一篇文章&#xff09;&#xff0c;有爱的人可以自取学习&#xff0c;当然如果可以的话我会把我的文章翻出来变成文章。 1.数据操作 本期4.1数据操作的链接在这。 链接&#xff1a;https://pan.baidu.com/s…

Discuz! X3.5苗木_苗木网_苗木价格_苗木求购信息_苗木批发网模板utf-8

适合做苗木行业平台苗木网站、苗木信息网,提供苗木报价、各地苗木求购信息、绿化苗木采购招标、苗木基地展示、苗木百科知识、花木交易及苗木资讯、各地苗木信息网络行情。解压上传到template目录下&#xff0c;后台安装即可&#xff0c;包含PC手机端模板 下载地址&#xff1a;…