【PHP】控制摄像头缩放监控画面大小,并保存可视画面为图片

一、前言

功能描述

调用摄像头并可以控制缩放摄像头监控画面的大小,把可视画面保存为图片。

我使用的是USB摄像头,其他摄像头此方法应该也通用。

使用技术

使用到的技术比较简单,前端使用WebcamJS插件调用摄像头,并摄像头监控画面,使用CSS的transform属性来放大或缩小画面的大小。后端使用PHP的Imagick类库来缩放图片,最终保存图片到本地。

二、最终效果

Capture:保存可视区域图片;放大:放大可视区域画面;缩小:缩小可视区域画面;还原:还原可视区域画面。

三、业务逻辑说明

前端

① 调用摄像头:使用WebcamJS库调用摄像头,显示监控画面(注意:需要在https下才能使用此插件);

② 缩放画面:先初始可视区域的宽高,设置scale缩放比例,再使用CSS的transform属性来缩放画面大小(注意:transform属性只是在视觉上对图片进行了缩放,其实和图像的真实大小并不一致,因为我这里为了保持放大后的图像尺寸大小和原始图像尺寸大小在视觉上一致,所以我把多余的画面区域使用overflow隐藏了);

③ 数据传输后端:把图片数据和缩放比例传输给PHP后端进行处理。此时传输的图像数据是base64编码,尺寸大小并不是视觉上所看到的画面大小,这个需要在后端进行处理。

后端

① 接收前端传过来的数据(base64图片编码、缩放比例);

② 把接收的base64编码保存为图片到本地;

③ 对图片进行处理:使用Imagick类库对图像进行处理,前面说了前端传过来的图像尺寸并不是可视区域的尺寸,所以为了保存一致,需要对接收的原始图像进行缩放处理。需要两个步骤,先是根据放大比例计算并保存放大后的图片(是原始大小的图片,不是视觉大小的图片),再对该图片进行裁剪,裁剪方法是计算裁剪区域的起始坐标,这个坐标是从放大后图像的中心位置开始计算的,最后根据这个坐标和裁剪尺寸进行裁剪并保存新的图片。这样就得到了一个从放大后的图像中心为圆心,向外扩散裁剪;

④ 保存裁剪后的图片,进行后续操作。

四、代码

前端

<!doctype html><html lang="en">
<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"><title>WebcamJS Test Page - Large Capture</title><style type="text/css">body { font-family: Helvetica, sans-serif; }h2, h3 { margin-top:0; }form { margin-top: 15px; }form > input { margin-right: 15px; }#my_camera {  transition: transform 0.3s ease-in-out; /* 添加过渡效果,使变换更平滑 */  transform-origin: center center; /* 变换原点设置为图片中心 */  width: 100%; /* 初始尺寸设置为容器宽度 */  height: auto; /* 保持图片的宽高比 */  }#imageContainer{width: 640px; /* 设置你想要的容器宽度 */  height: 480px; /* 设置你想要的容器高度 */  overflow: hidden; /* 隐藏超出容器的部分 */  position: relative; /* 如果需要相对于容器定位图片,可以添加这个属性 */}</style>
</head>
<body><h1>WebcamJS Test Page - Large/Small Capture</h1><div id="imageContainer" style=""><div id="my_camera"></div></div><!-- A button for taking snaps --><form><input type=button value="Capture" onClick="take_snapshot()"><input type=button value="放大" id="zoomIn" ><input type=button value="缩小" id="zoomOut"><input type=button value="还原" id="reset"></form><script type="text/javascript" src="/static/index/js/webcam.min.js"></script><script src="https://ajax.aspnetcdn.com/ajax/jquery/jquery-3.5.1.min.js"></script><script language="JavaScript">Webcam.set({width: 640,height: 480,image_format: 'jpeg',jpeg_quality: 90});Webcam.attach( '#my_camera' );</script><script language="JavaScript">function take_snapshot() {// take snapshot and get image dataWebcam.snap( function(data_uri) {console.log(scale)var imgBase64 = data_uri$.ajax({url:'/index/camera/photo',dataType:'JSON',type:'POST',data:{data:imgBase64,scale:scale},success:function (res) {console.log(res)}})});}var scale = 1; // 初始缩放比例  $('#zoomIn').click(function() {  if (scale < 3) { // 限制最大缩放比例,这里设置为3 scale += 0.1; // 每次点击放大0.1  $('#my_camera').css('transform', 'scale(' + scale + ')');  }  // 计算放大后的尺寸var originalWidth = $("#my_camera").width();var originalHeight = $("#my_camera").height();var zoomedWidth = originalWidth * scale;  var zoomedHeight = originalHeight * scale; console.log(zoomedWidth)console.log(zoomedHeight)});  $('#zoomOut').click(function() {  if (scale > 1) { // 限制最小缩放比例,这里设置为1  scale -= 0.1; // 每次点击缩小0.1  $('#my_camera').css('transform', 'scale(' + scale + ')'); }  });  $('#reset').click(function() {  scale = 1$('#my_camera').css('transform', 'scale(' + scale + ')'); });  </script></body>
</html>

后端

// 处理图像
public function photo()
{$image= input('post.data');		//接收base64数据$scale= input('post.scale');	//接收缩放比例//图片存放的路径$path = "uploads".DS."chufang".DS.date('Y-m-d', time()) . DS;// 检查该目录是否存在,不存在就创建if (!file_exists($path)) {mkdir($path, 0700, true); //创建目录chmod($path, 0700); //赋予权限}$uid = session('uid');//确保图片名唯一,防止重名产生覆盖$imageName = 'wx_' .$uid.'_'. time() . rand(1000, 9000) . '.jpg';//判断是否有逗号 如果有就截取后半部分if (strstr($image,",")){$image = explode(',',$image);$image = $image[1];}//图片完整路径$imageSrc= ROOT_PATH .'public' .DS. $path . $imageName;// 生成文件夹和图片$r = file_put_contents($imageSrc, base64_decode($image));// 原始图像路径$sourceImagePath= $imageSrc;// 目标图像路径$targetImagePath = ROOT_PATH .'public' .DS. $path .'target.jpg';  // 实例化(原始图像路径)$image = new \Imagick($sourceImagePath);// 获取原始图像的尺寸  $originalWidth = $image->getImageWidth();  $originalHeight = $image->getImageHeight();  // 计算放大后图像的尺寸(这仅用于计算裁剪区域,最终图像尺寸保持不变)  $scaledWidth = $originalWidth * $scale;$scaledHeight = $originalHeight * $scale;// 保存放大后的图像  $image->resizeImage($scaledWidth, $scaledHeight, \Imagick::FILTER_LANCZOS, 1);  // 设定裁剪区域的尺寸(这里设置与原始图像一样大的尺寸)  $cropWidth = $originalWidth * 1; 	// 如果比原始宽度大50%,可*1.5  $cropHeight = $originalHeight * 1; // 如果比原始高度大50%,可*1.5 // 计算裁剪区域的起始坐标(从放大后图像的中心开始)  $startX = ($scaledWidth - $originalWidth) / 2;  $startY = ($scaledHeight - $cropHeight) / 2;  // 确保起始坐标是整数(因为像素坐标必须是整数)  $startX = (int)round($startX);  $startY = (int)round($startY);  // 使用 Imagick 的 cropImage 方法裁剪图像  $image->cropImage($cropWidth, $cropHeight, $startX, $startY);  // 保存新图像$image->writeImage($targetImagePath);  // 清除资源  $image->clear();  $image->destroy();  }

 五、资源下载

WebcamJS: jQuery移动端调用摄像头拍照插件WebcamJS

Imagick:PHP安装Imagick扩展库(网上有教程,可自行搜索)

完整代码下载:https://download.csdn.net/download/qq_25285531/89487658

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

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

相关文章

shell实用脚本1

参考公众号民工哥技术之路 场景一&#xff1a; 有两台服务器&#xff0c;a服务器的IP为11.0.1.18&#xff0c;b服务器的IP为11.0.1.12&#xff0c;都有个目录/app/tmp/test&#xff0c;我们需要比较这个目录里面的文件的一致性 #!/bin/bash ################################…

《mysql》--mysql约束

数据库约束 有的时候数据库中的数据是有一定要求的&#xff0c;有些数据认为是合法数据&#xff0c;有些是非法数据&#xff0c;如果靠人工检查显然是不靠谱的&#xff1b; 数据库会自动的对数据的合法性进行校验检查目的就是&#xff0c;保证数据中能够避免被插入/修改一些非…

Linux基础 - 使用 ssh 服务管理远程主机(window linux vscode)

目录 零. 简介 一. 打开linux shh 二. window连接linux 三. linux连接linux 四. VSCode远程 零. 简介 SSH&#xff08;Secure Shell&#xff09;服务是一种网络协议&#xff0c;主要用于在不安全的网络环境中为计算机之间的通信提供安全的加密连接。 SSH 服务具有以下重要…

二、安装虚拟机

本篇来源&#xff1a;山海同行 本篇地址&#xff1a;https://shanhaigo.cn/courseDetail/1805875642621952000 本篇资源&#xff1a;以整理到-山海同行 一、官网下载centos7 1. 进入CentOS 官方网站 官方网站&#xff1a;https://www.centos.org/download/ 2. 选择iso 点击下…

Java中的注解:原理与实战

Java中的注解&#xff1a;原理与实战 大家好&#xff0c;我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01; Java注解&#xff08;Annotation&#xff09;是一种用于在代码中添加元数…

在nginx服务器发布项目以及在tomcat服务器发布项目

在nginx服务器发布项目&#xff1a; nginx有一个“热部署”或“无缝升级”的特性&#xff0c;这意味着在不停止服务的情况下&#xff0c;也可以更新配置文件和html文件夹。 如果上传的是配置文件&#xff0c;或者修改了nginx的配置&#xff0c;那么可能需要重启nginx来应用这…

高中数学:不等式-常用不等式知识点汇总

一、基本性质 比较大小的常用两种方法&#xff1a;作差法&#xff0c;作商法 等式性质 不等式性质 二、基本(均值)不等式 扩展 三、二次函数与一元二次方程不等式 定义 解的对应关系 一元二次不等式的求解过程 四、二元一次不等式(组)与线性规划 关键在于求多个不等…

无线领夹麦克风怎么挑选,能让声音变好听的领夹麦推荐大全

近年来&#xff0c;随着直播销售和个人视频日志&#xff08;Vlog&#xff09;的流行&#xff0c;自媒体内容创作已经成为一种文化现象。这一现象不仅改变了人们获取信息的方式&#xff0c;也极大地推动了相关音频设备的发展。无线领夹麦克风&#xff0c;以其轻巧的设计和出色的…

MySQL数据库基础练习系列:科研项目管理系统

DDL CREATE TABLE Users (user_id INT AUTO_INCREMENT PRIMARY KEY COMMENT 用户ID,username VARCHAR(50) NOT NULL UNIQUE COMMENT 用户名,password VARCHAR(255) NOT NULL COMMENT 密码,gender ENUM(男, 女) NOT NULL COMMENT 性别,email VARCHAR(100) UNIQUE COMMENT 邮箱 …

【杂记-浅谈VRRP虚拟路由器冗余协议】

一、VRRP协议概述 VRRP&#xff0c;Virtual Router Redundancy Protocol&#xff0c;即虚拟路由器冗余协议&#xff0c;是一种用于提高网络可靠性和容错能力的协议。它能够在多个路由器之间共享一个虚拟IP地址&#xff0c;当主路由器失效时&#xff0c;备用路由器可以接管虚拟…

字节码编程ASM之idea插件asm bytecode outline的使用

写在前面 直接用ASM来编写字节码程序难度其实还是蛮大的&#xff0c;为此&#xff0c;就有热心人事开发了相关的idea插件 &#xff0c;其中比较优秀的一个是asm bytecode outline,本文就来一起看下如何使用。 1&#xff1a;安装 file->setting->plugins,搜索asm bytec…

gin-vue-amdin 新增路由

1&#xff1a;在api目录的example 下新建controller 层如下图&#xff08;&#xff09;&#xff1a; 在enter.go 中 加入 这个新建的结构体&#xff1a; 2&#xff1a;在router 的example 文件夹下 新建对应的路由文件 3&#xff1a;在initlize 的router 中 添加对应的代码&a…

PDF处理篇:有哪些免费的PDF注释工具

PDF 是一种功能强大的格式&#xff0c;广泛用于处理和传输数据。您可以创建自己的 PDF 文件&#xff0c;也可以使用其他人创建的 PDF 文件。但是&#xff0c;有时您想在 PDF 文件中包含其他文本、图形和其他元素。这就是 PDF 注释器为您提供帮助的地方。 有许多可用的 PDF 注释…

Bazel与Gradle工具差异

之前介绍Bazel文章中有同学闻到Bazel与Gradle工具的差异。这篇文章我们解答这个问题。 来自Bazel员工的说法 Bazel和Gradle强调构建体验的不同方面。在某种程度上,它们的侧重点是互斥的——Gradle对灵活性和非突出性的要求对它的构建结构进行了限制,而Bazel对可靠性和性能的…

无线领夹麦克风品牌排名,揭秘哪种领夹麦性价比高!

在直播电商和Vlog的热潮推动下&#xff0c;自媒体内容创作迎来了前所未有的繁荣。麦克风行业也因应这一趋势&#xff0c;迎来了快速的增长期。特别是无线领夹麦克风&#xff0c;以其便携性和高效的录音能力&#xff0c;迅速成为视频制作者的新宠。它不仅在直播带货和短视频制作…

allure安装教程

1、下载 allure的官网下载地址&#xff1a; https://github.com/allure-framework/allure2/releases 注意&#xff1a;官网时常访问失败&#xff0c;可以访问以下网址&#xff1a; https://repo.maven.apache.org/maven2/io/qameta/allure/allure-commandline/ 选择一个版本&…

Qt实现开机自启两种方法包含注意事项以及常见问题解决

Qt开机自启教程 Qt是一个跨平台的C++框架,用于开发图形用户界面应用程序,同时也支持其他类型的应用程序开发,如命令行工具、服务器、嵌入式设备应用程序等。用户在虚拟机开发后使用交叉编译器放到设备中设置开机自启,以下是两种常用的方法。 通过Systemd 设置开机自启 1…

C++ CMake 预定义宏与变量

宏/变量 说明 CMAKE_SOURCE_DIR 顶层 CMakeLists.txt 所在的目录 CMAKE_BINARY_DIR 构建输出目录的顶层路径 CMAKE_CURRENT_SOURCE_DIR 当前处理的 CMakeLists.txt 所在的路径 CMAKE_CURRENT_BINARY_DIR 当前处理的 CMakeLists.txt 输出的构建目录 CMAKE_CURRENT_LIS…

Uniapp的使用

为什么要使用uniapp uniapp 可以进行多端开发&#xff0c;uniapp 在设计的时候就拥有许多兼容性代码&#xff0c;可以兼容很多的平台 如 支付宝小程序 html页面 微信小程序等&#xff0c;注重开发效率而不是运行效率时 &#xff0c;就可以考虑一下 uniapp 当然也可以去…

深入浅出:MongoDB中的背景创建索引

深入浅出&#xff1a;MongoDB中的背景创建索引 想象一下&#xff0c;你正忙于将成千上万的数据塞入你的MongoDB数据库中&#xff0c;你的用户期待着实时的响应速度。此时&#xff0c;你突然想到&#xff1a;“嘿&#xff0c;我应该给这些查询加个索引&#xff01;” 没错&…