当前位置: 首页 > 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;在建表时应将字段"金额"的数据类型定义为计算。若…...

【SpringBoot】100、SpringBoot中使用自定义注解+AOP实现参数自动解密

在实际项目中,用户注册、登录、修改密码等操作,都涉及到参数传输安全问题。所以我们需要在前端对账户、密码等敏感信息加密传输,在后端接收到数据后能自动解密。 1、引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId...

1688商品列表API与其他数据源的对接思路

将1688商品列表API与其他数据源对接时&#xff0c;需结合业务场景设计数据流转链路&#xff0c;重点关注数据格式兼容性、接口调用频率控制及数据一致性维护。以下是具体对接思路及关键技术点&#xff1a; 一、核心对接场景与目标 商品数据同步 场景&#xff1a;将1688商品信息…...

AI,如何重构理解、匹配与决策?

AI 时代&#xff0c;我们如何理解消费&#xff1f; 作者&#xff5c;王彬 封面&#xff5c;Unplash 人们通过信息理解世界。 曾几何时&#xff0c;PC 与移动互联网重塑了人们的购物路径&#xff1a;信息变得唾手可得&#xff0c;商品决策变得高度依赖内容。 但 AI 时代的来…...

R语言速释制剂QBD解决方案之三

本文是《Quality by Design for ANDAs: An Example for Immediate-Release Dosage Forms》第一个处方的R语言解决方案。 第一个处方研究评估原料药粒径分布、MCC/Lactose比例、崩解剂用量对制剂CQAs的影响。 第二处方研究用于理解颗粒外加硬脂酸镁和滑石粉对片剂质量和可生产…...

【JVM面试篇】高频八股汇总——类加载和类加载器

目录 1. 讲一下类加载过程&#xff1f; 2. Java创建对象的过程&#xff1f; 3. 对象的生命周期&#xff1f; 4. 类加载器有哪些&#xff1f; 5. 双亲委派模型的作用&#xff08;好处&#xff09;&#xff1f; 6. 讲一下类的加载和双亲委派原则&#xff1f; 7. 双亲委派模…...

【Nginx】使用 Nginx+Lua 实现基于 IP 的访问频率限制

使用 NginxLua 实现基于 IP 的访问频率限制 在高并发场景下&#xff0c;限制某个 IP 的访问频率是非常重要的&#xff0c;可以有效防止恶意攻击或错误配置导致的服务宕机。以下是一个详细的实现方案&#xff0c;使用 Nginx 和 Lua 脚本结合 Redis 来实现基于 IP 的访问频率限制…...

STM32HAL库USART源代码解析及应用

STM32HAL库USART源代码解析 前言STM32CubeIDE配置串口USART和UART的选择使用模式参数设置GPIO配置DMA配置中断配置硬件流控制使能生成代码解析和使用方法串口初始化__UART_HandleTypeDef结构体浅析HAL库代码实际使用方法使用轮询方式发送使用轮询方式接收使用中断方式发送使用中…...

MySQL 部分重点知识篇

一、数据库对象 1. 主键 定义 &#xff1a;主键是用于唯一标识表中每一行记录的字段或字段组合。它具有唯一性和非空性特点。 作用 &#xff1a;确保数据的完整性&#xff0c;便于数据的查询和管理。 示例 &#xff1a;在学生信息表中&#xff0c;学号可以作为主键&#xff…...

ubuntu22.04有线网络无法连接,图标也没了

今天突然无法有线网络无法连接任何设备&#xff0c;并且图标都没了 错误案例 往上一顿搜索&#xff0c;试了很多博客都不行&#xff0c;比如 Ubuntu22.04右上角网络图标消失 最后解决的办法 下载网卡驱动&#xff0c;重新安装 操作步骤 查看自己网卡的型号 lspci | gre…...

大数据治理的常见方式

大数据治理的常见方式 大数据治理是确保数据质量、安全性和可用性的系统性方法&#xff0c;以下是几种常见的治理方式&#xff1a; 1. 数据质量管理 核心方法&#xff1a; 数据校验&#xff1a;建立数据校验规则&#xff08;格式、范围、一致性等&#xff09;数据清洗&…...