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

时间:2018-03-07 20:18:19

标签: colors processing average webcam

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

结果是我不断变色(0,0,0),黑色。

谢谢大家!

PS抱歉,如果我的代码看起来很乱......我是Processing的新手,所以我不知道这可能是难以阅读还是包含不良做法。谢谢。

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 个答案:

答案 0 :(得分:0)

你如此接近,但遗漏了一个重要方面:你正在采样的像素数。

请注意,在为完整图像注释掉的示例代码中,您需要除以完整的像素数(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然后转换为Lab colour space以计算感知平均值(然后转换回XYZ和RGB显示在屏幕上)。如果这是您有兴趣尝试的内容,您可以在openFrameworks中找到older answer来证明这一点(您会注意到它与简单方案中的处理类似)。