>  기사  >  웹 프론트엔드  >  웹 기술이 모바일 모니터링을 구현하는 방법

웹 기술이 모바일 모니터링을 구현하는 방법

小云云
小云云원래의
2018-02-09 13:27:111626검색

이 기사에서는 주로 웹 기술이 모션 모니터링, 모션 감지(일반적으로 모션 감지라고도 함)를 구현하는 방법을 소개합니다. 이는 무인 감시 비디오 및 자동 알람에 자주 사용됩니다. 카메라가 서로 다른 프레임 속도로 수집한 이미지는 특정 알고리즘에 따라 CPU에서 계산 및 비교되며, 사람이 지나가거나 렌즈가 움직이는 등 사진이 변경되면 계산 및 비교 결과에서 얻은 숫자가 표시됩니다. 임계값을 초과하고 시스템이 자동으로 해당 처리를 수행할 수 있음을 나타냅니다.

웹 기술을 사용한 모바일 모니터링 소개

위 인용에서 "모바일 모니터링"에는 다음 요소가 필요하다는 결론을 내릴 수 있습니다.

컴퓨터 움직임 알고리즘을 결정하는 데 사용되는 카메라 움직임 후 처리

참고: 이 기사에 포함된 모든 사례는 PC/Mac의 최신 버전 Chrome/Firefox 브라우저를 기반으로 하며 일부 사례는 카메라로 완료해야 합니다. 모든 스크린샷은 로컬에 저장됩니다.

상대가 대화를 원하지 않아 링크를 던집니다:

체험 링크>>

웹 기술이 모바일 모니터링을 구현하는 방법
종합 케이스

이 케이스는 다음 두 가지 기능을 가지고 있습니다.

촬영 후 POST 1초 동안 사진이 촬영되고 1초 후에 음악이 정지됩니다. 움직임이 발생하면 재생 상태가 다시 시작됩니다. 위의 경우는 "모션 모니터링"의 실제 효과와 원리를 직접적으로 반영하지 않을 수 있습니다. 이 경우에는 또.

체험링크>

웹 기술을 기반으로 하기 때문에 영상 소스는 WebRTC를, 픽셀 처리는 Canvas를 사용합니다.

비디오 소스웹 기술이 모바일 모니터링을 구현하는 방법

는 Flash 또는 Silverlight에 의존하지 않으며 웹 애플리케이션이 사용자의 카메라 및 마이크 스트림을 얻을 수 있도록 하는 WebRTC(웹 실시간 통신)의 navigator.getUserMedia() API를 사용합니다.

샘플 코드는 다음과 같습니다.

<!-- 若不加 autoplay,则会停留在第一帧 -->
<video id="video" autoplay></video>
// 具体参数含义可看相关文档。
const constraints = {
 audio: false,
 video: {
 width: 640,
 height: 480
 }
}
navigator.mediaDevices.getUserMedia(constraints)
 .then(stream => {
 // 将视频源展示在 video 中
 video.srcObject = stream
 })
 .catch(err => {
 console.log(err)
 })

호환성 문제로 인해 Safari 11에서는 WebRTC를 지원하기 시작합니다. 자세한 내용은 caniuse를 참조하세요.

픽셀 처리

동영상 소스를 얻은 후 물체가 움직이는지 여부를 판단할 수 있는 자료가 있습니다. 물론 여기에는 고급 인식 알고리즘이 사용되지 않습니다. 단지 두 개의 연속 스크린샷 간의 픽셀 차이를 사용하여 개체가 이동했는지 여부를 판단합니다(엄격히 말하면 사진의 변화입니다).

Screenshot

비디오 소스의 스크린샷을 얻기 위한 샘플 코드:

const video = document.getElementById(&#39;video&#39;)
const canvas = document.createElement(&#39;canvas&#39;)
const ctx = canvas.getContext(&#39;2d&#39;)
canvas.width = 640
canvas.height = 480
// 获取视频中的一帧
function capture () {
 ctx.drawImage(video, 0, 0, canvas.width, canvas.height)
 // ...其它操作
}

스크린샷의 차이를 알아보세요두 사진의 픽셀 차이를 보려면 ""잠깐만 기다려 주세요. "" 범프랩의! "——일반적인 2D 충돌 감지" 이 블로그 게시물에서 언급된 '픽셀 감지' 충돌 알고리즘은 솔루션 중 하나입니다. 이 알고리즘은 두 개의 오프 스크린 캔버스의 동일한 위치에 있는 픽셀의 투명도가 동시에 0보다 큰지 여부를 탐색하여 충돌이 있는지 확인합니다. 물론 여기서는 "동일한 위치의 픽셀이 다른지(또는 그 차이가 특정 임계값보다 작은지)"로 변경하여 이동 여부를 판단해야 합니다.

하지만 위의 방법은 약간 번거롭고 비효율적입니다. 여기서는

를 사용하여 캔버스에 있는 새 요소(즉, 두 번째 스크린샷과 첫 번째 스크린샷)의 합성 방법을 지정하여 두 스크린샷의 차이를 알아냅니다.


체험링크>>

샘플코드 :

function diffTwoImage () {
 // 设置新增元素的合成方式
 ctx.globalCompositeOperation = &#39;difference&#39;
 
 // 清除画布
 ctx.clearRect(0, 0, canvas.width, canvas.height)
 
 // 假设两张图像尺寸相等
 ctx.drawImage(firstImg, 0, 0)
 ctx.drawImage(secondImg, 0, 0)
}
ctx.globalCompositeOperation = 'difference'

두 사진의 차이점

위 사례를 경험하고 나면, "QQ게임 "틀린그림찾기"" 다시 하고 싶은 기분이 드시나요? 그 다음에. 또한 이 사례는 다음 두 가지 상황에도 해당될 수 있습니다.


디자이너가 제공한 두 디자인 초안의 전후 차이를 모를 때

웹 기술이 모바일 모니터링을 구현하는 방법

결과를 확인하고 싶을 때 두 브라우저 간의 동일한 웹페이지 "액션" 렌더링의 차이는 언제입니까? 위의 "두 이미지의 차이" 사례에서 검은색은 해당 위치의 픽셀이 변경되지 않았음을 의미하고, 픽셀이 밝을수록 해당 지점이 변경되었음을 의미합니다. "액션"이 커졌습니다. 따라서 두 개의 연속 스크린샷을 결합한 후 밝은 픽셀이 있으면 "액션"입니다. 그러나 프로그램을 덜 "민감하게" 만들기 위해 임계값을 설정할 수 있습니다. 밝은 픽셀의 수가 임계값보다 크면 "동작"이 발생한 것으로 간주됩니다. 물론 외부 환경(조명 등)의 영향을 최대한 피하기 위해 "충분히 밝지 않은" 픽셀을 제거할 수도 있습니다.

想要获取 Canvas 的像素信息,需要通过 ctx.getImageData(sx, sy, sw, sh),该 API 会返回你所指定画布区域的像素对象。该对象包含 datawidthheight。其中 data 是一个含有每个像素点 RGBA 信息的一维数组,如下图所示。

getImageData 图像
含有 RGBA 信息的一维数组

获取到特定区域的像素后,我们就能对每个像素进行处理(如各种滤镜效果)。处理完后,则可通过 ctx.putImageData() 将其渲染在指定的 Canvas 上。

扩展:由于 Canvas 目前没有提供“历史记录”的功能,如需实现“返回上一步”操作,则可通过 getImageData 保存上一步操作,当需要时则可通过 putImageData 进行复原。

示例代码:


let imageScore = 0
const rgba = imageData.data
for (let i = 0; i < rgba.length; i += 4) {
 const r = rgba[i] / 3
 const g = rgba[i + 1] / 3
 const b = rgba[i + 2] / 3
 
 const pixelScore = r + g + b
 
 // 如果该像素足够明亮
 if (pixelScore >= PIXEL_SCORE_THRESHOLD) {
 imageScore++
 }
}
// 如果明亮的像素数量满足一定条件
if (imageScore >= IMAGE_SCORE_THRESHOLD) {
 // 产生了移动
}

在上述案例中,你也许会注意到画面是『绿色』的。其实,我们只需将每个像素的红和蓝设置为 0,即将 RGBA 的 r = 0; b = 0 即可。这样就会像电影的某些镜头一样,增加了科技感和神秘感。

体验地址>>


const rgba = imageData.data
for (let i = 0; i < rgba.length; i += 4) {
 rgba[i] = 0 // red
 rgba[i + 2] = 0 // blue
}
ctx.putImageData(imageData, 0, 0)

将 rgba 中的 r 和 b 置为 0
将 RGBA 中的 R 和 B 置为 0

跟踪“移动物体”

有了明亮的像素后,我们就要找出其 x 坐标的最小值与 y 坐标的最小值,以表示跟踪矩形的左上角。同理,x 坐标的最大值与 y 坐标的最大值则表示跟踪矩形的右下角。至此,我们就能绘制出一个能包围所有明亮像素的矩形,从而实现跟踪移动物体的效果。

웹 기술이 모바일 모니터링을 구현하는 방법
웹 기술이 모바일 모니터링을 구현하는 방법

体验链接>>

示例代码:


function processDiff (imageData) {
 const rgba = imageData.data
 
 let score = 0
 let pixelScore = 0
 let motionBox = 0
 
 // 遍历整个 canvas 的像素,以找出明亮的点
 for (let i = 0; i < rgba.length; i += 4) {
 pixelScore = (rgba[i] + rgba[i+1] + rgba[i+2]) / 3
 
 // 若该像素足够明亮
 if (pixelScore >= 80) {
 score++
 
 coord = calcCoord(i)
 motionBox = calcMotionBox(montionBox, coord.x, coord.y)
 }
 }
 
 return {
 score,
 motionBox
 }
}
// 得到左上角和右下角两个坐标值
function calcMotionBox (curMotionBox, x, y) {
 const motionBox = curMotionBox || {
 x: { min: coord.x, max: x },
 y: { min: coord.y, max: y }
 }
 motionBox.x.min = Math.min(motionBox.x.min, x)
 motionBox.x.max = Math.max(motionBox.x.max, x)
 motionBox.y.min = Math.min(motionBox.y.min, y)
 motionBox.y.max = Math.max(motionBox.y.max, y)
 return motionBox
}
// imageData.data 是一个含有每个像素点 rgba 信息的一维数组。
// 该函数是将上述一维数组的任意下标转为 (x,y) 二维坐标。
function calcCoord(i) {
 return {
 x: (i / 4) % diffWidth,
 y: Math.floor((i / 4) / diffWidth)
 }
}

在得到跟踪矩形的左上角和右下角的坐标值后,通过 ctx.strokeRect(x, y, width, height) API 绘制出矩形即可。


ctx.lineWidth = 6
ctx.strokeRect(
 diff.motionBox.x.min + 0.5,
 diff.motionBox.y.min + 0.5,
 diff.motionBox.x.max - diff.motionBox.x.min,
 diff.motionBox.y.max - diff.motionBox.y.min
)

웹 기술이 모바일 모니터링을 구현하는 방법
这是理想效果,实际效果请打开 体验链接

扩展:为什么上述绘制矩形的代码中的 x、y 要加 0.5 呢?一图胜千言:
0.5 像素

性能缩小尺寸

在上一个章节提到,我们需要通过对 Canvas 每个像素进行处理,假设 Canvas 的宽为 640,高为 480,那么就需要遍历 640 * 480 = 307200 个像素。而在监测效果可接受的前提下,我们可以将需要进行像素处理的 Canvas 缩小尺寸,如缩小 10 倍。这样需要遍历的像素数量就降低 100 倍,从而提升性能。

体验地址>>

示例代码:


const motionCanvas // 展示给用户看
const backgroundCanvas // offscreen canvas 背后处理数据
motionCanvas.width = 640
motionCanvas.height = 480
backgroundCanvas.width = 64
backgroundCanvas.height = 48

웹 기술이 모바일 모니터링을 구현하는 방법
尺寸缩小 10 倍

定时器

我们都知道,当游戏以『每秒60帧』运行时才能保证一定的体验。但对于我们目前的案例来说,帧率并不是我们追求的第一位。因此,每 100 毫秒(具体数值取决于实际情况)取当前帧与前一帧进行比较即可。

另外,因为我们的动作一般具有连贯性,所以可取该连贯动作中幅度最大的(即“分数”最高)或最后一帧动作进行处理即可(如存储到本地或分享到朋友圈)。

延伸

至此,用 Web 技术实现简易的“移动监测”效果已基本讲述完毕。由于算法、设备等因素的限制,该效果只能以 2D 画面为基础来判断物体是否发生“移动”。而微软的 Xbox、索尼的 PS、任天堂的 Wii 等游戏设备上的体感游戏则依赖于硬件。以微软的 Kinect 为例,它为开发者提供了可跟踪最多六个完整骨骼和每人 25 个关节等强大功能。利用这些详细的人体参数,我们就能实现各种隔空的『手势操作』,如画圈圈诅咒某人。

下面几个是通过 Web 使用 Kinect 的库:

  • DepthJS:以浏览器插件形式提供数据访问。

  • Node-Kinect2: 以 Nodejs 搭建服务器端,提供数据比较完整,实例较多。

  • ZigFu: H5, U3D, Flash를 지원하며 비교적 완전한 API를 갖추고 있습니다.

  • Kinect-HTML5: Kinect-HTML5는 C#을 사용하여 서버를 구축하고 색상 데이터, 깊이 데이터 및 뼈 데이터를 제공합니다. Node-Kinect2 관련 권장 사항을 통한 골격 데이터 Acquire 골격 데이터 :

ajax 작동 글로벌 모니터링, 사용자 세션에 대한 솔루션 실패 110 시간 모니터링 카테고리의 컨텐츠 권장 사항 通过 Web 访问 Kinect

PHP 타이머 페이지 러닝타임 모니터링 수업

위 내용은 웹 기술이 모바일 모니터링을 구현하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.