颜色阈值JS、平均图像颜色检测JS

问题描述 投票:0回答:1

我观看了以下教程https://youtu.be/BTWPDboW38o?si=_21TOjCfrXC3VWIL并尝试了同样的操作。我期望的是,我想根据视频流的颜色更改文档的背景颜色。但它总是返回 rgb(0,0,0)。

'use strict';
try {
    const w = window,
        d = document,
        ng = navigator,
        id = e => {
            return d.getElementById(e)
        },
        cn = id('lh'),
        i = id('i'),
        o = id('o'),
        cx = cn.getContext('2d', {
            willReadFrequently: true
        }),
        face = r => ng.mediaDevices.getUserMedia({
            video: {
                facingMode: {
                    exact: 'user'
                }
            }
        }).then(s => {
            i.srcObject = s;
            i.onloadedmetadata = e => {
                setInterval(() => {
                    let c = 0,
                        k = -4,
                        h = cn.height = i.videoHeight,
                        w = cn.width = i.videoWidth,
                        dt = cx.getImageData(0, 0, w, h),
                        io = dt.data,
                        dl = io.length,
                        R, G, B;
                    R = G = B = 0;
                    cx.drawImage(i, 0, 0, w, h);
                    o.src = cn.toDataURL('image/webp');
                    while ((k += r * 4) < dl) {
                        ++c;
                        R += io[k];
                        G += io[k + 1];
                        B += io[k + 2]
                    };
                    ['R', 'G', 'B'].forEach(e1 => {
                        eval(e1 + '=' + `~~(${e1}/c)`)
                    });
                    let rgb = `rgb(${R},${G},${B})`;
                    d.body.style.background = rgb
                }, -1)
            }
        });
    face(4)
} catch (e) {
    alert(e)
}

我希望它应该根据视频流改变文档的背景颜色。

javascript image colors stream
1个回答
0
投票

好吧,你的代码实际上有很多错误

  1. 分配视频元素的 srcObject 后,您必须调用 play

  2. 在 setInterval 中,您在 let 语句中获取图像数据,但您已将任何内容绘制到画布上

  3. 当您实际调用face(4)时,您不会将r变量传递给then函数

  4. 当您使用数组 e1 的内容调用 eval 时,实际上保存的是字母“R”、“G”、“B”而不是它们的值

  5. 我不确定您实际上想通过 eval 实现什么目的,请参阅 按位非运算符 (~)

'use strict';

var timer;
var stream;

document.querySelector('input[value=stop]').onclick = e=>{
  clearInterval(timer);
  if(stream)stream.getTracks().forEach(track=>track.stop());
}

try {
    const w = window,
        d = document,
        ng = navigator,
        id = e => {
            return d.getElementById(e)
        },
        cn = id('lh'),
        i = id('i'),
        o = id('o'),
        cx = cn.getContext('2d', {
            willReadFrequently: true
        }),
        face = r => ng.mediaDevices.getUserMedia({
            video: {width:100,height:100}
        }).then(s => {
            stream=s;
            i.srcObject = s;
            i.play();
            i.onloadedmetadata = e => {
                timer=setInterval(() => {
                    let c = 0,
                        k = -4,
                        h = cn.height = i.videoHeight,
                        w = cn.width = i.videoWidth;
                        
                    cx.drawImage(i, 0, 0, w, h);
                    let dt = cx.getImageData(0, 0, w, h),
                        io = dt.data,
                        dl = io.length,
                        R, G, B;
                    
                    R = G = B = 0;
                    o.src = cn.toDataURL('image/webp');
                    while ((k += 4) < dl) {
                        ++c;
                        R += io[k];
                        G += io[k + 1];
                        B += io[k + 2]
                    };
                    R/=c;
                    G/=c;
                    B/=c;
                    /*
                    ['R', 'G', 'B'].forEach(e1 => {
                        eval(e1 + '=' + `~~(${e1}/c)`)
                    });
                    */
                    let rgb = `rgb(${R},${G},${B})`;
                    d.body.style.background = rgb
                }, -1)
            }
        });
    face(4)
} catch (e) {
    alert(e)
}
canvas {
  border:1px solid lightgray;
}
video {
  border:1px solid lightgray;
}
img {
  border:1px solid lightgray;
}
input {
  font-size:16px;
  padding:5px;
}
<canvas id=lh></canvas>
<video id=i></video>
<img id=o>
<input type=button value=stop>

我添加了停止功能,因此可以通过重新加载页面来关闭它

我担心它实际上不会在 stackoverflow 网站上运行,我认为他们必须关闭网络摄像头访问并且不允许播放视频

我为以后访问此页面的任何人创建了一个更简洁的版本

  var stream    = await navigator.mediaDevices.getUserMedia({
        video   : true
  });
  
  var video         = document.createElement('video');
  video.srcObject   = stream;
  video.play();
  
  update();
  
  function update(){
    
        gen.update();
        
        ctx.clearRect(0,0,canvas.width,canvas.height);
        ctx.drawImage(video,0,0,canvas.width,canvas.height);
        
        var data    = ctx.getImageData(0,0,canvas.width,canvas.height);
        var n       = data.data.length;
        var r       = 0;
        var g       = 0;
        var b       = 0;
        
        for(var i=0;i<n;i+=8){
              
              r  += data.data[i]/n*4;
              g  += data.data[i+1]/n*4;
              b  += data.data[i+2]/n*4;
              
        }//for
        
        document.body.style.background    = `rgb(${r},${g},${b})`;
        
        if(abort)return;
        requestAnimationFrame(update,1000/framerate);
    
  }//update
© www.soinside.com 2019 - 2024. All rights reserved.