当前位置: 首页 > news >正文

OpenCV 库来捕获和处理视频输入和相似度测量(73)

 返回:OpenCV系列文章目录(持续更新中......)
上一篇:OpenCV的周期性噪声去除滤波器(70)
下一篇 :使用 OpenCV 创建视频(74)

目标

如今,拥有数字视频录制系统供您使用是很常见的。因此,您最终会遇到不再处理一批图像,而是处理视频流的情况。这些可能有两种类型:实时图像馈送(在网络摄像头的情况下)或预先录制的硬盘驱动器存储文件。幸运的是,OpenCV以相同的方式处理这两者,使用相同的C++类。因此,以下是您将在本教程中学到的内容:

  • 如何打开和阅读视频流
  • 检查图像相似度的两种方法:PSNR 和 SSIM

C++源代码


作为使用 OpenCV 展示这些内容的测试用例,我创建了一个小程序,可以读取两个视频文件并在它们之间执行相似性检查。您可以使用它来检查新的视频压缩算法的工作情况。让我们有一个参考(原始)视频,比如这个小的 Megamind 剪辑和它的压缩版本。您还可以在 OpenCV 源库的文件夹samples/data中找到源代码和这些视频文件。

#include <iostream> // for standard I/O
#include <string> // for strings
#include <iomanip> // for controlling float print precision
#include <sstream> // string to number conversion#include <opencv2/core.hpp> // Basic OpenCV structures (cv::Mat, Scalar)
#include <opencv2/imgproc.hpp> // Gaussian Blur
#include <opencv2/videoio.hpp>
#include <opencv2/highgui.hpp> // OpenCV window I/Ousing namespace std;
using namespace cv;double getPSNR ( const Mat& I1, const Mat& I2);
Scalar getMSSIM( const Mat& I1, const Mat& I2);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;conv << argv[3] << endl << argv[4]; // put in the stringsconv >> psnrTriggerValue >> delay; // take out the numbersint frameNum = -1; // Frame counterVideoCapture 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";// WindowsnamedWindow(WIN_RF, WINDOW_AUTOSIZE);namedWindow(WIN_UT, WINDOW_AUTOSIZE);moveWindow(WIN_RF, 400 , 0); //750, 2 (bernat =0)moveWindow(WIN_UT, refS.width, 0); //1500, 2cout << "Reference frame resolution: Width=" << refS.width << " Height=" << refS.height<< " of nr#: " << captRefrnc.get(CAP_PROP_FRAME_COUNT) << endl;cout << "PSNR trigger value " << setiosflags(ios::fixed) << setprecision(3)<< psnrTriggerValue << endl;Mat frameReference, frameUnderTest;double psnrV;Scalar mssimV;for(;;) //Show the image captured in the window and repeat{captRefrnc >> frameReference;captUndTst >> frameUnderTest;if (frameReference.empty() || frameUnderTest.empty()){cout << " < < < Game over! > > > ";break;}++frameNum;cout << "Frame: " << frameNum << "# ";psnrV = getPSNR(frameReference,frameUnderTest);cout << setiosflags(ios::fixed) << setprecision(3) << psnrV << "dB";if (psnrV < psnrTriggerValue && psnrV){mssimV = getMSSIM(frameReference, frameUnderTest);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);char c = (char)waitKey(delay);if (c == 27) break;}return 0;
}// ![get-psnr]
double getPSNR(const Mat& I1, const Mat& I2)
{Mat s1;absdiff(I1, I2, s1); // |I1 - I2|s1.convertTo(s1, CV_32F); // cannot make a square on 8 bitss1 = s1.mul(s1); // |I1 - I2|^2Scalar s = sum(s1); // sum elements per channeldouble sse = s.val[0] + s.val[1] + s.val[2]; // sum channelsif( sse <= 1e-10) // for small values return zeroreturn 0;else{double mse = sse / (double)(I1.channels() * I1.total());double psnr = 10.0 * log10((255 * 255) / mse);return psnr;}
}
// ![get-psnr]// ![get-mssim]Scalar getMSSIM( const Mat& i1, const Mat& i2)
{const double C1 = 6.5025, C2 = 58.5225;/***************************** INITS **********************************/int d = CV_32F;Mat I1, I2;i1.convertTo(I1, d); // cannot calculate on one byte large valuesi2.convertTo(I2, d);Mat I2_2 = I2.mul(I2); // I2^2Mat I1_2 = I1.mul(I1); // I1^2Mat I1_I2 = I1.mul(I2); // I1 * I2/*************************** END INITS **********************************/Mat mu1, mu2; // PRELIMINARY COMPUTINGGaussianBlur(I1, mu1, Size(11, 11), 1.5);GaussianBlur(I2, mu2, Size(11, 11), 1.5);Mat 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_2 -= mu1_2;GaussianBlur(I2_2, sigma2_2, Size(11, 11), 1.5);sigma2_2 -= mu2_2;GaussianBlur(I1_I2, sigma12, Size(11, 11), 1.5);sigma12 -= 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); // mssim = average of ssim mapreturn mssim;
}
// ![get-mssim]

如何读取视频流(在线摄像机或离线文件)?

从本质上讲,视频操作所需的所有功能都集成在 cv::VideoCapture C++ 类中。这本身是建立在 FFmpeg 开源库之上的。这是 OpenCV 的基本依赖项,因此您无需担心这一点。视频由一系列图像组成,我们在文献中将这些图像称为帧。对于视频文件,有一个帧速率指定两帧之间的长度。虽然对于摄像机来说,它们通常每秒可以数字化多少帧是有限制的,但这个属性并不那么重要,因为摄像机在任何时候都能看到世界的当前快照。

您需要执行的第一个任务是将其源代码分配给 cv::VideoCapture 类。您可以通过 cv::VideoCapture::VideoCapture 或其 cv::VideoCapture::open 函数执行此操作。如果此参数为整数,则将类绑定到相机、设备。此处传递的数字是设备的 ID,由操作系统分配。如果您的系统连接了单个摄像头,则其 ID 可能为零,并且从那里开始进一步增加。如果传递给这些参数的参数是字符串,它将引用视频文件,并且字符串指向文件的位置和名称。例如,对于上面的源代码,有效的命令行是:

video/Megamind.avi video/Megamind_bug.avi 35 10

我们进行相似性检查。这需要参考和测试用例视频文件。前两个参数指的是这一点。这里我们使用一个相对地址。这意味着应用程序将查看其当前工作目录并打开视频文件夹,并尝试在其中查找Megamind.aviMegamind_bug.avi

const string sourceReference = argv[1],sourceCompareWith = argv[2];VideoCapture captRefrnc(sourceReference);
// or
VideoCapture captUndTst;
captUndTst.open(sourceCompareWith);

若要检查类与视频源的绑定是否成功,请使用 cv::VideoCapture::isOpened 函数:

if ( !captRefrnc.isOpened()){cout << "Could not open reference " << sourceReference << endl;return -1;}

调用对象析构函数时,自动关闭视频。但是,如果要在此之前关闭它,则需要调用其 cv::VideoCapture::release 函数。视频的帧只是简单的图像。因此,我们只需要从 cv::VideoCapture 对象中提取它们并将它们放入 Mat 对象中。视频流是连续的。您可以通过 cv::VideoCapture::read 或重载的 >> 运算符一个接一个地获取帧:

Mat frameReference, frameUnderTest;
captRefrnc >> frameReference;
captUndTst.read(frameUnderTest);

如果无法获取任何帧(导致视频流关闭或视频文件末尾),则上面的读取操作将空 Mat 对象。如果出现以下情况,我们可以通过一个简单的方法来检查这一点:

if( frameReference.empty() || frameUnderTest.empty())
{// exit the program
}

读取方法由帧抓取和应用的解码组成。可以使用 cv::VideoCapture::grab 和 cv::VideoCapture::retrieve 函数显式调用这两个函数。

除了帧的内容之外,视频还附加了许多信息。这些通常是数字,但在某些情况下,它可能是短字符序列(4 个字节或更少)。因此,为了获取这些信息,有一个名为 cv::VideoCapture::get 的通用函数返回包含这些属性的双精度值。使用按位运算对有效值仅为整数的双精度类型和转换中的字符进行解码。它的单个参数是查询属性的 ID。例如,这里我们得到参考和测试用例视频文件中的帧大小;加上参照内部的帧数。

Size refS = Size((int) captRefrnc.get(CAP_PROP_FRAME_WIDTH),(int) captRefrnc.get(CAP_PROP_FRAME_HEIGHT)),cout << "Reference frame resolution: Width=" << refS.width << " Height=" << refS.height<< " of nr#: " << captRefrnc.get(CAP_PROP_FRAME_COUNT) << endl;

在处理视频时,您可能经常希望自己控制这些值。为此,有一个 cv::VideoCapture::set 函数。它的第一个参数仍然是要更改的属性的名称,第二个参数是包含要设置的值的 double 类型。如果成功,它将返回 true,否则返回 false。很好的例子是在视频文件中寻找给定的时间或帧:

captRefrnc.set(CAP_PROP_POS_MSEC, 1.2); // go to the 1.2 second in the video
captRefrnc.set(CAP_PROP_POS_FRAMES, 10); // go to the 10th frame of the video
// now a read operation would read the frame at the set position

对于可以读取和更改的属性,请查看 cv::VideoCapture::get 和 cv::VideoCapture::set 函数的文档。

图像相似度 - PSNR 和 SSIM

我们想检查我们的视频转换操作有多难以察觉,因此我们需要一个系统来逐帧检查相似性或差异性。最常用的算法是PSNR(又名峰值信噪比)。最简单的定义是从均方误差开始的。假设有两个图像:I1 和 I2;具有二维大小的 i 和 j,由 c 个通道组成。

然后 PSNR 表示为:

这里的 (MAX_I)是像素的最大有效值。对于简单的单字节图像,每个通道每像素,这是 255。当两个图像相同时,MSE 将给出零,从而导致 PSNR 公式中的除以零运算无效。在这种情况下,PSNR 是未定义的,因此我们需要单独处理这种情况。之所以过渡到对数刻度,是因为像素值具有非常宽的动态范围。所有这些都转换为 OpenCV,函数如下所示:

double getPSNR(const Mat& I1, const Mat& I2)
{Mat s1;absdiff(I1, I2, s1); // |I1 - I2|s1.convertTo(s1, CV_32F); // cannot make a square on 8 bitss1 = s1.mul(s1); // |I1 - I2|^2Scalar s = sum(s1); // sum elements per channeldouble sse = s.val[0] + s.val[1] + s.val[2]; // sum channelsif( sse <= 1e-10) // for small values return zeroreturn 0;else{double mse = sse / (double)(I1.channels() * I1.total());double psnr = 10.0 * log10((255 * 255) / mse);return psnr;}
}

通常,视频压缩的结果值介于 30 到 50 之间,越高越好。如果图像明显不同,您将得到更低的图像,例如 15 左右。这种相似性检查计算起来既简单又快捷,但在实践中,它可能与人眼感知有些不一致。结构相似性算法旨在纠正这一点。

描述这些方法远远超出了本教程的目的。为此,我邀请您阅读介绍它的文章。尽管如此,您可以通过查看下面的 OpenCV 实现来获得它的良好图像。

注意

SSIM在以下文章中进行了更深入的描述:“Z. Wang, A. C. Bovik, H. R. Sheikh and E. P. Simoncelli,“图像质量评估:从错误可见性到结构相似性”,IEEE Transactions on Image Processing,第 13 卷,第 4 期,第 600-612 页,2004 年 4 月。

Scalar getMSSIM( const Mat& i1, const Mat& i2)
{const double C1 = 6.5025, C2 = 58.5225;/***************************** INITS **********************************/int d = CV_32F;Mat I1, I2;i1.convertTo(I1, d); // cannot calculate on one byte large valuesi2.convertTo(I2, d);Mat I2_2 = I2.mul(I2); // I2^2Mat I1_2 = I1.mul(I1); // I1^2Mat I1_I2 = I1.mul(I2); // I1 * I2/*************************** END INITS **********************************/Mat mu1, mu2; // PRELIMINARY COMPUTINGGaussianBlur(I1, mu1, Size(11, 11), 1.5);GaussianBlur(I2, mu2, Size(11, 11), 1.5);Mat 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_2 -= mu1_2;GaussianBlur(I2_2, sigma2_2, Size(11, 11), 1.5);sigma2_2 -= mu2_2;GaussianBlur(I1_I2, sigma12, Size(11, 11), 1.5);sigma12 -= 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); // mssim = average of ssim mapreturn mssim;
}

这将返回图像每个通道的相似性索引。此值介于 0 和 1 之间,其中 1 对应于完全拟合。不幸的是,许多高斯模糊的成本非常高,因此虽然 PSNR 可以在实时环境中工作(每秒 24 帧),但这比实现类似的性能结果要多得多。

因此,本教程开头提供的源代码将对每个帧执行 PSNR 测量,并且仅对 PSNR 低于输入值的帧执行 SSIM。出于可视化目的,我们在 OpenCV 窗口中显示两个图像,并将 PSNR 和 MSSIM 值打印到控制台。期待看到类似的东西:

您可以在 YouTube 上观察此操作时实例。

相关文章:

OpenCV 库来捕获和处理视频输入和相似度测量(73)

返回:OpenCV系列文章目录&#xff08;持续更新中......&#xff09; 上一篇:OpenCV的周期性噪声去除滤波器(70) 下一篇 :使用 OpenCV 创建视频(74) ​ 目标 如今&#xff0c;拥有数字视频录制系统供您使用是很常见的。因此&#xff0c;您最终会遇到不再处理一批图像&#xf…...

了解TMS运输管理系统,实现物流高效运转

TMS运输管理系统&#xff08;Transportation Management System&#xff09;是一种集成物流和信息技术的解决方案&#xff0c;通过优化运输流程、实时跟踪货物信息和自动化管理操作&#xff0c;提高物流效率&#xff0c;降低运营成本&#xff0c;实现高效运输。 TMS运输管理系…...

数据库原理与应用实验三 嵌套查询

实验目的和要求 加深和掌握对嵌套查询的理解和应用 实验环境 Windows10 SQLServer 实验内容与过程 图书&#xff08;书号&#xff0c;书名&#xff0c;价格&#xff0c;出版社&#xff09; 读者&#xff08;卡号&#xff0c;姓名&#xff0c;年龄&#xff0c;所属单位&a…...

LeetCode 110.平衡二叉树(Java/C/Python3/Go实现含注释说明,Easy)

标签 树深度优先搜索递归 题目描述 给定一个二叉树&#xff0c;判断它是否是高度平衡的二叉树。 本题中&#xff0c;一棵高度平衡的二叉树定义为&#xff1a; 一个二叉树每个节点的左右两个子树的高度差的绝对值不超过1。 原题&#xff1a;LeetCode 110.平衡二叉树 思路及…...

【SQL】ACID事务与隔离级别

数据库事务 数据库事务具有ACID这4个特性&#xff1a; A&#xff1a;Atomicity&#xff0c;原子性&#xff0c;将所有SQL作为原子工作单元执行&#xff0c;要么全部执行&#xff0c;要么全部不执行&#xff1b;C&#xff1a;Consistency&#xff0c;一致性&#xff0c;事务完…...

深度神经网络中的不确定性研究综述

A.单一确定性方法 对于确定性神经网络&#xff0c;参数是确定的&#xff0c;每次向前传递的重复都会产生相同的结果。对于不确定性量化的单一确定性网络方法&#xff0c;我们总结了在确定性网络中基于单一正向传递计算预测y *的不确定性的所有方法。在文献中&#xff0c;可以找…...

实用的Chrome浏览器命令

Google Chrome 是一款广泛使用的网络浏览器&#xff0c;它提供了许多实用的快捷键和命令&#xff0c;可以帮助用户更高效地浏览网页。以下是一些常用的 Chrome 浏览器命令&#xff1a; 1. 新标签页: Ctrl T (Windows/Linux) 或 Command T (Mac) 2. 关闭当前标签: Ctrl W 或…...

无人作业控制器--4G/5G通信

一、环境 开发环境&#xff1a;ubuntu 22 ros2 humble 发布运行环境&#xff1a;地平线旭日x3派、arm64 4G 模组&#xff1a; 移远EC20模块 5G 模组&#xff1a;移远RG200U-CN 网络通信模组根据需要选择其中一款&#xff0c; 前期我们使用4G模组&#xff0c;后续迭代因为…...

动态规划-两个数组的dp问题2

文章目录 1. 不同的子序列&#xff08;115&#xff09;2. 通配符匹配&#xff08;44&#xff09; 1. 不同的子序列&#xff08;115&#xff09; 题目描述&#xff1a; 状态表示&#xff1a; 根据题意这里的dp数组可以定义为二维&#xff0c;并且dp[i][j]表示字符串t的0到i的…...

如何设置并行度 ——《OceanBase 并行执行》系列 2

并行度&#xff08;degree of parallelism&#xff0c;简称 DOP&#xff09;&#xff0c;是指在执行过程中所使用的工作线程数量。设计并行执行的初衷在于充分利用多核资源以提升效率。OceanBase 的并行执行框架支持多种设定并行度的方式&#xff0c;既允许用户手动设置&#x…...

python直接发布到网站wordpress之三批量发布图片

在前面的文章中&#xff0c;实现了使用python操作wordpress发布文字内容和图片内容。 python直接发布到网站wordpress之一只发布文字-CSDN博客 python直接发布到网站wordpress之二发布图片-CSDN博客 不过&#xff0c;此时发布图片的数量只能是一张图片。但在实际应用中&…...

C#面:ADO.NET 相对于ADO等主要有什么改进

C# ADO.NET 是微软为.NET平台开发的一套数据访问技术&#xff0c;相对于传统的ADO&#xff08;ActiveX Data Objects&#xff09;等&#xff0c;它有以下几个主要改进&#xff1a; 面向对象&#xff1a;ADO.NET 是面向对象的数据访问技术&#xff0c;它使用.NET框架中的类和对…...

web前端学习笔记7-iconfont使用

7. iconfont的使用流程 字体图标使用较多的是阿里巴巴iconfont图标库,它是阿里巴巴体验团队推出的图标库和图标管理平台,提供了大量免费和可定制的矢量图标,以满足网页设计、平面设计、UI设计、应用程序开发和其他创意项目的需求。 官方网站:https://www.iconfont.cn/ 使用…...

国内小白用什么方法充值使用ChatGPT4.0?

首先说一下IOS礼品卡订阅&#xff0c;目前最经济实惠的订阅方式&#xff0c;具体操作步骤 使用IOS设备充值&#xff0c;用 App Stroe 兑换券 1、支付宝地址切换旧金山&#xff0c;在里面买app store 的兑换卷 2、美区Apple ID登陆app store &#xff0c;充值兑换券 3、IOS设…...

富格林:正确杜绝欺诈实现出金

富格林悉知&#xff0c;现货黄金一直以来都是投资者们追逐的热门品种之一。其安全性和避险特性吸引着广大投资者。但在现货黄金市场中要想实现出金其实并不简单&#xff0c;是需要我们通过一定的技巧和方法去正确杜绝欺诈套路。下面为了帮助广大投资者正确杜绝欺诈实现出金&…...

基于java,SpringBoot和VUE的求职招聘简历管理系统设计

摘要 基于Java, Spring Boot和Vue的求职招聘管理系统是一个为了简化求职者与雇主间互动流程而设计的现代化在线平台。该系统后端采用Spring Boot框架&#xff0c;以便快速搭建具有自动配置、安全性和事务管理等特性的RESTful API服务&#xff0c;而前端则使用Vue.js框架构建动…...

sqlserver数据库日志文件log.ldf文件占用过大清除的办法

sqlserver数据库日志文件log.ldf文件占用过大清除的办法 技术交流 http://idea.coderyj.com/ 1.清除数据库日志的方法 --- 查看数据库日志文件名 USE cs GO SELECT file_id, name,size,* FROM sys.database_files;ps 可以看到其中name字段为数据库日志名称"数据库日志名称…...

【Python小技巧】matplotlib不显示图像竟是numpy惹的祸

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、问题&#xff1a;df.plot() 显示不出图像二、尝试各种解决办法1. 增加matplotlib.use&#xff0c;设定GUI2. 升级matplotlib版本 三、numpy是个重要的库1. …...

【AIGC】1、爆火的 AIGC 到底是什么 | 全面介绍

文章目录 一、AIGC 的简要介绍二、AIGC 的发展历程三、AIGC 的基石3.1 基本模型3.2 基于人类反馈的强化学习3.3 算力支持 四、生成式 AI&#xff08;Generative AI&#xff09;4.1 单模态4.1.1 生成式语言模型&#xff08;Generative Language Models&#xff0c;GLM&#xff0…...

云计算技术概述_3.云计算的部署方式

根据NIST的定义&#xff0c;云计算从部署模式上看可以分为公有云、社区云、私有云和混合云四种类型。 注&#xff1a;NIST&#xff08;美国国家标准与技术研究院&#xff09;是美国商务部下属的一个物理科学实验室和非监管机构。 其任务是促进创新和行业竞争力。 NIST 将其活动…...

简述 BIO 、NIO 模型

BIO : 同步阻塞I/O&#xff08;Block IO&#xff09; 服务器实现模式为每一个连接一个线程&#xff0c;即客户端有连接请求时服务器就需要启动一个线程进行处理&#xff0c;如果这个连接不做任何事情会造成不必要的线程开销&#xff0c;此处可以通过线程池机制进行优化。 impo…...

【Python小练】随机验证码

题目 提示输出含数字、字母的四位随机数&#xff0c;输入提示的验证码进行验证&#xff0c;验证码正确结束程序&#xff0c;验证码错误继续输入。 分析 我们可以通过random模块生成0到9的随机数&#xff0c;也可以通过生成65到90的随机数&#xff0c;将65到90的随机ASCLL码转换…...

《1w实盘and大盘基金预测 day30》

今日预测&#xff1a; 3123-3150-3177 探底回升&#xff0c;震荡上涨&#xff0c;收小红小绿 双创指数后期上涨的幅度也是会大于上证的&#xff0c;四月底的时候就提醒建仓。 关注板块&#xff1a;医疗、地产、电力、证券 这周预测 这周上证指数最高看到3200 继续看涨&#…...

软件工程案例学习-图书管理系统-面向对象方法

文档编号&#xff1a;LMS_1 版 本 号&#xff1a;V1.0 ** ** ** ** ** ** 文档名称&#xff1a;需求分析规格说明书 项目名称&#xff1a;图书管理系统 项目负责人&#xff1a;计敏 胡杰 ** ** …...

python:机器学习特征优选(过滤法)

作者:CSDN @ _养乐多_ 本文将介绍如何使用 python 语言使用过滤法进行机器学习特征优选。分别有F值、互信息(Mutual Information,MI)、方差阈值(Variance Threshold,VT)、相关性方法。 文章目录 一、特征数据1.1 将用于分析的数据从GEE下载到本地1.2 从其他方法获取二、…...

CH32V 系列 MCU IAP 使用函数形式通过传参形式灵活指定APP跳转地址

参考: CH32V 系列 MCU IAP 升级跳转方法 CH32V103 的 IAP 问题&#xff08;跳转及中断向量表重定位&#xff09; 1. 沁恒的RISC-V内核MCU的IAP跳转示例程序简要分析 沁恒的RISC-V内核的MCU比如CH32V203、CH32V307等系列的EVT包中IAP升级的示例程序中都是通过使能软件中断之后&…...

教程分享:如何为跨境电商、外贸、国际展会制作二维码?

不论是做跨境电商、在全球做产品推广&#xff0c;还是国外的餐厅运营、参加国际展会&#xff0c;或者是做创意户外广告、制作个性化的个人名片、有趣的产品包装……只要是在国外使用二维码&#xff0c;你都可以在QR Tiger去制作您需要的二维码&#xff01; 一、认识QR Tiger 二…...

ComfyUI 基础教程(十三):ComfyUI-Impact-Pack 面部修复

SD的WebUI 中的面部修复神器 ADetailer,无法在ComfyUI 中使用。那么如何在ComfyUI中进行面部处理呢?ComfyUI 中也有几个面部修复功能,比如ComfyUI Impact Pack(FaceDetailer),以及换脸插件Reactor和IPAdapter。 ComfyUI-Impact-Pack 是一个功能强大的插件,专为 ComfyUI …...

专题五_位运算(2)

目录 面试题 01.01. 判定字符是否唯一 解析 题解 268. 丢失的数字 解析 题解 371. 两整数之和 解析 题解 面试题 01.01. 判定字符是否唯一 面试题 01.01. 判定字符是否唯一 - 力扣&#xff08;LeetCode&#xff09; 解析 题解 class Solution { public:bool isUnique…...

ZCC5503 18V 1A 6uA低静态功耗 同步降压控制器

1. 概要 ZCC5503R 是一款基准电压源、振荡电路、 比较器 PWM/PFM 控制器构成的 CMOS 降压电路调整器&#xff0c;利用 PWM/PFM 自动切换控制电路达到可调占空比&#xff0c;具有全输入电压范围&#xff08;3~18V &#xff09;内的低纹波、高效率及大电流输出等特点. 2. 产…...

知名网站建设联系电话/百度推广客户端怎么登陆

IS NULL: 当列的值是 NULL,此运算符返回 true。 IS NOT NULL: 当列的值不为 NULL, 运算符返回 true。 <>: 比较操作符&#xff08;不同于 运算符&#xff09;&#xff0c;当比较的的两个值相等或者都为 NULL 时返回 true。 关于 NULL 的条件比较运算是比较特殊的。你…...

publiccms网站模板/刷关键词的平台

——在做测试的过程中&#xff0c;遇到一些问题都会去进行抓包&#xff0c;抓包可以帮助我们解决很多问题&#xff0c;抓包工具有很多比如fiddler&#xff0c;浏览器调试工具&#xff08;F12&#xff09;&#xff0c;charles等&#xff0c;抓包工具是我们测试人员必不可少的一项…...

做360效果图网站/企业网站策划

在Spring Cloud Zuul组件中&#xff0c;一共有四种类型的过滤器&#xff1a;Pre前置过滤器、Post后置过滤器、Route路由过滤器、Error错误过滤器。通过自定义前置过滤器、后置过滤器&#xff0c;可以实现对请求的Request处理和Response处理&#xff0c;比如在前置过滤器中实现用…...

c2c代表网站是什么/在线代理浏览国外网站

1.盒子模型 对盒子模型的理解标准盒子模型和怪异盒子模型的区别和使用场景2.position position的属性有哪些releative&#xff0c;absolute, fixed三者的区别以及使用场景&#xff08;重点在releative和absolute是如何配合使用的&#xff0c;使用时候的注意点在哪里&#xff09…...

高考写作网站/关键词自动优化

先做个标题党 回头有时间更新&#xff0c;放一张图...

不用编程做APP和响应式网站/站长网站查询

Java原生API操作ZooKeeper可参看&#xff1a; Java原生API操作Zookeeper&#xff08;一&#xff09; Java原生API操作Zookeeper&#xff08;二&#xff09; 相关内容&#xff1a; 基于Curator操作ZooKeeper&#xff08;二&#xff09;-Watcher操作 基于Curator操作ZooKeep…...