摄像头实时检查程序,插入设备,自动显示画面,支持多个摄像头,支持拍照,照片放大缩小

支持的特性

  • 插入摄像头设备后,无需手动选择,自动显示摄像头画面,需要预先授权
  • 支持多个摄像头切换显示
  • 多个摄像头时支持 默认显示特定名称的摄像头
  • 支持拍照
  • 支持照片放大,缩小

显示效果

在这里插入图片描述
在这里插入图片描述

完整代码

<!DOCTYPE html>
<html lang="zh"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>摄像头实时检测,拍照</title><style type="text/css">body {text-align: center;}.flex {display: flex;flex-direction: row;/* align-items: center; */justify-content: center;}.hidden {display: none;}</style></head><body><h1>摄像头实时检测</h1><div class="flex"><div><video id="videoElement" autoplay playsinline controls></video><p><label for="videoSource">选择摄像头:</label><select id="videoSource"></select><span class="hidden" id="closeCamera" onclick="stopVideoStream()">关闭摄像头</span><span id="cameraStatus">摄像头状态:未连接或已被占用</span><button id="captureButton" onclick="takePicture()">拍照</button></p></div><div style="margin-left: 20px"><div style="border: 1px solid #ddd; box-sizing: content-box"><canvas id="paperCanvas" width="640px" height="480px"></canvas></div></div></div><script src="./paper-full.min.js"></script><script>const video = document.getElementById("videoElement");const cameraStatus = document.getElementById("cameraStatus");const captureButton = document.getElementById("captureButton");const videoSelect = document.getElementById("videoSource");let mediaStream;let raster;function gotDevices(deviceInfos) {videoSelect.value = "";videoSelect.innerHTML = "";for (let i = 0; i !== deviceInfos.length; ++i) {const deviceInfo = deviceInfos[i];const option = document.createElement("option");option.value = deviceInfo.deviceId;if (deviceInfo.kind === "videoinput") {option.text = deviceInfo.label || "摄像头 " + (videoSelect.length + 1);videoSelect.appendChild(option);if (deviceInfo.label.includes("TOOCAA")) {videoSelect.value = deviceInfo.deviceId;}}}}function getStream() {if (window.stream) {window.stream.getTracks().forEach((track) => {track.stop();});}const constraints = {video: {deviceId: { exact: videoSelect.value },},};navigator.mediaDevices.getUserMedia(constraints).then(gotStream).catch(handleError);}function gotStream(stream) {window.stream = stream;video.srcObject = stream;cameraStatus.textContent = "摄像头状态:已连接";const videoTrack = stream.getVideoTracks()[0];const settings = videoTrack.getSettings();captureButton.style.display = "inline-block";console.log(settings);}function startVideoStream() {if (navigator.mediaDevices) {navigator.mediaDevices.getUserMedia({ video: true }).then(function (stream) {mediaStream = stream; // 保存媒体流以便后续操作video.srcObject = stream;cameraStatus.textContent = "摄像头状态:已连接";const videoTrack = stream.getVideoTracks()[0];const settings = videoTrack.getSettings();captureButton.style.display = "inline-block";console.log(settings);}).catch(function (error) {console.error("无法获取摄像头:", error);cameraStatus.textContent = "摄像头状态:未连接或已被占用";captureButton.style.display = "none";});}}function stopVideoStream() {if (mediaStream) {mediaStream.getTracks().forEach((track) => track.stop()); // 停止所有媒体轨道}video.srcObject = null; // 清除视频源cameraStatus.textContent = "摄像头状态:已断开";captureButton.style.display = "none";}function initPaperCanvas() {paper.setup("paperCanvas");paper.view.element.addEventListener("wheel", function (event) {event.preventDefault();// 计算缩放因子var delta = event.deltaY > 0 ? 0.9 : 1.1; // 向下滚动缩小视图,向上滚动放大视图// 鼠标位置相对于视图的当前坐标var mousePosition = new paper.Point(event.offsetX, event.offsetY);var viewPosition = paper.view.viewToProject(mousePosition);// 应用缩放paper.view.scale(delta, viewPosition);});// 鼠标拖动事件处理移动const tool = new paper.Tool();var lastPoint = null; // 上一次鼠标位置var dragging = false;var lastViewCenter;tool.onMouseDown = (event) => {lastPoint = event.point;dragging = true;};tool.onMouseDrag = (event) => {if (dragging && lastPoint) {lastViewCenter = paper.view.center;const delta = lastPoint.subtract(event.point);paper.view.center = paper.view.center.add(delta);lastPoint = event.point.add(paper.view.center.subtract(lastViewCenter));}};tool.onMouseUp = () => {// 结束拖动dragging = false;};}window.onload = () => {if (navigator.mediaDevices) {navigator.mediaDevices.enumerateDevices().then(gotDevices).then(getStream).catch(handleError);}videoSelect.onchange = getStream;// 监听媒体设备变化事件if (navigator.mediaDevices) {navigator.mediaDevices.addEventListener("devicechange", function (event) {// 尝试重新获取媒体流以检查摄像头是否仍然可用navigator.mediaDevices.getUserMedia({ video: true }).then(function () {navigator.mediaDevices.enumerateDevices().then(gotDevices).then(getStream).catch(handleError);// startVideoStream(); // 摄像头已连接,重新开始视频流}).catch(function () {stopVideoStream(); // 摄像头已断开,停止视频流并更新状态// destoryCanvas();});});}initPaperCanvas();};// 拍照功能function takePicture() {let canvas = document.createElement("canvas");canvas.width = video.videoWidth;canvas.height = video.videoHeight;const context = canvas.getContext("2d");context.drawImage(video, 0, 0, canvas.width, canvas.height);displayPictureOnPaper(canvas.toDataURL("image/png"));canvas = null;}function displayPictureOnPaper(imageData) {raster = new paper.Raster({source: imageData,position: paper.view.center,});}function destoryCanvas() {if (raster) {raster.remove();}}function handleError(error) {console.error("无法获取摄像头:", error);cameraStatus.textContent = "摄像头状态:未连接或已被占用";captureButton.style.display = "none";}</script></body>
</html>

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

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

相关文章

Spring Boot 有哪些优点?

Spring Boot 有哪些优点&#xff1f; &#x1f496;The Begin&#x1f496;点点关注&#xff0c;收藏不迷路&#x1f496; Spring Boot以其简洁和高效的特点&#xff0c;革新了Java应用的开发和部署方式。以下是其几大核心优势&#xff0c;让你一目了然&#xff1a; 减少时间成…

【舞动生命,营养护航】亨廷顿舞蹈症患者的维生素补给站

Hey小伙伴们~&#x1f44b; 在这个充满色彩的世界里&#xff0c;每个人都在以自己的方式绽放光彩。但你知道吗&#xff1f;有一群特别的朋友&#xff0c;他们面对着亨廷顿舞蹈症的挑战&#xff0c;却依然以不屈不挠的精神舞动着生命的旋律。&#x1f483;✨ 今天&#xff0c;就…

Windows下线程的竞争与资源保护(win32-API)

一、前言 在线程编程中&#xff0c;资源共享与保护是一个核心议题&#xff0c;尤其当多个线程试图同时访问同一份资源时&#xff0c;如果不采取适当的措施&#xff0c;就会引发一系列的问题&#xff0c;如数据不一致、竞态条件、死锁等。为了确保数据的一致性和线程安全&#…

数据结构(树、平衡树、红黑树)

目录 树 树的遍历方式 平衡二叉树 旋转机制 左旋 右旋 旋转实例 左左 左右 右右 右左 总结 红黑树 树 相关概念 节点的内部结构如下 二叉树与二叉查找树的定义如下 树的遍历方式 前序遍历&#xff1a;当前节点&#xff0c;左子节点&#xff0c;右子结点 中序遍…

Excel的使用总结1

目录 1、汇总公式&#xff1a;TEXTJOIN 2、excel中选择某个区域的方法 3、excel中如何在复制的时候&#xff0c;不将公式一起复制过去 4、想要自动填充某个区域的值的方法 1、汇总公式&#xff1a;TEXTJOIN TEXTJOIN 函数 - Microsoft 支持 例&#xff1a;TEXTJOIN("…

25 配置交换机网关

配置交换机网关 一、配置交换机默认网关 配置管理网关&#xff1a; Switch(config)#ip default-gateway 192.168.1.254二、配置交换机管理IP及默认网关练习 Route0&#xff1a; # 进入特权模式 Router>enable# 进入全局配置模式 Router#configure terminal # 进入f0/0口…

了解prolog规则

要推理先要有规则&#xff1b; 假设有一条规则&#xff0c; 如果X和Y是朋友&#xff0c;那么Y和X也是朋友&#xff1b; 这条规则写成这样&#xff0c; friend(X,Y) :- friend(Y, X). X和Y都是大写&#xff0c;表示这是两个变量&#xff1b;符号 :- 表示推理关系&…

【计算机网络】mini HTTP服务器框架与代码

注注注&#xff1a;本篇博文都是代码实现细节&#xff0c;但不会进行演示&#xff0c;演示看孪生篇 另外&#xff0c;由于tcp套接字部分本质都是套路&#xff0c;所以就不再进行赘述。 目录 1 请求反序列化2 读取url文件内容3 构建响应 1 请求反序列化 我们肯定会先收到请求&…

搜狐新闻HarmonyOS Push开发实践

本文字数&#xff1a;1795字 预计阅读时间&#xff1a;15分钟 01 背景 搜狐新闻作为HarmonyOS的合作伙伴&#xff0c;于2023年12月成功上架鸿蒙单框架应用市场&#xff0c;成为首批鸿蒙应用矩阵的一员。 推送作为新闻类应用的重要组成部分&#xff0c;我们将其纳入到二期功能开…

资本相信人形机器人

文&#xff5c;刘俊宏 编&#xff5c;王一粟 闷热的场馆里&#xff0c;兴奋的议论声&#xff0c;所有人生怕错过这场AI让机器人进化的盛宴。 人山人海的会展现场 光锥智能拍摄 8月21日&#xff0c;2024世界机器人大会&#xff08;WRC&#xff09;在北京开幕。在这场由169家…

vue3 element-plus el-table 多层级表头动态渲染。

效果图: html: <el-table :data"arrlist" border style"width: 100%"><template v-for"(i, index) in currentFieldData" :key"index"><el-table-column :label"i.label" :header-D"i.headerAlign&q…

TCP系列相关内容

一、TCP上传文件 loop——本地回环测试地址。 void *memset&#xff08;void *s,int c,size_t n&#xff09;——给一个变量设定一个值。 1、“粘包”问题 两次分别发送的数据&#xff0c;被一起接收形成该现象。 原因&#xff1a;TCP流式套接字&#xff0c;数据与数据间没…

分布式锁 redis与zookeeper

redis实现分布式锁 原理 基于redis命令setnx key value来实现分布式锁的功能&#xff0c;只有当key不存在时&#xff0c;setnx才可以设置成功并返回1&#xff0c;否则设置失败返回0。 方案1&#xff1a; 方案1存在的问题 假如在加锁成功&#xff0c;释放锁之前&#xff0c;…

飞书怎么关联任意两段话

最近开始用飞书记文档&#xff0c;体验实在是非常的丝滑&#xff0c;对我来说感觉没有找到更好的竞品了。废话不多说&#xff0c;接下来简单介绍一下怎么关联任意两段话吧。 首先说明&#xff0c;关联可以单向&#xff0c;也可以双向。 直接举例。 我想要将蓝字关联到最下面的…

自适应学习率(Datawhale X 李宏毅苹果书 AI夏令营)

传统的梯度下降方法在优化过程中常常面临学习率设置不当的问题。固定的学习率在训练初期可能过大&#xff0c;导致模型训练不稳定&#xff0c;而在后期可能过小&#xff0c;导致训练速度缓慢。为了克服这些问题&#xff0c;自适应学习率方法应运而生。这些方法通过动态调整学习…

微服务通信

目录 一、Feign远程调用 1、Feign简介 2、基本使用 二、Dubbo 1、基本简介 2、基础实现 一、Feign远程调用 先来看我们以前利用RestTemplate发起远程调用的代码&#xff1a; //通过restTemplate调用商品微服务String url "service-product";Product product …

proc文件的写操作机制

“一切皆是文件”。 Linux的基本哲学之一。它是指linux系统中的所有一切都可以通过文件的方式访问、管理&#xff0c;即便不是文件&#xff0c;也以文件的形式来管理。例如硬件设备、进程、套接字等都抽象成文件&#xff0c;使用统一的用户接口&#xff0c;虽然文件类型各不相同…

qt-内置图片遍历-Lambda按钮

内置图片遍历-Lambda按钮 知识点widget.hwidget.cppmain.cpp运行图 知识点 使用新的connect语法连接信号和槽 --Lambda 使用 connect(btn, &QToolButton::clicked, this, [this, btn,index]() { onToolButtonClicked(btn)}); // Lambda表达式中调用成员函数&#xff0c;并…

Springboot打包、部署

一、导入maven打包插件 <build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins> </build> 二、执行打包操作&#xff08;…

基于imx6ull平台opencv的图像采集和显示屏LCD显示功能(不带Qt界面)

目录 一、概述二、环境要求2.1 硬件环境2.2 软件环境 三、开发流程3.1 编写测试3.2 验证功能 一、概述 本文档是针对imx6ull平台opencv的图像采集和显示屏LCD显示功能&#xff0c;opencv通过摄像头采集视频图像&#xff0c;将采集的视频图像送给显示屏LCD进行显示。 测试结果…