当前位置: 首页 > 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…...

华为云AI开发平台ModelArts

华为云ModelArts&#xff1a;重塑AI开发流程的“智能引擎”与“创新加速器”&#xff01; 在人工智能浪潮席卷全球的2025年&#xff0c;企业拥抱AI的意愿空前高涨&#xff0c;但技术门槛高、流程复杂、资源投入巨大的现实&#xff0c;却让许多创新构想止步于实验室。数据科学家…...

mongodb源码分析session执行handleRequest命令find过程

mongo/transport/service_state_machine.cpp已经分析startSession创建ASIOSession过程&#xff0c;并且验证connection是否超过限制ASIOSession和connection是循环接受客户端命令&#xff0c;把数据流转换成Message&#xff0c;状态转变流程是&#xff1a;State::Created 》 St…...

基于服务器使用 apt 安装、配置 Nginx

&#x1f9fe; 一、查看可安装的 Nginx 版本 首先&#xff0c;你可以运行以下命令查看可用版本&#xff1a; apt-cache madison nginx-core输出示例&#xff1a; nginx-core | 1.18.0-6ubuntu14.6 | http://archive.ubuntu.com/ubuntu focal-updates/main amd64 Packages ng…...

江苏艾立泰跨国资源接力:废料变黄金的绿色供应链革命

在华东塑料包装行业面临限塑令深度调整的背景下&#xff0c;江苏艾立泰以一场跨国资源接力的创新实践&#xff0c;重新定义了绿色供应链的边界。 跨国回收网络&#xff1a;废料变黄金的全球棋局 艾立泰在欧洲、东南亚建立再生塑料回收点&#xff0c;将海外废弃包装箱通过标准…...

Spring Boot面试题精选汇总

&#x1f91f;致敬读者 &#x1f7e9;感谢阅读&#x1f7e6;笑口常开&#x1f7ea;生日快乐⬛早点睡觉 &#x1f4d8;博主相关 &#x1f7e7;博主信息&#x1f7e8;博客首页&#x1f7eb;专栏推荐&#x1f7e5;活动信息 文章目录 Spring Boot面试题精选汇总⚙️ **一、核心概…...

涂鸦T5AI手搓语音、emoji、otto机器人从入门到实战

“&#x1f916;手搓TuyaAI语音指令 &#x1f60d;秒变表情包大师&#xff0c;让萌系Otto机器人&#x1f525;玩出智能新花样&#xff01;开整&#xff01;” &#x1f916; Otto机器人 → 直接点明主体 手搓TuyaAI语音 → 强调 自主编程/自定义 语音控制&#xff08;TuyaAI…...

现有的 Redis 分布式锁库(如 Redisson)提供了哪些便利?

现有的 Redis 分布式锁库&#xff08;如 Redisson&#xff09;相比于开发者自己基于 Redis 命令&#xff08;如 SETNX, EXPIRE, DEL&#xff09;手动实现分布式锁&#xff0c;提供了巨大的便利性和健壮性。主要体现在以下几个方面&#xff1a; 原子性保证 (Atomicity)&#xff…...

GO协程(Goroutine)问题总结

在使用Go语言来编写代码时&#xff0c;遇到的一些问题总结一下 [参考文档]&#xff1a;https://www.topgoer.com/%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B/goroutine.html 1. main()函数默认的Goroutine 场景再现&#xff1a; 今天在看到这个教程的时候&#xff0c;在自己的电…...

PostgreSQL——环境搭建

一、Linux # 安装 PostgreSQL 15 仓库 sudo dnf install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-$(rpm -E %{rhel})-x86_64/pgdg-redhat-repo-latest.noarch.rpm# 安装之前先确认是否已经存在PostgreSQL rpm -qa | grep postgres# 如果存在&#xff0…...

安卓基础(Java 和 Gradle 版本)

1. 设置项目的 JDK 版本 方法1&#xff1a;通过 Project Structure File → Project Structure... (或按 CtrlAltShiftS) 左侧选择 SDK Location 在 Gradle Settings 部分&#xff0c;设置 Gradle JDK 方法2&#xff1a;通过 Settings File → Settings... (或 CtrlAltS)…...