
随着摄像头的不断改进,实时物体检测功能越来越受到人们的青睐。从自动驾驶汽车、智能监控系统到增强现实应用,这项技术被广泛应用于各种场合。
计算机视觉是利用摄像头和计算机来执行上述操作的技术的高级术语,是一个庞大而复杂的领域。不过,你可能不知道,你可以在浏览器中轻松地开始实时物体检测。
本文将介绍如何使用 构建实时对象检测应用程序并将其部署到服务器。实时对象检测应用程序利用了用户的 *** 摄像头反馈。
以下是本指南中使用的关键技术的细分:
npm create vite@latest kinsta-object-detection --template react
这将使用 vite 为您搭建一个基线 React 项目。
npm i @tensorflow-models/coco-ssd @tensorflow/tfjs
现在,您可以开始开发应用程序了。
在编写对象检测逻辑代码之前,让我们先了解一下本指南中的开发内容。下面是应用程序的用户界面:

应用程序的用户界面设计
当用户点击 “Start Webcam” 按钮时,系统会提示用户授予应用程序访问 *** 摄像头画面的权限。权限授予后,应用程序开始显示 *** 摄像头画面,并检测画面中的物体。然后,该程序会渲染一个方框,在实时画面上显示检测到的对象,并添加一个标签。
首先,在 App.jsx 文件中粘贴以下代码,创建应用程序的用户界面:
import ObjectDetection from './ObjectDetection';
function App() {
return (
<div className="app">
<h1>Image Object Detection</h1>
<ObjectDetection />
</div>
);
}
export default App;
该代码段指定了页面的页眉,并导入了一个名为 ObjectDetection 的自定义组件。该组件包含捕捉 *** 摄像头画面和实时检测对象的逻辑。
要创建该组件,请在 src 目录中新建一个名为 ObjectDetection.jsx 的文件,并粘贴以下代码:
import { useEffect, useRef, useState } from 'react';
const ObjectDetection = () => {
const videoRef = useRef(null);
const [isWebcamStarted, setIsWebcamStarted] = useState(false)
const startWebcam = async () => {
// TODO
};
const stopWebcam = () => {
// TODO
};
return (
<div className="object-detection">
<div className="buttons">
<button onClick={isWebcamStarted ? stopWebcam : startWebcam}>{isWebcamStarted ? "Stop" : "Start"} Webcam</button>
</div>
<div className="feed">
{isWebcamStarted ? <video ref={videoRef} autoPlay muted /> : <div />}
</div>
</div>
);
};
export default ObjectDetection;
上面的代码定义了一个 结构,其中包含一个用于启动和停止 *** 摄像头馈送的按钮和一个 <video> 元素,一旦 *** 摄像头馈送激活,该元素将用于向用户显示 *** 摄像头馈送。状态容器 isWebcamStarted 用于存储 *** 摄像头的状态。startWebcam 和 stopWebcam 这两个函数用于启动和停止 *** 摄像头馈送。让我们来定义它们:
以下是 startWebcam 函数的代码:
const startWebcam = async () => {
try {
setIsWebcamStarted(true)
const stream = await navigator.mediaDevices.getUserMedia({ video: true });
if (videoRef.current) {
videoRef.current.srcObject = stream;
}
} catch (error) {
setIsWebcamStarted(false)
console.error('Error accessing webcam:', error);
}
};
该函数负责请求用户授予 *** 摄像头访问权限,一旦授予权限,它就会设置 <video> 以向用户显示实时 *** 摄像头馈送。
如果代码无法访问 *** 摄像头(可能是由于当前设备上没有 *** 摄像头或用户被拒绝),函数将向控制台打印一条信息。您可以使用错误块向用户显示失败的原因。
接下来,用以下代码替换 stopWebcam 函数:
const stopWebcam = () => {
const video = videoRef.current;
if (video) {
const stream = video.srcObject;
const tracks = stream.getTracks();
tracks.forEach((track) => {
track.stop();
});
video.srcObject = null;
setPredictions([])
setIsWebcamStarted(false)
}
};
这段代码会检查 <video> 对象访问的正在运行的视频流轨迹,并停止每个轨迹。最后,它会将 isWebcamStarted 状态设置为 false。
此时,请尝试运行应用程序,检查是否可以访问和查看 *** 摄像头画面。
确保将以下代码粘贴到 index.css 文件中,以确保应用程序的外观与您之前看到的预览效果相同:
#root {
font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
line-height: 1.5;
font-weight: 400;
color-scheme: light dark;
color: rgba(255, 255, 255, 0.87);
background-color: #242424;
min-width: 100vw;
min-height: 100vh;
font-synthesis: none;
text-rendering: optimizeLegibility;
-webkit-font- *** oothing: antialiased;
-moz-osx-font- *** oothing: grayscale;
}
a {
font-weight: 500;
color: #646cff;
text-decoration: inherit;
}
a:hover {
color: #535bf2;
}
body {
margin: 0;
display: flex;
place-items: center;
min-width: 100vw;
min-height: 100vh;
}
h1 {
font-size: 3.2em;
line-height: 1.1;
}
button {
border-radius: 8px;
border: 1px solid transparent;
padding: 0.6em 1.2em;
font-size: 1em;
font-weight: 500;
font-family: inherit;
background-color: #1a1a1a;
cursor: pointer;
transition: border-color 0.25s;
}
button:hover {
border-color: #646cff;
}
button:focus,
button:focus-visible {
outline: 4px auto -webkit-focus-ring-color;
}
@media (prefers-color-scheme: light) {
:root {
color: #213547;
background-color: #ffffff;
}
a:hover {
color: #747bff;
}
button {
background-color: #f9f9f9;
}
}
.app {
width: 100%;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}
.object-detection {
width: 100%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
.buttons {
width: 100%;
display: flex;
justify-content: center;
align-items: center;
flex-direction: row;
button {
margin: 2px;
}
}
div {
margin: 4px;
}
}
此外,请删除 App.css 文件,以免弄乱组件的样式。现在,您可以编写在应用程序中集成实时对象检测的逻辑了。
import * as cocoSsd from '@tensorflow-models/coco-ssd'; import '@tensorflow/tfjs';
ObjectDetection 组件中创建一个状态,用于存储 Coco SSD 模型生成的预测数组: const [predictions, setPredictions] = useState([]);
const predictObject = async () => {
const model = await cocoSsd.load();
model.detect(videoRef.current).then((predictions) => {
setPredictions(predictions);
})
.catch(err => {
console.error(err)
});
}; 该函数使用视频源,对视频源中出现的物体进行预测。它将为您提供一个预测对象数组,每个对象都包含一个标签、一个置信度百分比和一组显示该对象在视频帧中位置的坐标。
您需要不断调用该函数来处理不断出现的视频帧,然后使用存储在 predictions 状态中的预测结果在实时视频画面中为每个已识别的对象显示方框和标签。
setInterval 函数连续调用该函数。您还必须在用户停止 *** 摄像头馈送后停止调用该函数。为此,请使用 JavaScript 中的 clearInterval 函数。在 ObjectDetection 组件中添加以下状态容器和 useEffect 钩子,以设置在启用 *** 摄像头时持续调用 predictObject 函数,并在禁用 *** 摄像头时移除该函数: const [detectionInterval, setDetectionInterval] = useState()
useEffect(() => {
if (isWebcamStarted) {
setDetectionInterval(setInterval(predictObject, 500))
} else {
if (detectionInterval) {
clearInterval(detectionInterval)
setDetectionInterval(null)
}
}
}, [isWebcamStarted]) 这将使应用程序每 500 毫秒检测 *** 摄像头前的物体。您可以根据自己对物体检测速度的要求来改变这个值,但要注意,如果检测频率过高,可能会导致应用程序占用浏览器的大量内存。
prediction 状态容器中获得了预测数据,可以用它在实时视频源中的对象周围显示标签和方框。为此,请更新 ObjectDetection 的 return 语句,使其返回如下内容: return (
<div className="object-detection">
<div className="buttons">
<button onClick={isWebcamStarted ? stopWebcam : startWebcam}>{isWebcamStarted ? "Stop" : "Start"} Webcam</button>
</div>
<div className="feed">
{isWebcamStarted ? <video ref={videoRef} autoPlay muted /> : <div />}
{/* Add the tags below to show a label using the p element and a box using the div element */}
{predictions.length > 0 && (
predictions.map(prediction => {
return <>
<p style={{
left: `${prediction.bbox[0]}px`,
top: `${prediction.bbox[1]}px`,
width: `${prediction.bbox[2] - 100}px`
}}>{prediction.class + ' - with '
+ Math.round(parseFloat(prediction.score) * 100)
+ '% confidence.'}</p>
<div className={"marker"} style={{
left: `${prediction.bbox[0]}px`,
top: `${prediction.bbox[1]}px`,
width: `${prediction.bbox[2]}px`,
height: `${prediction.bbox[3]}px`
}} />
</>
})
)}
</div>
{/* Add the tags below to show a list of predictions to user */}
{predictions.length > 0 && (
<div>
<h3>Predictions:</h3>
<ul>
{predictions.map((prediction, index) => (
<li key={index}>
{`${prediction.class} (${(prediction.score * 100).toFixed(2)}%)`}
</li>
))}
</ul>
</div>
)}
</div>
); 这将在 *** 摄像头画面的右下方显示预测列表,并使用 Coco SSD 提供的坐标在预测对象周围绘制一个方框,同时在方框顶部添加一个标签。
.feed {
position: relative;
p {
position: absolute;
padding: 5px;
background-color: rgba(255, 111, 0, 0.85);
color: #FFF;
border: 1px dashed rgba(255, 255, 255, 0.7);
z-index: 2;
font-size: 12px;
margin: 0;
}
.marker {
background: rgba(0, 255, 0, 0.25);
border: 1px dashed #fff;
z-index: 1;
position: absolute;
}
} 至此,应用程序开发完成。现在可以重新启动开发服务器来测试应用程序。下面是应用程序完成后的样子:

使用 *** 摄像头实时检测物体的演示。
您可以在此 中找到完整代码。
最后一步是将应用程序部署到服务器(以 为例),让用户可以使用。
Git 仓库准备就绪后,请按照以下步骤将对象检测应用程序部署到 Kinsta:
yarn build 或 npm run build20.2.0 dist 应用程序部署完成后,您可以从仪表板单击 Visit Site 来访问应用程序。现在,您可以尝试在装有摄像头的各种设备上运行该应用程序,看看它的性能如何。
您已经使用 React 和 TensorFlow.js 成功构建了一个实时对象检测应用程序。这将使您能够探索令人兴奋的计算机视觉世界,并直接在用户浏览器中创建交互式体验。
请记住,我们使用的 Coco SSD 模型只是一个起点。通过进一步探索,您可以使用 TensorFlow.js 深入研究自定义对象检测,从而定制应用程序以识别与您的需求相关的特定对象。
Linux面板环境安装,主要支持LNMP和LAMP、Tomcat、node.js。不过对于大部分站长来说,主要是LNMP和LAMP两个环境的安装。 LNMP和LAMP两个环境的最大区别是,前者采用Nginx作为Web服务器,后者则采用Apache作为Web服务器。(选择哪个作为您的Web服务器,可...
本章节主要是对宝塔面板的主界面的各个版本进行一个简单的说明。 宝塔面板主界面主要包括:服务器操作系统、服务器状态、站点信息、软件管理及网络流量几个部分。 Windows面板有部分功能未实现,其余部分与Linux面板同步。 系统操作...
经过几个小时的努力工作后,您是否感到眼睛疲劳或难以阅读代码?许多程序员在开始头疼之前从没想过要切换字体。 如果您经常发现在尝试扫描一千行代码时眼睛模糊不清,或者在停止编码数小时后头疼,那么可能是时候尝试一种新字体了。即使您没有遇到这些症状,设计良好的字体通常也比默认系统字体具有更好的可读性。...
Node.js和PHP是Web开发工作中常用的两种基本Web技术。两者都为服务器端开发做出了贡献,Node.js甚至同时服务于客户端和服务器端开发。 PHP已经为开发人员服务了近3年,现在它为78%的网络提供支持。相比之下,Node.js相对较新,但扩展速度非常快,由于其全栈开发能力而成为流行...
近年来,Web应用程序和网站的开发变得越来越简单。即使是我们当中最受技术挑战的人也已经相当熟练地使用WordPress和Wix等产品。 对于更高级的开发人员,有许多工具可以帮助简化开发过程。这些工具中最有用的工具之一是Laravel。 本文回答了“什么是Laravel?”这个问题。通过将其分...
市场上有各种各样的数据库可供选择,用户通常可以仔细考虑PostgreSQL与SQL Server,以便为他们的用例找出更好的选择。使用PostgreSQL进行运营的组织可能希望切换到像Microsoft SQL Server这样的数据库,因为它主要迎合不同的数据仓库解决方案、电子商务和其他业务线...