【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.hqwc.cn/news/587630.html

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

相关文章

Matlab|基于关键场景辨别算法的两阶段鲁棒微网优化调度

目录 主要内容 部分代码 结果一览 下载链接 主要内容 该模型主要求解的是微网两阶段鲁棒优化调度问题&#xff0c;与目前大部分用CCG算法不同&#xff0c;模型创新性的采用关键场景辨别法&#xff0c;通过少量的迭代辨别出最恶劣的场景&#xff0c;针对光伏出力的…

Flutter 开发学习笔记(3):第三方UI库的引入

文章目录 前言初始化程序Icon导入如何导入 Toast消息提示框引入简单封装简单使用 Charts图表导入新建pages文件夹存放page简单代码实现效果 总结 前言 Flutter已经发布了有10年了&#xff0c;生态也算比较完善了。用于安卓程序开发应该是非常的方便。我们这里就接入一些简单的…

3D怎么看模型内部结构---模大狮模型网

在3D建模和设计过程中&#xff0c;了解模型的内部结构是十分重要的。这不仅有助于审美和设计&#xff0c;还能够帮助我们更好地理解模型的构造和特性。模大狮将介绍一些方法和技巧&#xff0c;帮助您探索3D模型的内部结构。 一、使用切片工具 切片模型&#xff1a;通过切片工具…

Polardb MySQL 产品架构及特性

一、产品概述; 1、产品族 参考&#xff1a;https://edu.aliyun.com/course/3121700/lesson/341900000?spma2cwt.28120015.3121700.6.166d71c1wwp2px 2、polardb mysql架构优势 1&#xff09;大容量高弹性&#xff1a;最大支持存储100T&#xff0c;最高超1000核CPU&#xff0…

ensp华为AC+AP上线配置

AR1配置&#xff1a; <Huawei>system-view # 进入系统视图<Huawei>sysname R1 # 设备重命名[R1]dhcp enable # 开启DHCP功能[R1]interface GigabitEthernet0/0/0 # 进入接口 [R1-GigabitEthernet0/0/0]ip address 192.168.0.1 23 # 配置接口地址 [R1-GigabitE…

BGP-安全特性、扩展特性、增强特性

BGP-安全特性&#xff0c;扩展特性 BGP路由反射器和联盟的比较 反射器 联盟 不需要更改现有的网络拓扑&#xff0c;兼容性号 需要修改逻辑拓扑 配置方便&#xff0c;客户机不知道自己是客户机 所有设备需要重新进行配置&#xff0c;且所有设备必须支持联盟功能 集群与集群…

HBase(超级无敌详细PROMAX讲解版)

简介 概述 图-1 HBase图标 HBase原本是由Yahoo!公司开发的后来贡献给了Apache的一套开源的、基于Hadoop的、分布式的、可扩展的非关系型数据库(Non-Relational Database)&#xff0c;因此HBase不支持SQL(非关系型数据库基本上都不支持SQL)&#xff0c;而是提供了一套单独的命…

深入理解数据结构第二弹——二叉树(2)——堆排序及其时间复杂度

看这篇前请先把我上一篇了解一下&#xff1a;深入理解数据结构第一弹——二叉树&#xff08;1&#xff09;——堆-CSDN博客 前言&#xff1a; 相信很多学习数据结构的人&#xff0c;都会遇到一种情况&#xff0c;就是明明最一开始学习就学习了时间复杂度&#xff0c;但是在后期…

数据仓库实践

什么是数据仓库&#xff1f; 数据仓库是一个用于存储大量数据并支持数据分析与报告的系统。它通常用于集成来自不同来源的数据&#xff0c;提供一个统一的视图&#xff0c;以便进行更深入的分析和决策。 数据仓库的主要优势&#xff1f; 决策支持&#xff1a;为企业决策提供可靠…

MegaSeg Pro for Mac v6.3.1 注册激活版 音视频DJ混音工具

MegaSeg Pro for Mac是一款专业的DJ和广播自动化软件&#xff0c;旨在为音乐专业人士提供强大的音乐播放和演播功能。这款软件具有多种功能&#xff0c;包括强大的音乐库管理&#xff0c;支持导入和组织大量音乐文件&#xff0c;可以轻松管理你的音乐收藏。它支持广泛的音频格式…

Java设计之道:色即是空,空即是色

0.引子 我们的这个世界上&#xff0c;存在这么一种东西&#xff1a; 第一&#xff1a;它不占据任何3D之体积&#xff0c;即它没有Volume第二&#xff1a;它也不占据任何2D之面积&#xff0c;即它没有Area第三&#xff1a;它也不占据任何1D之长度&#xff0c;即它没有Length 总…

华为审核被拒提示: 您的应用存在(最近任务列表隐藏风险活动)的行为,不符合华为应用市场审核标准

应用审核意见&#xff1a; 您的应用存在&#xff08;最近任务列表隐藏风险活动&#xff09;的行为&#xff0c;不符合华为应用市场审核标准。 修改建议&#xff1a;请参考测试结果进行修改。 请参考《审核指南》第2.19相关审核要求&#xff1a;https://developer.huawei.com/c…