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已经快要废弃了,官方推荐使用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:https://spike.blog.csdn.net/ 本文地址:https://spike.blog.csdn.net/article/details/132212193 图像由 DreamShaper8 模型生成,融合糖果世界。 幻想 (Fantasy) 风格图像是一种以想象力为主导的艺术形式,创造了…...
部署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代码实现)
💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…...
一百五十四、Kettle——Linux上安装Kettle9.3(踩坑,亲测有效,附截图)
一、目的 由于kettle8.2在Linux上安装后,共享资源库创建遇到一系列问题,所以就换成kettle9.3 二、kettle版本以及安装包网盘链接 kettle9.3.0安装包网盘链接 链接: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的基础上,在拦截器中处理的。springboot在Filter中完成解密工作。 uni-app 项目中引入crypto-js。 npm install crypto-js加密方法 const SECRET_KEY CryptoJS.enc.Utf8.parse(…...
【Unity造轮子】制作一个简单的2d抓勾效果(类似蜘蛛侠的技能)
前言 欢迎阅读本文,本文将向您介绍如何使用Unity游戏引擎来实现一个简单而有趣的2D抓勾效果,类似于蜘蛛侠的独特能力。抓勾效果是许多动作游戏和平台游戏中的常见元素,给玩家带来了无限的想象和挑战。 不需要担心,即使您是一…...
Unity 人物连招(三段连击)
一: 连招思路 首先人物角色上有三个攻击实例对象 Damage,每一个damage定义了攻击的伤害值,攻击距离,触发器名称,伤害的发起者,攻击持续时间,攻击重置时间,伤害的碰撞框大小等字段: …...
关于WSL以及docker连接adb的坑
结论 WSL可以连接到adb,需要和主机保持一致的adb型号。主机是windows还是macOS的docker没法直接连接到adb设备,只有主机为Linux才可以。其他平台只能通过TCP网络协议。 具体过程 关于WSL连接adb设备 windows安装adb工具(安装可以去官网下…...
python安装第三方包时报错:...\lib\site-packages\pip\_vendor\urllib3\response.py...
安装redis第三方包: pip install redis报错现象: 解决方法:使用以下命令可成功安装 pip install redis -i http://pypi.douban.com/simple --trusted-host pypi.douban.com...
腾讯云从业者认证考试考点——云存储产品
文章目录 存储产品功能云存储产品概述存储产品存储网关存储服务 存储分类按存储方式分按存储频率分 云存储与传统存储的区别功能需求性能需求容量扩展数据共享 云硬盘CBS产品概述归档存储和文件存储归档存储CAS文件存储CFS 对象存储存储网关存储网关的分类 云数据迁移CDM日志服…...
猿辅导Motiff与IXDC达成战略合作,将在UI设计领域推动AI革新更多可能性
近日,“IXDC 2023国际体验设计大会”在北京国家会议中心拉开序幕,3000设计师、1000企业、200全球商业领袖,共襄为期5天的用户体验创新盛会。据了解,此次大会是以“设计领导力”为主题,分享全球设计、科技、商业的前沿趋…...
条件操作符(三目操作符)
比如之前我们想写一个条件判断表达式是这样写的: 用操作符就可以这样写: 应用,比如求两个数的最大值...
(五)Unity开发Vision Pro——FAQ
常见问题 (FAQ) 1.问:我看到在visionOS 模拟器中运行的结果与在硬件上运行的结果不同 请注意,在模拟器中运行时,某些特定于硬件的功能不可用 - 最明显的是 AR 数据。这可能意味着 VisionOS 模拟器中的模拟结果可能与 Vision Pro 耳机上的模…...
GitOps 与 DevOps:了解关键差异,为企业做出最佳选择
在软件开发领域,GitOps 和 DevOps 是加强协作和实现软件交付流程自动化的重要技术。虽然这两种模式都旨在提高软件开发生命周期的效率,但它们的核心原则和实施方式却各不相同。 本篇文章将帮助您了解 GitOps 和 DevOps 之间的差异、它们的工作流程&am…...
Java实现Word文档转PDF,PDF转Word,PDF转Excel,PDF转换工具
前言 java实现word文档转PDF,PDF转word 解决只能转换4页问题 解决每页头部存在水印问题 实现 引入依赖 <dependency><groupId>com.documents4j</groupId><artifactId>documents4j-local</artifactId><version>1.0.3</ve…...
Docker部署ES服务,全量同步的时候内存爆炸,ES自动关闭,CPU100%
问题 使用canal-adapter全量同步(参考Canal Adapter1.1.5版本API操作服务,手动同步数据(4))的时候 小批量数据可以正常运行(几千条)只要数据量一大(上万条),…...
Python——添加照片边框
原图: 添加边框后: 添加边框会读取照片的exif信息如时间、相机型号、品牌以及快门焦段等信息,将他们显示在下面的边框中。 获取当前py文件路径 import os #get path that py file located def Get_Currentpath():file_path os.path.abspa…...
wordpress后台更新后 前端没变化的解决方法
使用siteground主机的wordpress网站,会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后,网站没有变化的情况。 不熟悉siteground主机的新手,遇到这个问题,就很抓狂,明明是哪都没操作错误&#x…...
深度学习在微纳光子学中的应用
深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向: 逆向设计 通过神经网络快速预测微纳结构的光学响应,替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…...
DockerHub与私有镜像仓库在容器化中的应用与管理
哈喽,大家好,我是左手python! Docker Hub的应用与管理 Docker Hub的基本概念与使用方法 Docker Hub是Docker官方提供的一个公共镜像仓库,用户可以在其中找到各种操作系统、软件和应用的镜像。开发者可以通过Docker Hub轻松获取所…...
Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)
文章目录 1.什么是Redis?2.为什么要使用redis作为mysql的缓存?3.什么是缓存雪崩、缓存穿透、缓存击穿?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个点
一、基本方式: 图标使用.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 中,将 long long 类型转换为 QString 可以通过以下两种常用方法实现: 方法 1:使用 QString::number() 直接调用 QString 的静态方法 number(),将数值转换为字符串: long long value 1234567890123456789LL; …...
vue3+vite项目中使用.env文件环境变量方法
vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量,这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...
