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

OPENCV C++(十一)

鼠标响应函数


//鼠标响应函数
void on_mouse(int EVENT, int x, int y, int flags, void* userdata)
{Mat hh;hh = *(Mat*)userdata;switch (EVENT){case EVENT_LBUTTONDOWN:{vP.x = x;vP.y = y;drawMarker(hh, vP, Scalar(255, 255, 255));//circle(hh, vP, 4, cvScalar(255, 255, 255), -1);imshow(wName, hh);return;}break;}}

 drawMarker(hh, vP, Scalar(255, 255, 255));

这个是画一个十字符号 标记一个点

绘制直方图和以前篇幅一样

//绘制直方图
int drawHist(cv::Mat& histMat, float* srcHist, int bin_width, int bin_heght)
{histMat.create(bin_heght, 256 * bin_width, CV_8UC3);histMat = Scalar(255, 255, 255);float maxVal = *std::max_element(srcHist, srcHist + 256);for (int i = 0; i < 256; i++) {Rect binRect;binRect.x = i * bin_width;float height_i = (float)bin_heght * srcHist[i] / maxVal;binRect.height = (int)height_i;binRect.y = bin_heght - binRect.height;binRect.width = bin_width;rectangle(histMat, binRect, CV_RGB(255, 0, 0), -1);}return 0;
}

 统计视频一个点不受大影响的时候直方图是高斯分布的(灰度)

int index = grayMat.at<uchar>(vP.y, vP.x);

 选取刚才选中的点

histgram[index]++;

在对应的直方图加1

		drawHist(histMat, histgram, bin_width, bin_heght);drawMarker(frame, vP, Scalar(255, 255, 255));

这里还要画一个drawmaker因为第二遍就不会调用了

vp要是全局变量

完整代码:
 

int main() {// 验证某一背景像素值呈高斯分布VideoCapture cap(0);int cnt = 0;float histgram[256] = { 0 };Mat histMat;int bin_width = 3;int bin_heght = 100;while (1){Mat frame;Mat grayMat;cap >> frame;if (cnt == 0){Mat selectMat;frame.copyTo(selectMat);imshow(wName, selectMat);setMouseCallback(wName, on_mouse, &selectMat);waitKey(0);destroyAllWindows();}cvtColor(frame, grayMat, COLOR_BGR2GRAY);int index = grayMat.at<uchar>(vP.y, vP.x);histgram[index]++;drawHist(histMat, histgram, bin_width, bin_heght);drawMarker(frame, vP, Scalar(255, 255, 255));imshow("frame", frame);imshow("histMat", histMat);if (waitKey(30) == 27) {destroyAllWindows();break;}cnt++;}
return 0;
}

当然还有一些变量需要自己设置全局变量


直接拿原图和新图直接做差分

	VideoCapture cap(0);int cnt = 0;Mat frame;while (1) {cap>> frame;cvtColor(frame, frame, COLOR_BGR2GRAY);if (cnt == 0) {//第一帧,获得背景图像frame.copyTo(bgMat);}else {//第二帧开始背景差分//背景图像和当前图像相减absdiff(frame, bgMat, subMat);//差分结果二值化namedWindow("Result", WINDOW_AUTOSIZE);//滑动条创建cv::createTrackbar("threshold", "Result", &sub_threshold, 255, threshold_track);threshold_track(0, 0);imshow("frame", frame);}if (waitKey(30) == 27) {destroyAllWindows();break;}cnt++;}

 其中

absdiff(frame, bgMat, subMat);

如果摄像机是固定的,那么我们可以认为场景(背景)大多数情况下是不变的,而只有前景(被跟踪的目标)会运动,这样就可以建立背景模型。通过比较当前帧和背景模型,就能轻松地跟踪目标运动情况了。这里,最容易想到的比较方式就是当前帧减去背景模型了

将差分的图像二值化 这里创建了滑动条 bar

void threshold_track(int, void*)//这里就是定义的一个回调函数,里面是canny相关的操作
{threshold(subMat, bny_subMat, sub_threshold, 255, CV_THRESH_BINARY);imshow("Result", bny_subMat);
}


运用了高斯差分 因为本身图像的点都符合高斯分布,收光照等等影响,而这些都不能被考虑进移动物

    int nBg = 200;	cap >> frame;cvtColor(frame, frame, COLOR_BGR2GRAY);if (cnt <= nBg) {srcMats.push_back(frame);if (cnt == 0) {std::cout << "--- reading frame --- " << std::endl;}else {std::cout << "-";if (cnt % 50 == 0)std::cout << std::endl;}}

 这里是前200张帧是为了获取高斯分布

计算图像的平均值和方差(灰度)

int calcGaussianBackground(std::vector<cv::Mat> srcMats, cv::Mat& meanMat, cv::Mat& varMat)
{int rows = srcMats[0].rows;int cols = srcMats[0].cols;for (int h = 0; h < rows; h++){for (int w = 0; w < cols; w++){int sum = 0;float var = 0;//求均值for (int i = 0; i < srcMats.size(); i++) {sum += srcMats[i].at<uchar>(h, w);}meanMat.at<uchar>(h, w) = (uchar)(sum / srcMats.size());//求方差for (int i = 0; i < srcMats.size(); i++) {var += (float)pow((srcMats[i].at<uchar>(h, w) - meanMat.at<uchar>(h, w)), 2);}varMat.at<float>(h, w) = var / srcMats.size();}}return 0;
}

利用平均值和方差来判断是否是入侵背景的前景


int gaussianThreshold(cv::Mat srcMat, cv::Mat meanMat, cv::Mat varMat, float weight, cv::Mat& dstMat)
{int rows = srcMat.rows;int cols = srcMat.cols;for (int h = 0; h < rows; h++){for (int w = 0; w < cols; w++){int dif = abs(srcMat.at<uchar>(h, w) - meanMat.at<uchar>(h, w));int th = (int)(weight * varMat.at<float>(h, w));if (dif > th) {dstMat.at<uchar>(h, w) = 255;}else {dstMat.at<uchar>(h, w) = 0;}}}return 0;
}

这里的weight是权重,可以代表差异到什么程度就是前景

完整代码:

VideoCapture cap(0);std::vector<cv::Mat> srcMats;int nBg = 200;		float wVar = 3;int cnt = 0;bool calcModel = true;cv::Mat frame;cv::Mat meanMat;cv::Mat varMat;cv::Mat dstMat;while (1){cap >> frame;cvtColor(frame, frame, COLOR_BGR2GRAY);if (cnt <= nBg) {srcMats.push_back(frame);if (cnt == 0) {std::cout << "--- reading frame --- " << std::endl;}else {std::cout << "-";if (cnt % 50 == 0)std::cout << std::endl;}}else {if (calcModel) {std::cout << std::endl << "calculating background models" << std::endl;//计算模型meanMat.create(frame.size(), CV_8UC1);varMat.create(frame.size(), CV_32FC1);//调用计算模型函数calcGaussianBackground(srcMats, meanMat, varMat);}calcModel = false;//背景差分dstMat.create(frame.size(), CV_8UC1);//利用均值mat和方差mat,计算差分gaussianThreshold(frame, meanMat, varMat, wVar, dstMat);imshow("result", dstMat);imshow("frame", frame);}if (waitKey(30) == 27) {destroyAllWindows();break;}cnt++;}


opencv自带的背景差分方式

	// OPENCV的自带背景差分方式VideoCapture cap(0);	Mat inputFrame, frame, foregroundMask, foreground, background;int method = 0;Ptr<BackgroundSubtractor> model;if (method == 0) {model = createBackgroundSubtractorKNN();}else if (method == 1) {model = createBackgroundSubtractorMOG2();}else {cout << "Can not create background model using provided method: '" << method << "'" << endl;}bool doUpdateModel = true;bool doSmoothMask = false;while (1) {cap >> frame;model->apply(frame, foregroundMask, doUpdateModel ? -1 : 0);imshow("image", frame);if (doSmoothMask){GaussianBlur(foregroundMask, foregroundMask, Size(11, 11), 3.5, 3.5);threshold(foregroundMask, foregroundMask, 10, 255, THRESH_BINARY);}if (foreground.empty())foreground.create(frame.size(), frame.type());foreground = Scalar::all(0);frame.copyTo(foreground, foregroundMask);imshow("foreground mask", foregroundMask);imshow("foreground image", foreground);model->getBackgroundImage(background);if (!background.empty())imshow("mean background image", background);const char key = (char)waitKey(30);if (key == 27 || key == 'q') // ESC{cout << "Exit requested" << endl;break;}else if (key == ' '){doUpdateModel = !doUpdateModel;cout << "Toggle background update: " << (doUpdateModel ? "ON" : "OFF") << endl;}else if (key == 's'){doSmoothMask = !doSmoothMask;cout << "Toggle foreground mask smoothing: " << (doSmoothMask ? "ON" : "OFF") << endl;}}return 0;
}

 S是是否平滑 会用高斯滤波来平滑图像

空格是是否更新背景

目前不是太懂这里的代码 希望后续学到这里后会明白

相关文章:

OPENCV C++(十一)

鼠标响应函数 //鼠标响应函数 void on_mouse(int EVENT, int x, int y, int flags, void* userdata) {Mat hh;hh *(Mat*)userdata;switch (EVENT){case EVENT_LBUTTONDOWN:{vP.x x;vP.y y;drawMarker(hh, vP, Scalar(255, 255, 255));//circle(hh, vP, 4, cvScalar(255, 255…...

ES使用心得

客户端 Transport Client已经快要废弃了&#xff0c;官方推荐使用High Level REST Client。 常用命令 启停 systemctl start elasticsearch systemctl stop elasticsearch节点状态 curl http://myservice1:9200/_cat/nodes?vip heap.percent ram.percent cpu l…...

Stable Diffusion - 幻想 (Fantasy) 风格与糖果世界 (Candy Land) 人物提示词配置

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://spike.blog.csdn.net/article/details/132212193 图像由 DreamShaper8 模型生成&#xff0c;融合糖果世界。 幻想 (Fantasy) 风格图像是一种以想象力为主导的艺术形式&#xff0c;创造了…...

部署K8S集群

目录 一、环境搭建 1、准备环境 2、安装master节点 3、安装k8s-master上的node 4、安装配置k8s-node1节点 5、安装k8s-node2节点 6、为所有node节点配置flannel网络 7、配置docker开启加载防火墙规则允许转发数据 二、k8s常用资源管理 1、创建一个pod 2、pod管理 一、…...

在时间和频率域中准确地测量太阳黑子活动及使用信号处理工具箱(TM)生成广泛的波形,如正弦波、方波等研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…...

一百五十四、Kettle——Linux上安装Kettle9.3(踩坑,亲测有效,附截图)

一、目的 由于kettle8.2在Linux上安装后&#xff0c;共享资源库创建遇到一系列问题&#xff0c;所以就换成kettle9.3 二、kettle版本以及安装包网盘链接 kettle9.3.0安装包网盘链接 链接&#xff1a;https://pan.baidu.com/s/1MS8QBhv9ukpqlVQKEMMHQA?pwddqm0 提取码&…...

PackageNotFoundError: No package metadata was found for bitsandbytes解决方案

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…...

uni-app和springboot完成前端后端对称加密解密流程

概述 使用对称加密的方式实现。前端基于crypto-js。uni-app框架中是在uni.request的基础上&#xff0c;在拦截器中处理的。springboot在Filter中完成解密工作。 uni-app 项目中引入crypto-js。 npm install crypto-js加密方法 const SECRET_KEY CryptoJS.enc.Utf8.parse(…...

【Unity造轮子】制作一个简单的2d抓勾效果(类似蜘蛛侠的技能)

前言 欢迎阅读本文&#xff0c;本文将向您介绍如何使用Unity游戏引擎来实现一个简单而有趣的2D抓勾效果&#xff0c;类似于蜘蛛侠的独特能力。抓勾效果是许多动作游戏和平台游戏中的常见元素&#xff0c;给玩家带来了无限的想象和挑战。 不需要担心&#xff0c;即使您是一…...

Unity 人物连招(三段连击)

一&#xff1a; 连招思路 首先人物角色上有三个攻击实例对象 Damage,每一个damage定义了攻击的伤害值&#xff0c;攻击距离&#xff0c;触发器名称&#xff0c;伤害的发起者&#xff0c;攻击持续时间&#xff0c;攻击重置时间&#xff0c;伤害的碰撞框大小等字段&#xff1a; …...

关于WSL以及docker连接adb的坑

结论 WSL可以连接到adb&#xff0c;需要和主机保持一致的adb型号。主机是windows还是macOS的docker没法直接连接到adb设备&#xff0c;只有主机为Linux才可以。其他平台只能通过TCP网络协议。 具体过程 关于WSL连接adb设备 windows安装adb工具&#xff08;安装可以去官网下…...

python安装第三方包时报错:...\lib\site-packages\pip\_vendor\urllib3\response.py...

安装redis第三方包&#xff1a; pip install redis报错现象&#xff1a; 解决方法&#xff1a;使用以下命令可成功安装 pip install redis -i http://pypi.douban.com/simple --trusted-host pypi.douban.com...

腾讯云从业者认证考试考点——云存储产品

文章目录 存储产品功能云存储产品概述存储产品存储网关存储服务 存储分类按存储方式分按存储频率分 云存储与传统存储的区别功能需求性能需求容量扩展数据共享 云硬盘CBS产品概述归档存储和文件存储归档存储CAS文件存储CFS 对象存储存储网关存储网关的分类 云数据迁移CDM日志服…...

猿辅导Motiff与IXDC达成战略合作,将在UI设计领域推动AI革新更多可能性

近日&#xff0c;“IXDC 2023国际体验设计大会”在北京国家会议中心拉开序幕&#xff0c;3000设计师、1000企业、200全球商业领袖&#xff0c;共襄为期5天的用户体验创新盛会。据了解&#xff0c;此次大会是以“设计领导力”为主题&#xff0c;分享全球设计、科技、商业的前沿趋…...

条件操作符(三目操作符)

比如之前我们想写一个条件判断表达式是这样写的&#xff1a; 用操作符就可以这样写&#xff1a; 应用&#xff0c;比如求两个数的最大值...

(五)Unity开发Vision Pro——FAQ

常见问题 (FAQ) 1.问&#xff1a;我看到在visionOS 模拟器中运行的结果与在硬件上运行的结果不同 请注意&#xff0c;在模拟器中运行时&#xff0c;某些特定于硬件的功能不可用 - 最明显的是 AR 数据。这可能意味着 VisionOS 模拟器中的模拟结果可能与 Vision Pro 耳机上的模…...

GitOps 与 DevOps:了解关键差异,为企业做出最佳选择

在软件开发领域&#xff0c;GitOps 和 DevOps 是加强协作和实现软件交付流程自动化的重要技术。虽然这两种模式都旨在提高软件开发生命周期的效率&#xff0c;但它们的核心原则和实施方式却各不相同。 本篇文章将帮助您了解 GitOps 和 DevOps 之间的差异、它们的工作流程&am…...

Java实现Word文档转PDF,PDF转Word,PDF转Excel,PDF转换工具

前言 java实现word文档转PDF&#xff0c;PDF转word 解决只能转换4页问题 解决每页头部存在水印问题 实现 引入依赖 <dependency><groupId>com.documents4j</groupId><artifactId>documents4j-local</artifactId><version>1.0.3</ve…...

Docker部署ES服务,全量同步的时候内存爆炸,ES自动关闭,CPU100%

问题 使用canal-adapter全量同步&#xff08;参考Canal Adapter1.1.5版本API操作服务&#xff0c;手动同步数据&#xff08;4&#xff09;&#xff09;的时候 小批量数据可以正常运行&#xff08;几千条&#xff09;只要数据量一大&#xff08;上万条&#xff09;&#xff0c…...

Python——添加照片边框

原图&#xff1a; 添加边框后&#xff1a; 添加边框会读取照片的exif信息如时间、相机型号、品牌以及快门焦段等信息&#xff0c;将他们显示在下面的边框中。 获取当前py文件路径 import os #get path that py file located def Get_Currentpath():file_path os.path.abspa…...

wordpress后台更新后 前端没变化的解决方法

使用siteground主机的wordpress网站&#xff0c;会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后&#xff0c;网站没有变化的情况。 不熟悉siteground主机的新手&#xff0c;遇到这个问题&#xff0c;就很抓狂&#xff0c;明明是哪都没操作错误&#x…...

深度学习在微纳光子学中的应用

深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向&#xff1a; 逆向设计 通过神经网络快速预测微纳结构的光学响应&#xff0c;替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…...

DockerHub与私有镜像仓库在容器化中的应用与管理

哈喽&#xff0c;大家好&#xff0c;我是左手python&#xff01; Docker Hub的应用与管理 Docker Hub的基本概念与使用方法 Docker Hub是Docker官方提供的一个公共镜像仓库&#xff0c;用户可以在其中找到各种操作系统、软件和应用的镜像。开发者可以通过Docker Hub轻松获取所…...

Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)

文章目录 1.什么是Redis&#xff1f;2.为什么要使用redis作为mysql的缓存&#xff1f;3.什么是缓存雪崩、缓存穿透、缓存击穿&#xff1f;3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...

【入坑系列】TiDB 强制索引在不同库下不生效问题

文章目录 背景SQL 优化情况线上SQL运行情况分析怀疑1:执行计划绑定问题?尝试:SHOW WARNINGS 查看警告探索 TiDB 的 USE_INDEX 写法Hint 不生效问题排查解决参考背景 项目中使用 TiDB 数据库,并对 SQL 进行优化了,添加了强制索引。 UAT 环境已经生效,但 PROD 环境强制索…...

Cesium1.95中高性能加载1500个点

一、基本方式&#xff1a; 图标使用.png比.svg性能要好 <template><div id"cesiumContainer"></div><div class"toolbar"><button id"resetButton">重新生成点</button><span id"countDisplay&qu…...

Java - Mysql数据类型对应

Mysql数据类型java数据类型备注整型INT/INTEGERint / java.lang.Integer–BIGINTlong/java.lang.Long–––浮点型FLOATfloat/java.lang.FloatDOUBLEdouble/java.lang.Double–DECIMAL/NUMERICjava.math.BigDecimal字符串型CHARjava.lang.String固定长度字符串VARCHARjava.lang…...

P3 QT项目----记事本(3.8)

3.8 记事本项目总结 项目源码 1.main.cpp #include "widget.h" #include <QApplication> int main(int argc, char *argv[]) {QApplication a(argc, argv);Widget w;w.show();return a.exec(); } 2.widget.cpp #include "widget.h" #include &q…...

QT: `long long` 类型转换为 `QString` 2025.6.5

在 Qt 中&#xff0c;将 long long 类型转换为 QString 可以通过以下两种常用方法实现&#xff1a; 方法 1&#xff1a;使用 QString::number() 直接调用 QString 的静态方法 number()&#xff0c;将数值转换为字符串&#xff1a; long long value 1234567890123456789LL; …...

vue3+vite项目中使用.env文件环境变量方法

vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量&#xff0c;这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...