WebRTC从摄像头获取图片传入canvas
WebRTC从摄像头获取图片传入canvas
前面我们已经能够利用WebRTC的功能,通过浏览器打开摄像头,并把预览的图像显示在video元素中。
接下来我们尝试从视频中截取某一帧,显示在界面上。
html
先准备一下界面,摆上控件。下面是关键部分的代码。
<video playsinline autoplay></video>
<button id="showVideo">打开摄像头</button>
<button id="takeSnapshot">截取</button>
<button id="clearList">清除记录</button>
<canvas id="mainCanvas"></canvas>
<div id="list" style="display: grid; grid-template-columns: repeat(auto-fill, 100px);
column-gap: 20px; row-gap: 20px;"></div>
- video 用来预览视频
- 3个button,分别拿来打开摄像头,截取图片和清除记录
- canvas 用来显示截取的图片
- 下面的div是拿来存放多个截取图片记录的。给它指定了grid,显示多个图片时候比较好看一些
照例,需要引入adapter-latest.js
<script src="https://webrtc.github.io/adapter/adapter-latest.js"></script>
js
准备实现功能。
打开摄像头并预览
和之前的打开摄像头类似,还是要用到getUserMedia方法。拿到视频流后交给video去播放。
const video = document.querySelector('video');
const constraints = {
audio: false,
video: true
};
// ....
function openCamera(e) {
navigator.mediaDevices.getUserMedia(constraints).then(gotStream).catch(onError);
}
function gotStream(stream) {
window.stream = stream;
video.srcObject = stream;
}
function onError(error) {
console.log('navigator.MediaDevices.getUserMedia error: ', error.message, error.name);
}
截取图片
拿到界面中的canvas,先预定一个尺寸(不预定也行)。
const mCanvas = window.canvas = document.querySelector('#mainCanvas');
mCanvas.width = 480;
mCanvas.height = 360;
// 开始截取
mCanvas.width = video.videoWidth;
mCanvas.height = video.videoHeight;
mCanvas.getContext('2d').drawImage(video, 0, 0, mCanvas.width, mCanvas.height);
发起截取后,使用getContext获取到CanvasRenderingContext2D对象。然后调用它的drawImage方法。
把video中的视频帧绘制进去。
除了绘制这一个canvas,我们可以在每次发起(点击按钮)的时候创建新的canvas,把它们像相册一样展示出来。
const list = document.querySelector('#list'); // 拿来存放多个元素
// 新增1张
var divItem = document.createElement("div");
divItem.style.display = "block";
divItem.width = 100;
divItem.height = divItem.width * video.videoHeight / video.videoWidth; // 计算一下比例
divItem.style.width = divItem.width + "px";
divItem.style.height = divItem.height + "px";
console.log("div item size: ", divItem.width, divItem.height);
var c1 = document.createElement("canvas");
c1.width = divItem.width;
c1.height = divItem.height;
c1.getContext('2d').drawImage(video, 0, 0, mCanvas.width, mCanvas.height, 0, 0, c1.width, c1.height);
divItem.appendChild(c1);
list.appendChild(divItem);
子项的存放方式是div包裹canvas。先用document.createElement("div")创建divItem。
按照视频的宽高,计算调整divItem的大小,并设置style。
document.createElement("canvas")创建c1,它的宽高设置为前面divItem的宽高。然后把图片绘制进去。
drawImage时,前面传入的是视频(源)的范围,后面的4个参数是自己的绘制范围。
这样一个子项就生成完毕了。添加到我们准备好的列表(div)中。
清除记录
清除div(list)里的子项。用一个循环获取并移除子项。
var child = list.lastElementChild;
while (child) {
list.removeChild(child);
child = list.lastElementChild;
}
小结
打开摄像头,显示视频。把视频绘制到canvas上。创建多个canvas,做成历史记录的效果。
主要利用的还是canvas的绘制方法。绘制的时候注意传入的参数,能够指定绘制的边界。
也就是说只绘制视频大小中的一部分也是可行的。
示例中用到的关键方法
getUserMediagetContextdrawImagecreateElement
预览
简易的预览链接
WebRTC从摄像头获取图片传入canvas的更多相关文章
- 利用opencv从USB摄像头获取图片
由于opencv自带的VideoCapture函数直接从usb摄像头获取视频数据,所以用这个来作为实时的图像来源用于实体检测识别是很方便的. 1. 安装opencv 安装的步骤可以按照之前这个文章操作 ...
- ios中摄像头/相册获取图片,压缩图片,上传服务器方法总结
相册 iphone的相册包含摄像头胶卷+用户计算机同步的部分照片.用户可以通过UIImagePickerController类提供的交互对话框来从相册中选择图像.但是,注意:相册中的图片机器路径无法直 ...
- ios中摄像头/相册获取图片压缩图片上传服务器方法总结
本文章介绍了关于ios中摄像头/相册获取图片,压缩图片,上传服务器方法总结,有需要了解的同学可以参考一下下. 这几天在搞iphone上面一个应用的开发,里面有需要摄像头/相册编程和图片上传的问 ...
- js canvas获取图片base64 dataUrl
function getImgBase64(path, callback) { var img = new Image(); img.src = path; //图片加载完成后触发 img.onloa ...
- iOS 使用AFN 进行单图和多图上传 摄像头/相册获取图片,压缩图片
图片上传时必要将图片进行压缩,不然会上传失败 首先是同系统相册选择图片和视频.iOS系统自带有UIImagePickerController,可以选择或拍摄图片视频,但是最大的问题是只支持单选,由于项 ...
- 识别快递单号(2) - 加载图片到canvas
传送门: 识别快递单号(1) - 图像处理 转载请注明出处: http://www.cnblogs.com/zaiyuzhong/p/load-image-to-canvas.html 上篇说到我 ...
- 教你做炫酷的碎片式图片切换 (canvas)
前言 老规矩,先上 DEMO 和 源码.图片区域是可以点击的,动画会从点击的位置开始发生. 本来这个效果是我3年前做的,只是当是是用无数个 div 标签完成的,性能比较成问题,在移动端完全跑不动.最近 ...
- 图片在 canvas 中的 选中/平移/缩放/旋转,包含了所有canvas的2D变化,让你认识到数学的重要性
1.介绍 canvas 已经出来好久了,相信大家多少都有接触. 如果你是前端页面开发/移动开发,那么你肯定会有做过图片上传处理,图片优化,以及图片合成,这些都是可以用 canvas 实现的. 如果你是 ...
- JavaScript获取图片的原始尺寸
页面里的img元素,想要获取它的原始尺寸,以宽度为例可能首先想到的就是width,如下 <img src="http://img11.360buyimg.com/da/g14/M07/ ...
随机推荐
- ☕【Java技术指南】「编译器专题」深入分析探究“静态编译器”(JAVA\IDEA\ECJ编译器)是否可以实现代码优化?
技术分析 大家都知道Eclipse已经实现了自己的编译器,命名为 Eclipse编译器for Java (ECJ). ECJ 是 Eclipse Compiler for Java 的缩写,是 Jav ...
- 2020.10.10--pta阶梯赛练习2补题
7-3.N个数求和 本题的要求很简单,就是求N个数字的和.麻烦的是,这些数字是以有理数分子/分母的形式给出的,你输出的和也必须是有理数的形式. 输入格式: 输入第一行给出一个正整数N(≤100).随后 ...
- 霍尔效应实验 execl数据处理
execl 函数 =POWER() /*幂次*/ =ROUND() /*保留小数点后几位*/ =SQRT() /*开平方根*/ =POWER( x, 1/3 ) /*开立方根*/ =COUNTA() ...
- Mybatis 二级缓存应用 (21)
[MyBatis 二级缓存] 概述:一级缓存作用域为同一个SqlSession对象,而二级缓存用来解决一级缓存不能夸会话共享,作用范围是namespace级,可以被多个SqlSession共享(只要是 ...
- 第六次Scrum Metting
日期:2021年5月3日 会议主要内容概述:讨论前后端进度,前端各模块对接以及前后端对接. 一.进度情况 组员 负责 两日内已完成的工作 后两日计划完成的工作 工作中遇到的困难 徐宇龙 后端 数据模块 ...
- [no_code]团队贡献分分配规则
项目 内容 2020春季计算机学院软件工程(罗杰 任健) 2020春季计算机学院软件工程(罗杰 任健) 作业要求 团队贡献分分配规则 我们在这个课程的目标是 远程协同工作,采用最新技术开发软件 这个作 ...
- redis中lua脚本的简单使用
一.背景 在使用redis的过程中,发现有些时候需要原子性去操作redis命令,而redis的lua脚本正好可以实现这一功能.比如: 扣减库存操作.限流操作等等. redis的pipelining虽然 ...
- Gitflow branch与Docker image tag命名冲突怎么办?
谷歌还是比必应要好用一点. 在前公司,我根据主流的git flow 给团队搭建了一套devops流程,运行在 docker & k8s上. 在现代devops流程中,一般推荐使用git分支名或 ...
- Spring Security 的注册登录流程
Spring Security 的注册登录流程 数据库字段设计 主要数据库字段要有: 用户的 ID 用户名称 联系电话 登录密码(非明文) UserDTO对象 需要一个数据传输对象来将所有注册信息发送 ...
- 重学STM32---(十)之CAN通信(二)
目录 前言 程序编写 主代码 测试 前言 CAN协议是非常难的,但是在stm32中却是简单的,只需要我们配置寄存器即可,,,即使这样,我在学习的时候也遇到了许多困难 程序编写 1.开时钟,不用说 ...