js摄像头动态检测

利用摄像头每一秒截图一次图像。然后计算2次图像之间的相似度。

如果相似度低于98%就会报警。

var video = document.getElementsByClassName('inputvideo')[0];
video.innerHTML = "<video class='input_video' id='camera' autoplay width='640px' height='380px'></video>";const videoElement = document.getElementById('camera');// 获取用户媒体设备(摄像头)
navigator.mediaDevices.getUserMedia({ video: true }).then(function (stream) {videoElement.srcObject = stream;}).catch(function (error) {console.error('获取摄像头失败:', error);});var canvas = document.getElementsByClassName('outputcanvas')[0];
canvas.innerHTML = "<canvas class='output_canvas' width='640px' height='480px'></canvas>";var canvasElement = document.getElementsByClassName('output_canvas')[0];
var canvasCtx = canvasElement.getContext('2d');// 设置 canvas 尺寸与视频流尺寸一致
canvasElement.width = 64;
canvasElement.height = 64;
var last = 0function captureFrame() {// 捕获图像并绘制到画布canvasCtx.drawImage(videoElement, 0, 0, canvasElement.width, canvasElement.height);// 获取绘制后的图像数据const imageData = canvasCtx.getImageData(0, 0, canvasElement.width, canvasElement.height);// 压缩图像并将其绘制到目标画布上const compressedImageDataPromise = compressImgFromImageData(imageData);// 处理压缩后的图像数据compressedImageDataPromise.then(function (compressedData) {// 在这里可以使用 compressedData 进行进一步的操作,例如上传或显示在页面上// 清空画布canvasCtx.clearRect(0, 0, canvasElement.width, canvasElement.height);// 转换为灰度图像const grayscaleImageData = createGrayscale(compressedData);// 获取哈希指纹const hashFingerprint = getHashFingerprint(grayscaleImageData);// 判断 last 是否等于 hashFingerprintif (last !== 0) {if (last === hashFingerprint) {console.log('你没动');} else {// console.log('你动了' + last);// 计算汉明距离const distance = hammingDistance(last, hashFingerprint);// 计算相似度百分比const similarityPercentage = (1 - distance / (hashFingerprint.length * 2)) * 100;// console.log('汉明距离:', distance);const baifenbi=similarityPercentage.toFixed(2);console.log('相似度百分比:', baifenbi + '%');if (baifenbi<98){_funcCb (true, {param1: true})}_funcCb (true, {param2: baifenbi})}}last = hashFingerprint// console.log('哈希指纹:', hashFingerprint);// 在画布上绘制灰度图像canvasCtx.putImageData(grayscaleImageData, 0, 0);});
}// 每隔一段时间捕获一帧
setInterval(captureFrame, 1000); // 1 帧每秒// 定义压缩图像的函数
function compressImgFromImageData(imageData) {const canvas = document.createElement('canvas');const ctx = canvas.getContext('2d');const imgWidth = 64; // 设置压缩后的宽度canvas.width = imgWidth;canvas.height = imgWidth;// 将图像数据绘制到临时 canvas 上ctx.putImageData(imageData, 0, 0);// 获取压缩后的图像数据return new Promise((resolve, reject) => {const imgData = ctx.getImageData(0, 0, imgWidth, imgWidth);resolve(imgData);});
}// createGrayscale 函数已经在之前的代码中定义
// 根据 RGBA 数组生成 ImageData
function createImgData(dataDetail) {const canvas = document.createElement('canvas');const ctx = canvas.getContext('2d');const imgWidth = Math.sqrt(dataDetail.length / 4);const newImageData = ctx.createImageData(imgWidth, imgWidth);for (let i = 0; i < dataDetail.length; i += 4) {let R = dataDetail[i];let G = dataDetail[i + 1];let B = dataDetail[i + 2];let Alpha = dataDetail[i + 3];newImageData.data[i] = R;newImageData.data[i + 1] = G;newImageData.data[i + 2] = B;newImageData.data[i + 3] = Alpha;}return newImageData;
}// 创建灰度图像
function createGrayscale(imgData) {const newData = Array(imgData.data.length).fill(0);imgData.data.forEach((_data, index) => {if ((index + 1) % 4 === 0) {const R = imgData.data[index - 3];const G = imgData.data[index - 2];const B = imgData.data[index - 1];const gray = ~~((R + G + B) / 3);newData[index - 3] = gray;newData[index - 2] = gray;newData[index - 1] = gray;newData[index] = 255; // Alpha 值固定为255}});return createImgData(newData);
}// 获取图像的哈希指纹
function getHashFingerprint(imgData) {const grayList = imgData.data.reduce((pre, cur, index) => {if ((index + 1) % 4 === 0) {pre.push(imgData.data[index - 1]);}return pre;}, []);const length = grayList.length;const grayAverage = grayList.reduce((pre, next) => pre + next, 0) / length;return grayList.map(gray => (gray >= grayAverage ? 1 : 0)).join('');
}// 计算汉明距离
function hammingDistance(hash1, hash2) {if (hash1.length !== hash2.length) {throw new Error('Hashes must have the same length');}let distance = 0;for (let i = 0; i < hash1.length; i++) {if (hash1[i] !== hash2[i]) {distance++;}}return distance;
}

原理是看了有一篇文章

利用 JS 实现多种图片相似度算法

首先降低图片分辨率

然后使用指纹提取

在“平均哈希算法”中,若灰度图的某个像素的灰度值大于平均值,则视为1,否则为0。把这部分信息组合起来就是图片的指纹。由于我们已经拿到了灰度图的 ImageData 对象,要提取指纹也就变得很容易了:

最后用汉明距离计算相似度

摘一段维基百科关于“汉明距离”的描述:

在信息论中,两个等长字符串之间的汉明距离(英语:Hamming distance)是两个字符串对应位置的不同字符的个数。换句话说,它就是将一个字符串变换成另外一个字符串所需要替换的字符个数。

例如:

  • 1011101与1001001之间的汉明距离是2。
  • 2143896与2233796之间的汉明距离是3。
  • "toned"与"roses"之间的汉明距离是3。

体验地址

不许动 

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

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

相关文章

利用procrank和lsof定位出客户软件内存OOM的问题

最近遇到一些事情&#xff0c;觉得挺憋屈的&#xff0c;可是再憋屈总得往前走吧&#xff01;打工人&#xff0c;不好办啊&#xff01;事情是这样的&#xff0c;笔者在芯片原厂负责SDK和行业解决方案输出的&#xff0c;可以理解成整体SDK turnkey方案。但是有些客户多少还要改一…

CSS笔记(黑马程序员pink老师前端)圆角边框

圆角边框 border-radius:length; 效果显示 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Documen…

【Linux】网络编程网络基础(C++)

目录 一、计算机网络背景 二、认识 "协议" 三、网络协议初识 【3.1】协议分层 【3.2】OSI七层模型 【3.3】TCP/IP五层(或四层)模型 四、网络传输基本流程 【4.1】网络传输流程图 【4.2】数据包封装和分用 五、网络中的地址管理 一、计算机网络背景 【独立…

【周末闲谈】如何利用AIGC为我们创造有利价值?

个人主页&#xff1a;【&#x1f60a;个人主页】 系列专栏&#xff1a;【❤️周末闲谈】 系列目录 ✨第一周 二进制VS三进制 ✨第二周 文心一言&#xff0c;模仿还是超越&#xff1f; ✨第二周 畅想AR 文章目录 系列目录前言AIGCAI写作AI绘画AI视频生成AI语音合成 前言 在此之…

用Navicat备份Mysql演示系统数据库的时候出:Too Many Connections

今天用Navicat进行数据备份的时候&#xff0c;发现由于数据库连接数目过多导致连接锁定&#xff0c;这种情况在多人协同开发的场景中很常见。当然我这里也因为多个应用使用了数据库连接&#xff0c;所以出现了Too Many Connections。 可能是超过最大连接数了。 1、进入Navicat…

AUTOSARCAN-Tp协议

目录 一.单帧、首帧、连续帧、流控帧 单帧传输 SF单帧&#xff1a; 多帧传输 FF&#xff08;首帧&#xff09;&#xff1a; CF&#xff08;连续帧&#xff09;&#xff1a; FC&#xff08;流控帧&#xff09;&#xff1a; 一.单帧、首帧、连续帧、流控帧 CAN诊断由发送端…

MAC ITEM 解决cd: string not in pwd的问题

今天使用cd 粘贴复制的路径的时候,报了这么一个错. cd: string not in pwd eistert192 Library % cd Application Support cd: string not in pwd: Application eistert192 Library % 让人一脸懵逼. 对比一下,发现中文路径里的空格截断了路径 导致后面的路径就没有办法被包含…

视频汇聚/视频云存储/视频监控管理平台EasyCVR启动时打印starting server:listen tcp,该如何解决?

视频云存储/安防监控EasyCVR视频汇聚平台基于云边端智能协同&#xff0c;可实现视频监控直播、视频轮播、视频录像、云存储、回放与检索、智能告警、服务器集群、语音对讲、云台控制、电子地图、H.265自动转码H.264、平台级联等。为了便于用户二次开发、调用与集成&#xff0c;…

模糊测试面面观 | 模糊测试是如何发现异常情况的?

协议模糊测试是一种用于评估通信协议、文件格式和API实现系统安全性和稳定性的关键技术。在模糊测试过程中&#xff0c;监视器扮演着关键角色&#xff0c;它们能够捕获异常情况、错误响应、资源利用等&#xff0c;为测试人员提供有价值的信息&#xff0c;有助于发现潜在漏洞和问…

530. 二叉搜索树的最小绝对差

给你一个二叉搜索树的根节点 root &#xff0c;返回 树中任意两不同节点值之间的最小差值 。 差值是一个正数&#xff0c;其数值等于两值之差的绝对值。 示例 1&#xff1a; 输入&#xff1a;root [4,2,6,1,3] 输出&#xff1a;1示例 2&#xff1a; 输入&#xff1a;root [1,…

利用python进行视频下载并界面播放快速下载素材

工具&#xff1a;python designer&#xff08;python自带&#xff09;:UI界面设计工具 VLC&#xff1a;视频播放工具 需要的库如下&#xff1a; import os,platform os.environ[PYTHON_VLC_MODULE_PATH] "./vlc-3.0.14" import vlc from 脚本 import Player from …

使用IntelliJ IDEA本地启动调试Flink流计算工程的2个异常解决

记录&#xff1a;471 场景&#xff1a;使用IntelliJ IDEA本地启动调试Flink流计算时&#xff0c;报错一&#xff1a;加载DataStream报错java.lang.ClassNotFoundException。报错二&#xff1a;No ExecutorFactory found to execute the application。 版本&#xff1a;JDK 1.…