【OpenCV】场景中人的识别与前端计数

1.OpenCV代码设计讲解

突发奇想,搞个摄像头,识别一下实验室里面有几个人,计数一下(最终代码是累加计数,没有优化),拿OpenCV来玩一玩

首先,还是优先启动电脑摄像头,本项目将使用SSD进行人体检测。
deploy.prototxt与mobilenet_iter_73000.caffemodel自行从官网下载。

完整代码如下:

import cv2
import numpy as np# 加载MobileNet-SSD模型
net = cv2.dnn.readNetFromCaffe('deploy.prototxt', 'mobilenet_iter_73000.caffemodel')# 打开摄像头
cap = cv2.VideoCapture(0)while cap.isOpened():ret, frame = cap.read()if ret:# 创建blob,预处理输入数据# cv2.resize(frame, (300, 300)),将输入的 frame 图像调整为 300x300 像素的大小# 神经网络通常要求输入图像的尺寸固定,因此需要调整图像大小# frame:要处理的原始图像,(300, 300):目标图像的宽度和高度# 0.007843:这是一个缩放因子,用于将像素值缩放到适合神经网络的范围。# 127.5:是一个均值值,用于对像素进行归一化处理,使用 Caffe 训练的模型,输入图像通常会减去均值以中心化数据。blob = cv2.dnn.blobFromImage(cv2.resize(frame, (300, 300)), 0.007843, (300, 300), 127.5)net.setInput(blob)# 进行前向传播,得到检测结果detections = net.forward()# 获取帧的宽度和高度# 在 OpenCV 中,图像通常被表示为一个 NumPy 数组,其维度是 (height, width, channels)(h, w) = frame.shape[:2]# 具体结构由 cv2.dnn 模块的输出格式决定。# 对于物体检测任务,网络输出的数据维度一般是一个 4D 的张量 (NumPy 数组),其形状大致为(1, 1, N, 7)# 1 (Batch size):处理的图像批次数量,通常为 1,因为我们处理的是单张图像。# 1 (Number of classes):如果是单类检测,这里也是 1,表示输出的类别信息(可能是分类器的层数)。# N (Number of detections):这是该图像中检测到的对象数量。例如,网络可能检测到 100 个对象,N 就是 100。# 7 (Detection details):每个检测结果包含 7 个值,分别表示:# 第1个值: 检测结果的标签索引(通常是类别ID)。# 第2个值: 置信度 (confidence score)。# 第3-7个值: 边界框的坐标 (bounding box coordinates: x1, y1, x2, y2)。# 遍历检测结果for i in range(detections.shape[2]):confidence = detections[0, 0, i, 2]# 设置最低置信度阈值if confidence > 0.4:idx = int(detections[0, 0, i, 1])# 只检测人类(index 15是人类类别)if idx == 15:box = detections[0, 0, i, 3:7] * np.array([w, h, w, h])(startX, startY, endX, endY) = box.astype("int")# 画框标记人类cv2.rectangle(frame, (startX, startY), (endX, endY), (0, 255, 0), 2)# 显示结果cv2.imshow("Human Detection", frame)# 按 'q' 键退出if cv2.waitKey(1) & 0xFF == ord('q'):breakelse:breakcap.release()
cv2.destroyAllWindows()

2.升级一下

给判定到的人数记录下来,因为不是什么重要数据,拿redis存一下,然后通过前端展示出来,效果如下:

在这里插入图片描述

代码如下:

import cv2
import numpy as np
import redis
from flask import Flask, jsonify
from flask_cors import CORS  # 引入 CORS# 初始化 Flask 应用
app = Flask(__name__)
CORS(app)  # 启用 CORS 支持# 连接 Redis 服务器
r = redis.Redis(host='localhost', port=6379, db=0)# 加载 MobileNet-SSD 模型
net = cv2.dnn.readNetFromCaffe('deploy.prototxt', 'mobilenet_iter_73000.caffemodel')# 摄像头检测函数
def detect_humans():cap = cv2.VideoCapture(0)while cap.isOpened():ret, frame = cap.read()if ret:# 创建 blob,预处理输入数据blob = cv2.dnn.blobFromImage(cv2.resize(frame, (300, 300)), 0.007843, (300, 300), 127.5)net.setInput(blob)# 进行前向传播,得到检测结果detections = net.forward()# 获取帧的宽度和高度(h, w) = frame.shape[:2]# 初始化检测到的人数human_count = 0# 遍历检测结果for i in range(detections.shape[2]):confidence = detections[0, 0, i, 2]# 设置最低置信度阈值if confidence > 0.4:idx = int(detections[0, 0, i, 1])# 只检测人类(index 15 是人类类别)if idx == 15:human_count += 1  # 增加检测到的人数box = detections[0, 0, i, 3:7] * np.array([w, h, w, h])(startX, startY, endX, endY) = box.astype("int")# 画框标记人类cv2.rectangle(frame, (startX, startY), (endX, endY), (0, 255, 0), 2)# 将人数写入 Redis 缓存r.set('human_count', human_count)# 显示结果cv2.imshow("Human Detection", frame)# 按 'q' 键退出if cv2.waitKey(1) & 0xFF == ord('q'):breakelse:breakcap.release()cv2.destroyAllWindows()# 创建一个 API 路由来返回 Redis 中的人数
@app.route('/get_human_count', methods=['GET'])
def get_human_count():# 从 Redis 中获取人数human_count = r.get('human_count')if human_count:human_count = int(human_count)else:human_count = 0return jsonify({'human_count': human_count})if __name__ == '__main__':# 启动摄像头检测from threading import Threadt = Thread(target=detect_humans)t.daemon = Truet.start()# 启动 Flask 服务app.run(debug=True, host='0.0.0.0')

前端代码是Online Tutorials上学来的,自己稍微改了一下html的部分:

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Human Detection Count</title><link rel="stylesheet" href="human_style.css">
</head>
<body><div class="card"><div class="rating"><h2><span class="counter" data-target="0">0</span><sup>%</sup><br>Human</h2><div class="block"></div></div></div><script>// 初始化区块const rating = document.getElementsByClassName('rating')[0];const block = document.getElementsByClassName('block');for (let i = 1; i < 100; i++) {rating.innerHTML += "<div class='block'></div>";block[i].style.transform = "rotate(" + 3.6 * i + "deg)";block[i].style.animationDelay = `${i / 40}s`;}// 获取 Redis 中的人数并更新function fetchHumanCount() {fetch('http://127.0.0.1:5000/get_human_count')  // 后端 API 路由.then(response => response.json()).then(data => {const counter = document.querySelector('.counter');const target = data.human_count;  // 获取 Redis 中的值counter.setAttribute('data-target', target);// 启动计数器const NumberCounter = () => {const value = +counter.innerText;if (value < target) {counter.innerText = Math.ceil(value + 1);setTimeout(() => {NumberCounter();}, 25);}};NumberCounter();}).catch(error => console.error('Error fetching human count:', error));}// 每秒更新一次人数setInterval(fetchHumanCount, 1000);</script>
</body>
</html>

css全是Online Tutorials大佬写的,跟着视频敲了一遍:

@import url('https://fonts.googleapis.com/css?family=Poppins:200,300,400,500,600,700,800,900&display=swap');
*
{margin: 0;padding: 0%;box-sizing: border-box;font-family: 'Poppins', sans-serif;
}
body
{display: flex;justify-content: center;align-items: center;min-height: 100vh;background: radial-gradient(#444,#222);}
.card
{position: relative;width: 200px;height: 200px;}
.card .rating
{position: relative;width: 100%;height: 100%;/* background: rgba(107, 170, 221, 0.2); */
}
.card .rating .block
{position: absolute;width: 2px;height: 15px;background: #000;left: 50%;transform-origin: 50% 100px;opacity: 0;animation: animate 0.1s linear forwards;
}
.card .rating .block:nth-child(-n+90)
{background:#0f0;box-shadow: 0 0 15px #0f0,0 0 30px #0f0;
}
@keyframes animate {to{opacity: 1;}
}.card .rating h2{position: absolute;top:50%;left: 50%;transform:translate(-50%,-50%);color: #fff;font-size: 1.2em;font-weight: 500;text-align: center;line-height: 1.5em;
}.card .rating h2 span{font-size: 2.5em;font-weight: 700;
}.card .rating h2 sup
{font-size: 1.5em;font-weight: 300;
}

今天就先不写详解了,歇会~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/1543457.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

实验十七:串口通信实验

串口通信实验硬件接口图 具体原理可以查看相应的资料和视频 现就代码分享如下; main.c #include<reg52.h>typedef unsigned int u16; typedef unsigned char u8;sbit LED1=P2^0;void delay_10us(u16 n) {while(n--); }int n=0;void delay_ms(u16 ms) {u16 i,j;for(i=…

在线思维导图怎么制作?只需要台这些组合分析法!

思维导图经历了漫长的进化&#xff0c;现已成为信息组织、记忆和头脑风暴的重要工具。其制作方式主要有手绘和软件两种&#xff0c;随着互联网的发展&#xff0c;软件制作因其便捷性和易于保存逐渐占据主导。如今&#xff0c;在线工具使得用户能够免费创建思维导图。本文将以即…

实验十八:IIC-EEPROM实验

这个实验比较复杂,是目前第一个多文件项目 KEY1-4:P3^0-P3^3 IIC_SCL=P2^1; IIC_SDA=P2^0; //定义数码管位选信号控制脚 LSA=P2^2; LSB=P2^3; LSC=P2^4; 代码 main.c #include "public.h" #in

写作文的AI,不妨试试这些工具

写作文的AI&#xff0c;随着人工智能技术的迅猛发展&#xff0c;AI写作软件已经成为许多作家、学生和内容创作者的得力助手。这些软件不仅能帮助用户生成高质量的文章&#xff0c;还能提供创意灵感、语法校正和内容优化等多重功能。下面&#xff0c;本文将介绍五款各具特色的AI…

真正能抵抗裁员的,从不是专业能力,早知道这些都财务自由了

‍‍‍‍前几天跟一位朋友聊起来。 说她在大厂工作接近5年&#xff0c;业绩也不错&#xff0c;本想着再熬几年就回老家发展。没想到&#xff0c;今年公司大幅裁员&#xff0c;项目组直接被连锅端。 本以为不会轮到她了&#xff0c;上午被叫去办公室谈话&#xff0c;签字&…

高温情况下电容器失效的解决措施

在高温环境下&#xff0c;电容器容易出现失效问题&#xff0c;这不仅会影响设备的正常运行&#xff0c;还可能引发安全隐患。为有效应对高温条件下电容器的失效&#xff0c;需从预防、监测、选择合适的电容器以及维护保养等多个方面入手。以下是详细的解决措施&#xff1a; 一…

男生找女搭子一起旅游的目的,并没有你想象中的那么复杂!

在繁华都市的写字楼里&#xff0c;有一个名叫林宇的男生。最近&#xff0c;他在工作上遭遇了一系列的挫折&#xff0c;项目进展不顺&#xff0c;还被领导批评&#xff0c;心情郁闷到了极点。 为了排解心中的烦闷&#xff0c;林宇决定出去旅游。但他不想一个人孤单地踏上旅程&am…

彻底掌握Android中的ViewModel

彻底掌握Android中的ViewModel ViewModel 属于Android Jetpack库的一部分&#xff0c;是一种业务逻辑或屏幕状态容器。它提供了在配置更改&#xff08;如屏幕旋转&#xff09;后依旧保留相应状态的特性&#xff0c;帮助开发者以更加清晰和可维护的方式处理UI相关的数据&#x…

【中级通信工程师】终端与业务(二):终端产品

【零基础3天通关中级通信工程师】 终端与业务(二)&#xff1a;终端产品 本文是中级通信工程师考试《终端与业务》科目第二章《终端产品》的复习资料和真题汇总。终端与业务是通信考试里最简单的科目&#xff0c;有效复习通过率可达90%以上&#xff0c;本文结合了高频考点和近几…

产教专家共议数字时代下的数据思维人才培养

8 月 25 日至 26 日&#xff0c;"数据思维人才培养论坛"在大湾区大学松山湖校区圆满落幕。此次论坛作为对两个月前新时代计算机本科教育论坛上相关议题的深化&#xff0c;由中国人民大学杜小勇教授与大湾区大学李晓明教授携手发起。和鲸科技创始人、CEO 范向伟先生受…

【常见框架漏洞】ThinkPHP、struts2、Spring、Shiro

一、ThinkPHP 1.环境配置 靶场:vulhub/thinkphp/5-rcedocker-compose up -d #启动环境 访问靶场:http://ip:8080/index.php2.远程命令执行 执行whoami命令 poc: http://47.121.211.205:8080/index.php?sindex/think\app/invokefunction&functioncall_user_func_array&…

算法【Java】—— 位运算

位运算总结 位运算的运算符&#xff1a;按位与&#xff08;&&#xff09;&#xff0c;按位或&#xff08;|&#xff09;&#xff0c;按位异或&#xff08;^&#xff09;&#xff0c;按位取反&#xff08;~&#xff09;&#xff0c;还有移位操作符 <<&#xff0c;>…

加密与解密-PEiD查壳工具的下载及详细安装过程(附有下载文件)

下载链接在文末 下载压缩包后解压 &#xff01;&#xff01;安装路径不要有中文 解压后得到PEiD文件 双击任意一个即可运行使用 夸克网盘打开&#xff1a; 链接&#xff1a;https://pan.quark.cn/s/1216d81f1af5 提取码&#xff1a;pJ1W 动态分析工具 加密与解密-x32dbg…

人工智能时代:程序员的核心竞争力提升指南

在人工智能时代&#xff0c;程序员的核心竞争力不仅体现在编码技能上&#xff0c;更在于如何利用AI技术提升工作效率和创新能力。以下是一些关键点&#xff0c;可以帮助程序员在AI时代保持并提升自身的核心竞争力。 AI辅助编程正在逐渐改变程序员的工作方式&#xff0c;带来了一…

【人工智能】Transformers之Pipeline(十九):文生文(text2text-generation)

目录 一、引言 二、文生文&#xff08;text2text-generation&#xff09; 2.1 概述 2.2 Flan-T5: One Model for ALL Tasks 2.3 pipeline参数 2.3.1 pipeline对象实例化参数 2.3.2 pipeline对象使用参数 ​​​​​​​ 2.3.3 pipeline返回参数 ​​​​​​​​​​​…

模拟实现(优先级队列)priority_queue:优先级队列、仿函数、 反向迭代器等的介绍

文章目录 前言一、优先级队列二、仿函数三、 反向迭代器总结 前言 模拟实现&#xff08;优先级队列&#xff09;priority_queue&#xff1a;优先级队列、仿函数、 反向迭代器等的介绍 一、优先级队列 优先级队列本质是一个堆&#xff0c;使用vector容器进一步改进进行实现&am…

面向对象 vs 面向过程

Java 和 C 语言的区别&#xff1a;面向对象 vs 面向过程 在编程世界中&#xff0c;不同的编程语言承载着不同的编程范式。C 语言作为一门经典的面向过程编程语言&#xff0c;注重函数的调用和操作&#xff1b;而Java则是典型的面向对象编程语言&#xff0c;重视对象与类的设计…

【计算机网络】传输层协议TCP

目录 一、重新理解封装和解包二、TCP协议段格式三、确认应答(ACK)机制四、超时重传机制五、连接管理机制六、理解TIME_WAIT状态和CLOSE_WAIT状态七、流量控制八、滑动窗口九、拥塞控制十、延迟应答十一、面向字节流十二、粘包问题 一、重新理解封装和解包 在网络协议栈中&…

【LeetCode】动态规划—第 N 个泰波那契数(附完整Python/C++代码)

动态规划—#1137. 第 N 个泰波那契数 前言题目描述基本思路1. 泰波那契数列的定义:2. 理解递推关系:3. 解决方法:4. 进一步优化:5. 小总结: 代码实现Python3代码实现Python 代码解释C代码实现C 代码解释 总结: 前言 泰波那契数列是斐波那契数列的扩展版本。在斐波那契数列中&a…

三款远控工具大比拼,哪款更胜一筹?

当我们处在日益便捷的数字化生活中&#xff0c;我们不仅需要在实体空间与物理环境间活动&#xff0c;我们更可以通过科技的力量在屏幕间自由穿梭&#xff1b;向日葵远程控制工具&#xff0c;就是这样一款能让你在指尖上体验到操作乐趣的神奇工具&#xff1b;今天&#xff0c;就…