浏览器实时播放摄像头数据并通过 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>

总结

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

请添加图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用 Selenium 保持登录会话信息

使用 Selenium 保持登录会话信息 在进行 Web 自动化测试时,保持登录会话信息是一个常见的需求。这不仅能节省每次测试时重复登录的时间,还能模拟实际用户行为,使测试更加真实可靠。在这篇博客中,我们将深入探讨如何使用 Selenium 在每次启动时保持原有的登录会话信息。 什…

汇编中标签的引用$符号

一个c/c开发人员&#xff0c;居然不会汇编&#xff0c;真是惭愧。趁着闲暇时间学习一下汇编&#xff0c;曲不离口&#xff0c;码不离手。看一个简单的例子&#xff1a; .section .datavalue:.quad 200.section .text .global main main:nopMOVL value, %eaxret 就这一条指令&…

计算机网络:网络层 - IPv4地址

计算机网络&#xff1a;网络层 - IPv4地址 分类编址划分子网子网掩码 无分类编址 CIDRCIDR 地址块构造超网 在酒店中&#xff0c;每个房间都有门牌号码&#xff0c;服务员送餐时&#xff0c;就可以根据门牌号码来判断一份餐要送到那个房间。 在网络中也是如此&#xff0c;一份…

vue实现页面打印的四种方法

vue实现页面打印的四种方法 一、原始window.print()二、指定区域的打印三、生成 iframe 然后打印(推荐)四、使用第三方库 print.js 一、原始window.print() 优点:便捷打印缺点:不可打印指定的区域 //打印按钮<el-button class"printBox" type"primary"…

Django的‘通用视图TemplateView’

使用通用视图的好处是&#xff1a;如果有一个html需要展示&#xff0c;不需要写view视图函数&#xff0c;直接写好url即可。 使用通用视图的步骤如下&#xff1a; 1、编辑项目urls.py文件 from django.views.generic import TemplateView 在该文件的映射表中添加&#xff1a…

订单排队模式 :强复购,无库存担忧

库存积压&#xff0c;意味着资金的束缚和机会的错失&#xff1b;库存不足&#xff0c;又可能导致客户流失和市场机会的丧失。订单排队模式的核心理念是通过排队出局奖励、直推优先和代理商等机制&#xff0c;激发消费者的购买热情&#xff0c;同时确保库存的流动性和销售的增长…

八字综合测算网整站源码程序/黄历/灵签/排盘/算命/生肖星座/日历网/周公解梦

八字综合测算网整站源码程序/黄历/灵签/排盘/算命/生肖星座/日历网/周公解梦 演示地址&#xff1a; https://s24.gvyun.com/ 手机端地址&#xff1a; https://ms24.gvyun.com/ 网站功能分类&#xff1a; 八字&#xff1a;八字测算&#xff1b;日干论命&#xff1b;称骨论命…

网络框架netpoll中的SO_ZEROCOPY

背景了解 https://www.163.com/dy/article/FS6AS7SS0518R7MO.html https://docs.kernel.org/networking/msg_zerocopy.html send() with MSG_ZEROCOPY kernel v4.14 版本接受了来自 Google 工程师 Willem de Bruijn 在 TCP 网络报文的通用发送接口 send() 中实现的 zero-cop…

Vue配置项之el

el 首先说明一下&#xff0c;本人是前端小学生级别的菜鸡&#xff0c;吐槽的话请口下留情&#xff0c;在评论区指出错误或者补充不足&#xff0c;我会很喜欢&#xff0c;互喷不会进步&#xff0c;相互指点才会。。。。谢谢大家啦 目录 el 目录示例原理 &#x1f4cc;Vue.…

与君共勉:坚持+努力

你若学不进去、玩不尽兴、睡不踏实、心情不爽、浑身不对劲却又食欲旺盛&#xff1b; 没有扎实基础却总犹豫不决&#xff1b; 渴望出类拔萃却难以脚踏实地&#xff1b; 看见别人勤奋就焦躁不安&#xff1b; 到自己行动时却总是明天再说。 要知道在一无所有的年纪&#xff0…

ERP管理系统解决方案(附ERP流程和详细解决方法)

ERP 是专门为制造企业设计的综合性管理解决方案&#xff0c;旨在优化制造业务流程&#xff0c;整合各个部门和环节&#xff0c;实现生产、供应链、质量控制和销售等方面的高效协同。 传统的制造行业会面临哪些业务痛点&#xff0c;会考虑erp解决方案&#xff1a; 生产成本高昂…

LeetCode452用最少数量的箭引爆气球

题目描述 有一些球形气球贴在一堵用 XY 平面表示的墙面上。墙面上的气球记录在整数数组 points &#xff0c;其中points[i] [xstart, xend] 表示水平直径在 xstart 和 xend之间的气球。你不知道气球的确切 y 坐标。一支弓箭可以沿着 x 轴从不同点 完全垂直 地射出。在坐标 x 处…

华为数据驱动的企业数字化转型之路

华为数据驱动的企业数字化转型之路 数据驱动的数字化转型是企业未来发展的关键。通过构建完善的数据治理体系&#xff0c;包括差异化的数据管理、面向业务的信息架构、数据底座建设和自助数据服务&#xff0c;企业可以提升数据的利用效率和决策能力。本文将根据华为数据治理相…

Could not initialize class sun.awt.X11FontManager如何解决?

Handler dispatch failed; nested exception is java.lang.NoClassDefFoundError: Could not initialize class sun.awt.X11FontManager这个错误信息指出了一个嵌套异常 java.lang.NoClassDefFoundError&#xff0c;并且无法初始化类 sun.awt.X11FontManager。这个问题通常与 J…

Idea多线程调试

在 IntelliJ IDEA 中调试多线程应用程序可能会有些复杂&#xff0c;因为多个线程可能会同时运行和交互。不过&#xff0c;IDEA 提供了一些强大的工具来帮助你进行多线程调试。以下是一些关键步骤和技巧&#xff0c;帮助你有效地调试多线程应用程序&#xff1a; 创建一个示例多线…

没有废话-MySQL,MyBatis 动态参数添加序号值(默认递增或根据内容进行递增)

创建数据 创建表 CREATE TABLE aml_inst_risk_assess_category (id int(11) NOT NULL AUTO_INCREMENT COMMENT ID,dept_id int(11) DEFAULT NULL COMMENT 机构id,dept_name varchar(30) DEFAULT NULL COMMENT 机构名称…

《精通ChatGPT:从入门到大师的Prompt指南》附录C:专业术语表

附录C&#xff1a;专业术语表 本附录旨在为读者提供一本全面的术语表&#xff0c;帮助理解《精通ChatGPT&#xff1a;从入门到大师的Prompt指南》中涉及的各种专业术语。无论是初学者还是高级用户&#xff0c;这些术语的定义和解释将为您在使用ChatGPT时提供重要参考。 A AI&…

Linux中Web服务器配置和管理(Apache)

文章目录 一、WEB服务器介绍1.1、WEB服务器概述1.2、WEB服务器的发展历史1.3、WEB服务器的优点与缺点1.4、WEB服务器的工作流程 二、Apache介绍2.1、Apache是什么2.2、Apache的发展史与应用场景2.3、Apache的特点2.4、Apache的工作原理2.5、Apache的模块 三、安装使用Apache服务…

调用百度API实现图像多主体检测

目录 1. 作者介绍2&#xff0e;百度API介绍与获取2.1 API介绍2.2 注册账号并获取API Key 3&#xff0e;完整实验代码&#xff0c;测试结果3.1 调用API3.2框出主体部分&#xff0c;并标注标签和置信度3.3 测试结果 1. 作者介绍 邓富贵&#xff0c;男&#xff0c;西安工程大学电…

【动态规划】| 详解路径问题之地下城游戏 力扣174 (困难题)

&#x1f397;️ 主页&#xff1a;小夜时雨 &#x1f397;️专栏&#xff1a;动态规划 &#x1f397;️如何活着&#xff0c;是我找寻的方向 目录 1. 题目解析2. 代码 1. 题目解析 题目链接: https://leetcode.cn/problems/minimum-path-sum/description/ 建议先看一下前面…