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

浏览器实时播放摄像头数据并通过 Yolo 进行图像识别

安装 Ultralytics 之后,可以直接通过本地获取摄像头数据流,并通过 Yolo 模型实时进行识别。大多情况下,安装本地程序成本比较高,需要编译打包等等操作,如果可以直接通过浏览器显示视频,并实时显示识别到的对象类型就会方便很多。本文将通过 JS 原生代码 + 后台 Yolo 识别服务实现浏览器实时显示并识别对象类型的效果。

后发服务

后台服务采用 Python Flask 框架实现图片识别的 Rest API,开发之前,首先安装 Ultralytics 环境,我们使用官方的 DockerImage,用官方镜像作为基础镜像,安装相关依赖。

Dockerfile

# Use the ultralytics/ultralytics image as the base
FROM ultralytics/ultralytics:latest# Update package lists and install vim
RUN apt-get update && apt-get install -y vim# Install Flask using pip
RUN pip install flask flask-cors# Set the working directory
WORKDIR /app# Copy the current directory contents into the container at /app
COPY . /app# Expose port 5000 for Flask
EXPOSE 5000# Command to run the Flask application

App.py
后台 Rest API,/detect,解析 base64 图片,并返回识别到的图片分类和位置信息。

import os
from flask import Flask, request, jsonify
from ultralytics import YOLO
import cv2
import numpy as np# Initialize Flask app
app = Flask(__name__)# Load YOLOv8 model
model = YOLO('yolov8n.pt')  # You can change 'yolov8n.pt' to other versions like 'yolov8m.pt' or 'yolov8x.pt'# Function to perform object detection
def detect_objects(image):results = model(image)detections = []for result in results:for box in result.boxes:x1, y1, x2, y2 = map(int, box.xyxy)class_id = int(box.cls)confidence = box.confdetections.append({'class_id': class_id,'label': model.names[class_id],'confidence': float(confidence),'bbox': [x1, y1, x2, y2]})return detections# Route for object detection
@app.route('/detect', methods=['POST'])
def detect():if 'image' not in request.files:return jsonify({'error': 'No image provided'}), 400file = request.files['image']if file.filename == '':return jsonify({'error': 'No image selected for uploading'}), 400# Read imageimage = np.frombuffer(file.read(), np.uint8)image = cv2.imdecode(image, cv2.IMREAD_COLOR)# Perform detectiondetections = detect_objects(image)return jsonify(detections)# Run Flask app
if __name__ == '__main__':app.run(host='0.0.0.0', port=5000)

前端页面

在页面显示摄像头,实时发送图片数据到后台进行识别,获取位置并显示在画布纸上。

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Real-Time Object Detection with YOLO</title><style>body {display: flex;justify-content: center;align-items: center;height: 100vh;margin: 0;background-color: #f0f0f0;overflow: hidden;}#camera, #canvas {position: absolute;width: 50%;height: 50%;object-fit: cover;}#camera {z-index: 1;}#canvas {z-index: 2;}</style>
</head>
<body><video id="camera" autoplay playsinline></video><canvas id="canvas"></canvas><script>const classColors = {};function getRandomColor() {const letters = '0123456789ABCDEF';let color = '#';for (let i = 0; i < 6; i++) {color += letters[Math.floor(Math.random() * 16)];}return color;}function isMobileDevice() {return /Mobi|Android/i.test(navigator.userAgent);}async function setupCamera() {const video = document.getElementById('camera');const facingMode = isMobileDevice() ? 'environment' : 'user'; // Use back camera for mobile, front camera for PCtry {const stream = await navigator.mediaDevices.getUserMedia({video: {facingMode: { ideal: facingMode }}});video.srcObject = stream;return new Promise((resolve) => {video.onloadedmetadata = () => {resolve(video);};});} catch (error) {console.error('Error accessing camera:', error);alert('Error accessing camera: ' + error.message);}}async function sendFrameToBackend(imageData) {const response = await fetch('https://c.hawk.leedar360.com/api/detect', {method: 'POST',headers: {'Content-Type': 'application/json'},body: JSON.stringify({ image: imageData })});return await response.json();}function getBase64Image(video) {const canvas = document.createElement('canvas');canvas.width = video.videoWidth;canvas.height = video.videoHeight;const ctx = canvas.getContext('2d');ctx.drawImage(video, 0, 0, canvas.width, canvas.height);return canvas.toDataURL('image/jpeg').split(',')[1];}function renderDetections(detections, canvas, video) {const ctx = canvas.getContext('2d');ctx.clearRect(0, 0, canvas.width, canvas.height);ctx.drawImage(video, 0, 0, canvas.width, canvas.height);detections.forEach(det => {const { bbox, confidence, class_id, label } = det;if (confidence > 0.5) { // Only show detections with confidence > 0.5const [x, y, w, h] = bbox;if (!classColors[class_id]) {classColors[class_id] = getRandomColor();}const color = classColors[class_id];ctx.beginPath();ctx.rect(x, y, w - x, h - y);ctx.lineWidth = 2;ctx.strokeStyle = color;ctx.fillStyle = color;ctx.stroke();ctx.font = '24px Arial';  // Set font size to 24pxctx.fillText(`${label} (${Math.round(confidence * 100)}%)`,x,y > 24 ? y - 10 : 24  // Adjust position for the larger font size);}});}async function main() {const video = await setupCamera();if (!video) {console.error('Camera setup failed');return;}video.play();const canvas = document.getElementById('canvas');canvas.width = video.videoWidth;canvas.height = video.videoHeight;async function processFrame() {const imageData = getBase64Image(video);const detections = await sendFrameToBackend(imageData);renderDetections(detections, canvas, video);requestAnimationFrame(processFrame);}processFrame();}main();// Handle orientation change and resizingwindow.addEventListener('resize', () => {const video = document.getElementById('camera');const canvas = document.getElementById('canvas');canvas.width = video.videoWidth;canvas.height = video.videoHeight;});window.addEventListener('orientationchange', () => {const video = document.getElementById('camera');const canvas = document.getElementById('canvas');canvas.width = video.videoWidth;canvas.height = video.videoHeight;});</script>
</body>
</html>

总结

功能很好实现,效果还要微调,苹果的充电器并没有识别出来。

请添加图片描述

相关文章:

浏览器实时播放摄像头数据并通过 Yolo 进行图像识别

安装 Ultralytics 之后&#xff0c;可以直接通过本地获取摄像头数据流&#xff0c;并通过 Yolo 模型实时进行识别。大多情况下&#xff0c;安装本地程序成本比较高&#xff0c;需要编译打包等等操作&#xff0c;如果可以直接通过浏览器显示视频&#xff0c;并实时显示识别到的对…...

redis清空list

redis list清空 要清空Redis中的list&#xff0c;您可以使用LTRIM命令。Redis Ltrim 对一个列表进行修剪(trim)&#xff0c;就是说&#xff0c;让列表只保留指定区间内的元素&#xff0c;不在指定区间之内的元素都将被删除。 下标 0 表示列表的第一个元素&#xff0c;以 1 表示…...

汽车油耗NEDC与WLTP有什么区别?以及MATLAB/Simulink的汽车行驶工况仿真

最近的热点新闻非比亚迪的秦L莫属&#xff0c;其油耗达到2.9L/100km&#xff0c;但其标注为NEDC也引起了讨论&#xff0c; NEDC与WLTP的区别 NEDC的全称为“New European Driving Cycle”&#xff0c;即“新欧洲驾驶循环”。这种油耗测试标准起源于上世纪80年代&#xff0c;主…...

【Python】已解决报错:AttributeError: module ‘json‘ has no attribute ‘loads‘解决办法

&#x1f60e; 作者介绍&#xff1a;我是程序员洲洲&#xff0c;一个热爱写作的非著名程序员。CSDN全栈优质领域创作者、华为云博客社区云享专家、阿里云博客社区专家博主。 &#x1f913; 同时欢迎大家关注其他专栏&#xff0c;我将分享Web前后端开发、人工智能、机器学习、深…...

(5)按钮输入

文章目录 前言 1 基础设置 2 数字逻辑/模拟电压设置 3 PWM输入设置 4 额外设置 前言 连接到自动驾驶仪的最多四个外部按钮或开关可以被配置为触发辅助功能(Auxiliary Functions)&#xff0c;类似于 RC 通道开关的触发方式。这些按钮输入可以被配置为使用数字逻辑电平电压…...

嵌入式开发、C++后台开发、C++音视频开发怎么选择?

开始前刚好我有一些资料&#xff0c;是我根据网友给的问题精心整理了一份「嵌入式的资料从专业入门到高级教程」&#xff0c; 点个关注在评论区回复“888”之后私信回复“888”&#xff0c;全部无偿共享给大家&#xff01;&#xff01;&#xff01; 嵌入式开发&#xff1a;非常…...

高考志愿填报,大学读什么专业比较好?

高考分数出炉后&#xff0c;选择什么样的专业&#xff0c;如何去选择专业&#xff1f;于毕业生而言是一个难题。因为&#xff0c;就读的专业前景不好&#xff0c;意味着就业情况不乐观&#xff0c;意味着毕业就是失业。 盲目选择专业的确会让自己就业时受挫&#xff0c;也因此…...

33 _ 跨站脚本攻击(XSS):为什么Cookie中有HttpOnly属性?

通过上篇文章的介绍&#xff0c;我们知道了同源策略可以隔离各个站点之间的DOM交互、页面数据和网络通信&#xff0c;虽然严格的同源策略会带来更多的安全&#xff0c;但是也束缚了Web。这就需要在安全和自由之间找到一个平衡点&#xff0c;所以我们默认页面中可以引用任意第三…...

C++入门小结

C命名空间总结 C 中的命名空间&#xff08;Namespace&#xff09;是一种组织代码的方式&#xff0c;用于避免全局命名冲突。在同一个命名空间中&#xff0c;可以有相同名称的变量、函数和类&#xff0c;但它们彼此互不影响。下面是对 C 命名空间的一些总结&#xff1a; 定义命…...

Java 开发实例:Spring Boot+AOP+注解+Redis防重复提交(防抖)

文章目录 1. 环境准备2. 引入依赖3. 配置Redis4. 创建防重复提交注解5. 实现AOP切面6. 创建示例Controller7. 测试8. 进一步优化8.1 自定义异常处理8.2 提升Redis的健壮性 9. 总结 &#x1f389;欢迎来到Java学习路线专栏~探索Java中的静态变量与实例变量 ☆* o(≧▽≦)o *☆嗨…...

使用difflib实现文件差异比较用html显示

1.默认方式&#xff0c;其中加入文本过长&#xff0c;需要换行&#xff0c;因此做 contenthtml_output.replace(</style>,table.diff td {word-wrap: break-word;white-space: pre-wrap;max-width: 100%;}</style>)&#xff0c;添加换行操作 ps&#xff1a;当前te…...

【文末附gpt升级秘笈】AI热潮降温与AGI场景普及的局限性

AI热潮降温与AGI场景普及的局限性 摘要&#xff1a; 随着人工智能&#xff08;AI&#xff09;技术的迅猛发展&#xff0c;AI热一度席卷全球&#xff0c;引发了广泛的关注和讨论。然而&#xff0c;近期一些学者和行业专家对AI的发展前景提出了质疑&#xff0c;认为AI热潮将逐渐…...

Vue待学习

整个渲染过程了解 Vue实例&#xff1f;Vue模板&#xff1f;渲染函数render&#xff08;&#xff09;&#xff1f;虚拟DOM VNode?模板编译器&#xff1f;diff算法 CSS相关 CSS高级学习&#xff1f;过渡&#xff1f; 待熟悉掌握 Vue-router?VueX&#xff1f;Vue-Cli、Webpack和…...

TOP150-LC88

/*给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2&#xff0c;另有两个整数 m 和 n &#xff0c;分别表示 nums1 和 nums2 中的元素数目。请你 合并 nums2 到 nums1 中&#xff0c;使合并后的数组同样按 非递减顺序 排列。注意&#xff1a;最终&#xff0c;合并后数组不…...

使用Python和TCN进行时间序列预测:一个完整的实战示例

使用Python和TCN进行时间序列预测&#xff1a;一个完整的实战示例 时间卷积网络&#xff08;TCN&#xff09;已被证明在处理序列数据方面表现出色&#xff0c;尤其是在需要捕获长期依赖关系的任务中。在本文中&#xff0c;我们将通过一个简单的例子&#xff0c;展示如何使用Py…...

如何用R语言ggplot2画高水平期刊散点图

文章目录 前言一、数据集二、ggplot2画图1、全部代码2、细节拆分1&#xff09;导包2&#xff09;创建图形对象3&#xff09;主题设置4&#xff09;轴设置5&#xff09;图例设置6&#xff09;散点颜色7&#xff09;保存图片 前言 一、数据集 数据下载链接见文章顶部 处理前的数据…...

Python基于 Jupyter Notebook 的图形可视化工具库之ipysigma使用详解

概要 在数据科学和网络分析中,图(Graph)结构是一种常用的数据结构,用于表示实体及其关系。为了方便图数据的可视化和交互操作,ipysigma 提供了一个基于 Jupyter Notebook 的图形可视化工具。通过 ipysigma,用户可以在 Jupyter Notebook 中创建、编辑和展示图结构,方便进…...

四叉树和KD树

1. 简介 四叉树和KD树都是用于空间数据索引和检索的树状数据结构。它们通过将空间递归地划分为更小的区域&#xff0c;并存储每个区域内的点&#xff0c;来实现快速搜索和范围查询。 2. 四叉树 2.1 定义 四叉树是一种树状数据结构&#xff0c;它将二维空间递归地划分为四个…...

C语言中结构体使用.与->访问成员变量的区别

文章目录 前言点运算符&#xff08;.&#xff09;箭头运算符&#xff08;->&#xff09;总结 前言 在C语言中&#xff0c;. 和 -> 都是用来访问结构体成员的运算符&#xff0c;但它们的使用场景和含义有所不同。 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面…...

计算机二级Access选择题考点

在Access中&#xff0c;若要使用一个字段保存多个图像、图表、文档等文件&#xff0c;应该设置的数据类型是附件。在“销售表"中有字段:单价、数量、折扣和金额。其中&#xff0c;金额单价x数量x折扣&#xff0c;在建表时应将字段"金额"的数据类型定义为计算。若…...

LeetCode - 394. 字符串解码

题目 394. 字符串解码 - 力扣&#xff08;LeetCode&#xff09; 思路 使用两个栈&#xff1a;一个存储重复次数&#xff0c;一个存储字符串 遍历输入字符串&#xff1a; 数字处理&#xff1a;遇到数字时&#xff0c;累积计算重复次数左括号处理&#xff1a;保存当前状态&a…...

定时器任务——若依源码分析

分析util包下面的工具类schedule utils&#xff1a; ScheduleUtils 是若依中用于与 Quartz 框架交互的工具类&#xff0c;封装了定时任务的 创建、更新、暂停、删除等核心逻辑。 createScheduleJob createScheduleJob 用于将任务注册到 Quartz&#xff0c;先构建任务的 JobD…...

屋顶变身“发电站” ,中天合创屋面分布式光伏发电项目顺利并网!

5月28日&#xff0c;中天合创屋面分布式光伏发电项目顺利并网发电&#xff0c;该项目位于内蒙古自治区鄂尔多斯市乌审旗&#xff0c;项目利用中天合创聚乙烯、聚丙烯仓库屋面作为场地建设光伏电站&#xff0c;总装机容量为9.96MWp。 项目投运后&#xff0c;每年可节约标煤3670…...

css的定位(position)详解:相对定位 绝对定位 固定定位

在 CSS 中&#xff0c;元素的定位通过 position 属性控制&#xff0c;共有 5 种定位模式&#xff1a;static&#xff08;静态定位&#xff09;、relative&#xff08;相对定位&#xff09;、absolute&#xff08;绝对定位&#xff09;、fixed&#xff08;固定定位&#xff09;和…...

相机Camera日志分析之三十一:高通Camx HAL十种流程基础分析关键字汇总(后续持续更新中)

【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了:有对最普通的场景进行各个日志注释讲解,但相机场景太多,日志差异也巨大。后面将展示各种场景下的日志。 通过notepad++打开场景下的日志,通过下列分类关键字搜索,即可清晰的分析不同场景的相机运行流程差异…...

Unity | AmplifyShaderEditor插件基础(第七集:平面波动shader)

目录 一、&#x1f44b;&#x1f3fb;前言 二、&#x1f608;sinx波动的基本原理 三、&#x1f608;波动起来 1.sinx节点介绍 2.vertexPosition 3.集成Vector3 a.节点Append b.连起来 4.波动起来 a.波动的原理 b.时间节点 c.sinx的处理 四、&#x1f30a;波动优化…...

20个超级好用的 CSS 动画库

分享 20 个最佳 CSS 动画库。 它们中的大多数将生成纯 CSS 代码&#xff0c;而不需要任何外部库。 1.Animate.css 一个开箱即用型的跨浏览器动画库&#xff0c;可供你在项目中使用。 2.Magic Animations CSS3 一组简单的动画&#xff0c;可以包含在你的网页或应用项目中。 3.An…...

Chrome 浏览器前端与客户端双向通信实战

Chrome 前端&#xff08;即页面 JS / Web UI&#xff09;与客户端&#xff08;C 后端&#xff09;的交互机制&#xff0c;是 Chromium 架构中非常核心的一环。下面我将按常见场景&#xff0c;从通道、流程、技术栈几个角度做一套完整的分析&#xff0c;特别适合你这种在分析和改…...

【深度学习新浪潮】什么是credit assignment problem?

Credit Assignment Problem(信用分配问题) 是机器学习,尤其是强化学习(RL)中的核心挑战之一,指的是如何将最终的奖励或惩罚准确地分配给导致该结果的各个中间动作或决策。在序列决策任务中,智能体执行一系列动作后获得一个最终奖励,但每个动作对最终结果的贡献程度往往…...

Python常用模块:time、os、shutil与flask初探

一、Flask初探 & PyCharm终端配置 目的: 快速搭建小型Web服务器以提供数据。 工具: 第三方Web框架 Flask (需 pip install flask 安装)。 安装 Flask: 建议: 使用 PyCharm 内置的 Terminal (模拟命令行) 进行安装,避免频繁切换。 PyCharm Terminal 配置建议: 打开 Py…...