代码之家  ›  专栏  ›  技术社区  ›  Hope

如何获取网络摄像头提要中特定区域的平均颜色(处理/JavaScript)?

  •  1
  • Hope  · 技术社区  · 6 年前

    我正在使用处理从我的笔记本电脑获取网络摄像头提要。在左上角,我在显示的提要上绘制了一个矩形。我试图获得网络摄像头的平均颜色,但仅限于该矩形包含的区域。

    结果,我不断得到颜色(0,0,0),黑色。

    谢谢大家!

    PS抱歉,如果我的代码看起来很凌乱。。我是处理方面的新手,所以我不知道这是否很难阅读或包含不良做法。非常感谢。

    import processing.video.*;
    
    Capture webcam;
    Capture cap;
    PImage bg_img;
    
    color bgColor = color(0, 0, 0);
    
    int rMargin = 50;
    int rWidth = 100;
    
    color input = color(0, 0, 0);
    color background = color(255, 255, 255);
    color current;
    int bgTolerance = 5;
    
    void setup() {
      size(1280,720);
    
      // start the webcam
      String[] inputs = Capture.list();
      if (inputs.length == 0) {
        println("Couldn't detect any webcams connected!");
        exit();
      }
      webcam = new Capture(this, inputs[0]);
    
      webcam.start();
    
    }
    
    
    void draw() {
      if (webcam.available()) {
    
        // read from the webcam
        webcam.read();
    
        image(webcam, 0,0);
        webcam.loadPixels();
    
        noFill();
        strokeWeight(2);
        stroke(255,255, 255);
        rect(rMargin, rMargin, rWidth, rWidth);
    
        int yCenter = (rWidth/2) + rMargin;
        int xCenter = (rWidth/2) + rMargin;
        // rectMode(CENTER);
    
        int rectCenterIndex = (width* yCenter) + xCenter;
    
        int r = 0, g = 0, b = 0;
    
        //for whole image:
        //for (int i=0; i<bg_img.pixels.length; i++) {
        //    color c = bg_img.pixels[i];
        //    r += c>>16&0xFF;
        //    g += c>>8&0xFF;
        //    b += c&0xFF;
        //}
        //r /= bg_img.pixels.length;
        //g /= bg_img.pixels.length;
        //b /= bg_img.pixels.length;
    
        //CALCULATE AVG COLOR:
        int i;
    for(int x = 50; x <= 150; x++){
       for(int y = 50; y <= 150; y++){
               i = (width*y) + x;
               color c = webcam.pixels[i];
               r += c>>16&0xFF;
               g += c>>8&0xFF;
               b += c&0xFF;
           }
        }
        r /= webcam.pixels.length;
        g /= webcam.pixels.length;
        b /= webcam.pixels.length;
    
        println(r + " " + g + " " + b);
      }
    }
    
    1 回复  |  直到 6 年前
        1
  •  1
  •   George Profenza    6 年前

    您非常接近,但遗漏了一个重要方面:采样的像素数。

    请注意,在注释掉的完整图像示例代码中,您将除以完整的像素数(pixels.length)。

    然而,在经过调整的版本中,您只需要计算完整图像的一部分的平均颜色,这意味着像素数量较少。

    您仅对100x100像素的区域进行采样,这意味着您需要除以10000,而不是 webcam.pixels.length (1920x1000)。这就是为什么得到0,因为它是整数除法。 这就是我在代码中的意思:

     int totalSampledPixels = rWidth * rWidth;
     r /= totalSampledPixels;
     g /= totalSampledPixels;
     b /= totalSampledPixels;
    

    完全调整的草图:

    import processing.video.*;
    
    Capture webcam;
    Capture cap;
    PImage bg_img;
    
    color bgColor = color(0, 0, 0);
    
    int rMargin = 50;
    int rWidth = 100;
    int rHeight = 100;
    
    color input = color(0, 0, 0);
    color background = color(255, 255, 255);
    color current;
    int bgTolerance = 5;
    
    void setup() {
      size(1280,720);
    
      // start the webcam
      String[] inputs = Capture.list();
      if (inputs.length == 0) {
        println("Couldn't detect any webcams connected!");
        exit();
      }
      webcam = new Capture(this, inputs[0]);
    
      webcam.start();
    
    }
    
    
    void draw() {
      if (webcam.available()) {
    
        // read from the webcam
        webcam.read();
    
        image(webcam, 0,0);
        webcam.loadPixels();
    
        noFill();
        strokeWeight(2);
        stroke(255,255, 255);
        rect(rMargin, rMargin, rWidth, rHeight);
    
        int yCenter = (rWidth/2) + rMargin;
        int xCenter = (rWidth/2) + rMargin;
        // rectMode(CENTER);
    
        int rectCenterIndex = (width* yCenter) + xCenter;
    
        int r = 0, g = 0, b = 0;
    
        //for whole image:
        //for (int i=0; i<bg_img.pixels.length; i++) {
        //    color c = bg_img.pixels[i];
        //    r += c>>16&0xFF;
        //    g += c>>8&0xFF;
        //    b += c&0xFF;
        //}
        //r /= bg_img.pixels.length;
        //g /= bg_img.pixels.length;
        //b /= bg_img.pixels.length;
    
        //CALCULATE AVG COLOR:
        int i;
        for(int x = 0; x <= width; x++){
           for(int y = 0; y <= height; y++){
             if (x >= rMargin && x <= rMargin + rWidth && y >= rMargin && y <= rMargin + rHeight){
    
               i = (width*y) + x;
               color c = webcam.pixels[i];
               r += c>>16&0xFF;
               g += c>>8&0xFF;
               b += c&0xFF;
    
             }
           }
        }
        //divide by just the area sampled (x >= 50 && x <= 150 && y >= 50 && y <= 150 is a 100x100 px area) 
        int totalSampledPixels = rWidth * rHeight;
    
        r /= totalSampledPixels;
        g /= totalSampledPixels;
        b /= totalSampledPixels;
    
        fill(r,g,b);
        rect(rMargin + rWidth, rMargin, rWidth, rHeight);
    
        println(r + " " + g + " " + b);
      }
    }
    

    请记住,这是RGB颜色空间中的平均值,它与感知颜色空间不同。例如,如果你平均红色和黄色,你会期望橙色,但在RGB中,一点红色和绿色会变成黄色。

    希望RGB平均值足以满足您的需要,否则您可能需要将RGB转换为 CIE XYZ colour space 然后到 L a b colour space 计算感知平均值(然后转换回XYZ和RGB以在屏幕上显示)。如果你有兴趣尝试,你可以找到 older answer 在openFrameworks中演示这一点(您会注意到这可能类似于在简单场景中的处理)。