【问题标题】:Getting two consecutive frames from camera in Processing在处理中从相机获取两个连续的帧
【发布时间】:2018-01-05 18:35:00
【问题描述】:

我一直在尝试使用 Processing 来实现这一目标的几种方法,但每次都没有得到一些完全连续的方法。有人知道这样做的“正确方法”吗?

提前致谢!

【问题讨论】:

  • 你能说得更具体些吗?当你说它不明白时,你到底是什么意思?它会得到什么?你能发一个minimal reproducible example吗?
  • @Malo Maisonneuve 这可能取决于镜头前发生的事情,对吧?如果没有运动,两个连续的帧将看起来相同。正如凯文所提到的,请更具体一些。 “完全连续”的帧对您意味着什么?
  • 这次我不能发布任何最小、完整和可验证的示例,因为我没有任何示例。我的问题比这更广泛。我只是想将摄像机实时记录的视频线程的两个连续帧存储在两个不同的变量中。在我所做的每一次尝试中,我要么得到两个不连续的帧,要么得到两个相同的帧。不是说没有任何动静,而是两幅画面上的摄像头噪点都是一样的。那么,您是否有任何关于可以做到这一点的一小段代码的想法? (我希望我很清楚,如果没有,请告诉我:)

标签: image video camera processing frames


【解决方案1】:

理论上,听captureEvent() 获取新帧并跟踪是否先前记录了第一帧,如果是之后记录第二帧,则应该是这样。

这是一个基本的注释草图来说明这一点(按任意键抓取另一对帧):

import processing.video.*;

Capture camera;

PImage firstFrame;
PImage secondFrame;

void setup(){
  size(1920,480);

  camera = new Capture(this,640,480);
  camera.start();
}
void draw(){
  image(camera,0,0);
  if(firstFrame != null){
    image(firstFrame,640,0);
  }
  if(secondFrame != null){
    image(secondFrame,1280,0);
  }
}
//this is the callback from the video library when a new camera frame is available
void captureEvent(Capture c){
  //read a new frame
  c.read();
  //if the first frame wasn't recorded yet, record(copy) it's pixels
  if(firstFrame == null){
    firstFrame = c.get();
  }
  //same for the second frame, but check if the first frame has been recorded first
  if(firstFrame != null && secondFrame == null){
    secondFrame = c.get();
  }
}

void keyPressed(){
  //reset consecutive frames on keypress
  firstFrame = secondFrame = null;
}

理论上(正如您在Processing Video Library's source code 中看到的那样),仅当新的相机样本准备好时才会触发 captureEvent。 在实践中,您会发现两个连续的帧可能看起来相同(即使它们在时间上可能相差一秒),甚至是您在 cmets 中指出的噪声。

感觉你所追求的是一个连续的帧,但与前一个足够不同。如果是这种情况,您可以使用FrameDifferencing exampleProcessing > Examples > Libraries > Video > Capture > FrameDifferencing

这是上述草图的修改版本,使用 Golan Levin 的 FrameDifferencing 代码仅在略有不同时抓取第二帧:

import processing.video.*;

Capture camera;

PImage firstFrame;
PImage secondFrame;
PImage diff;

void setup(){
  size(1920,960);

  camera = new Capture(this,640,480);
  camera.start();

  diff = createImage(640,480,RGB);
}
void draw(){
  image(camera,0,0);
  if(firstFrame != null){
    image(firstFrame,640,0);
  }
  if(secondFrame != null){
    image(secondFrame,1280,0);
  }
  image(diff,0,480);
}
//this is the callback from the video library when a new camera frame is available
void captureEvent(Capture c){
  //read a new frame
  c.read();
  //if the first frame wasn't recorded yet, record(copy) it's pixels
  if(firstFrame == null){
    firstFrame = c.get();
    println("recorded first frame at",new java.util.Date());
  }
  //same for the second frame, but check if the first frame has been recorded first
  if(firstFrame != null && secondFrame == null){
    //if the difference between the first frame cand the current frame is even ever so slightly off, record the second frame
    if(difference(firstFrame,camera) > 100){
      secondFrame = c.get();
    }
  }

}

int difference(PImage first,PImage second){
  final int numPixels = 640*480;
  camera.loadPixels();
  int movementSum = 0; // Amount of movement in the frame
  for (int i = 0; i < numPixels; i++) { // For each pixel in the video frame...
    color currColor = first.pixels[i];
    color prevColor = second.pixels[i];
    // Extract the red, green, and blue components from current pixel
    int currR = (currColor >> 16) & 0xFF; // Like red(), but faster
    int currG = (currColor >> 8) & 0xFF;
    int currB = currColor & 0xFF;
    // Extract red, green, and blue components from previous pixel
    int prevR = (prevColor >> 16) & 0xFF;
    int prevG = (prevColor >> 8) & 0xFF;
    int prevB = prevColor & 0xFF;
    // Compute the difference of the red, green, and blue values
    int diffR = abs(currR - prevR);
    int diffG = abs(currG - prevG);
    int diffB = abs(currB - prevB);
    // Render the difference image to the screen
    diff.pixels[i] = color(diffR, diffG, diffB);
    // Add these differences to the running tally
    movementSum += diffR + diffG + diffB;
  }
  diff.updatePixels();
  return movementSum;
}

void keyPressed(){
  //reset consecutive frames on keypress
  firstFrame = secondFrame = null;
}

在上面的例子中,100 是一个任意值。 最大值为 255*3*640*480(每个通道 0-255 * 通道数 * 宽度 * 高度)

【讨论】:

    【解决方案2】:

    我看了科泰相机sourcesissue reports,尤其是this one。不幸的是,此代码不是为提供实时相机帧而构建的。

    你可以尝试以AndroidCapture项目为starter,修改原生Androidclass来达到你的目的。

    【讨论】:

    • 我实际上并没有使用他的相机,因为它更像是一台使用网络摄像头的电脑。但是这个问题是普遍的,还是只适用于这个特定的相机功能 KetaiCamera(我尝试在处理中使用 Capture 功能)?
    • 如果我正确解读this discussion,那么没有现成的类可以跟上Android相机的真实帧率。您应该查看 AndroidCapture 类,但要可靠地生成帧,您必须卷起虚拟袖子并使用 Android SDK 构建专用实现。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-27
    • 1970-01-01
    • 2013-07-28
    相关资源
    最近更新 更多