以实用的方式存储来自计算出的光流的运动矢量,从而能够从初始关键帧重建后续帧
Storing motion vectors from calculated optical flow in a practical way which enables reconstruction of subsequent frames from initial keyframes
我正在尝试存储从视频序列中的帧的光流中检测到的运动,然后使用这些存储的运动向量来仅使用第一帧作为参考来预测已知的帧。我目前正在使用两个处理草图——第一个草图为每个像素网格(每个宽度和高度 10 个像素)绘制一个运动矢量。这是为视频序列中的每一帧完成的。如果检测到足够的运动,则矢量仅绘制在网格中。第二个草图旨在从视频序列的初始帧结合从第一个草图获得的运动矢量信息粗略地重建视频帧。
到目前为止,我的方法如下:我能够从四个变量中确定第一个草图中绘制的每个运动矢量的大小、位置和方向。通过创建四个数组(两个用于运动矢量的 x 和 y 坐标,另外两个用于其在 x 和 y 方向上的长度),每次绘制运动矢量时,我都可以将四个变量中的每一个附加到上述数组。这是针对绘制矢量的整个帧中的每个像素网格以及序列中的每个帧(通过 for 循环)完成的。一旦数组已满,我就可以将它们作为字符串列表保存到文本文件中。然后我将这些字符串从文本文件加载到第二个草图中,连同视频序列的第一帧。我在 draw 函数的 while 循环中将字符串加载到变量中,并将它们转换回浮点数。每次调用 draw 函数时,我都会将一个变量递增一个 - 这将移动到下一帧(我在我的文本文件中使用了一个特定的数字作为分隔符,它出现在每一帧的末尾 - 循环搜索这个数字然后将变量递增 1,从而打破 while 循环并为后续帧再次调用 draw 函数)。对于每一帧,我可以绘制 10 x 10 像素框,然后根据从第一个草图中的文本文件中获取的参数移动。我的问题很简单:如何绘制特定帧的运动,而不让我在前一帧中对屏幕进行 blit 的内容影响下一帧的绘制内容。我获得 10 x 10 像素框的唯一方法是使用 get() 函数获取已经绘制到屏幕上的像素。
对于我的问题的长度和复杂性深表歉意。任何提示将不胜感激!我将为第二个草图添加代码。如果需要,我也可以添加第一个草图,但它相当长,而且很多不是我自己的。这是第二个草图:
import processing.video.*;
Movie video;
PImage [] naturalMovie = new PImage [0];
String xlengths [];
String ylengths [];
String xpositions [];
String ypositions [];
int a = 0;
int c = 0;
int d = 0;
int p;
int gs = 10;
void setup(){
size(640, 480, JAVA2D);
xlengths = loadStrings("xlengths.txt");
ylengths = loadStrings("ylengths.txt");
xpositions = loadStrings("xpositions.txt");
ypositions = loadStrings("ypositions.txt");
video = new Movie(this, "sample1.mov");
video.play();
rectMode(CENTER);
}
void movieEvent(Movie m) {
m.read();
PImage f = createImage(m.width, m.height, ARGB);
f.set(0, 0, m);
f.resize(width, height);
naturalMovie = (PImage []) append(naturalMovie, f);
println("naturalMovie length: " + naturalMovie.length);
p = naturalMovie.length - 1;
}
void draw() {
if(naturalMovie.length >= p && p > 0){
if (c == 0){
image(naturalMovie[0], 0, 0);
}
d = c;
while (c == d && c < xlengths.length){
float u, v, x0, y0;
u = float(xlengths[a]);
v = float(ylengths[a]);
x0 = float(xpositions[a]);
y0 = float(ypositions[a]);
if (u != 1.0E-19){
//stroke(255,255,255);
//line(x0,y0,x0+u,y0+v);
PImage box;
box = get(int(x0-gs/2), int(y0 - gs/2), gs, gs);
image(box, x0-gs/2 +u, y0 - gs/2 +v, gs, gs);
if (a < xlengths.length - 1){
a += 1;
}
}
else if (u == 1.0E-19){
if (a < xlengths.length - 1){
c += 1;
a += 1;
}
}
}
}
}
明智的话:大多数人不会阅读那堵文字墙。尝试 "dumb down" 您的 post 以便他们立即了解详细信息,而无需任何额外信息。如果您 post 一个 MCVE 而不是只给我们一半的代码,您也会过得更好。请注意,这 而不是 意味着 post 您的整个项目。相反,从一个空白的草图开始,只创建显示问题所需的最基本的代码。不要包含任何电影逻辑,并尽可能进行硬编码。我们应该能够将您的代码复制并粘贴到我们自己的机器上 运行 并查看问题。
说了这么多,我想我明白你在问什么了。
How do I draw the motion of a particular frame without letting what I've have blitted to the screen in the previous frame affect what will be drawn for the next frame. My only way of getting my 10 by 10 pixel box is by using the get() function which gets pixels that are already drawn to the screen.
将您的程序分成 view 和 model。现在你正在使用屏幕(视图)来存储你所有的信息,这会让你头疼。相反,将程序的 state 存储到一组变量(模型)中。对于您来说,这可能只是一堆 PVector
个实例。
假设我有一个 ArrayList<PVector>
保存我所有向量的当前位置:
ArrayList<PVector> currentPositions = new ArrayList<PVector>();
void setup() {
size(500, 500);
for (int i = 0; i < 100; i++) {
currentPositions.add(new PVector(random(width), random(height)));
}
}
void draw(){
background(0);
for(PVector vector : currentPositions){
ellipse(vector.x, vector.y, 10, 10);
}
}
请注意,我只是将他们的位置硬编码为随机的。这也是您的 MCVE 应该做的。然后在 draw()
函数中,我只是简单地绘制每个向量。这就像给你画了一个框架。
现在我们已经有了,我们可以创建一个 nextFrame()
函数,它根据 ArrayList
(我们的模型)而不是屏幕上绘制的内容来移动向量!
void nextFrame(){
for(PVector vector : currentPositions){
vector.x += random(-2, 2);
vector.y += random(-2, 2);
}
}
同样,我只是对随机运动进行硬编码,但您会从文件中读取这些内容。然后我们就调用nextFrame()
函数作为draw()
函数的最后一行:
如果您仍然遇到问题,我强烈建议您 post 使用与我的类似的 MCVE 并 post 使用一个新问题。祝你好运。
我正在尝试存储从视频序列中的帧的光流中检测到的运动,然后使用这些存储的运动向量来仅使用第一帧作为参考来预测已知的帧。我目前正在使用两个处理草图——第一个草图为每个像素网格(每个宽度和高度 10 个像素)绘制一个运动矢量。这是为视频序列中的每一帧完成的。如果检测到足够的运动,则矢量仅绘制在网格中。第二个草图旨在从视频序列的初始帧结合从第一个草图获得的运动矢量信息粗略地重建视频帧。
到目前为止,我的方法如下:我能够从四个变量中确定第一个草图中绘制的每个运动矢量的大小、位置和方向。通过创建四个数组(两个用于运动矢量的 x 和 y 坐标,另外两个用于其在 x 和 y 方向上的长度),每次绘制运动矢量时,我都可以将四个变量中的每一个附加到上述数组。这是针对绘制矢量的整个帧中的每个像素网格以及序列中的每个帧(通过 for 循环)完成的。一旦数组已满,我就可以将它们作为字符串列表保存到文本文件中。然后我将这些字符串从文本文件加载到第二个草图中,连同视频序列的第一帧。我在 draw 函数的 while 循环中将字符串加载到变量中,并将它们转换回浮点数。每次调用 draw 函数时,我都会将一个变量递增一个 - 这将移动到下一帧(我在我的文本文件中使用了一个特定的数字作为分隔符,它出现在每一帧的末尾 - 循环搜索这个数字然后将变量递增 1,从而打破 while 循环并为后续帧再次调用 draw 函数)。对于每一帧,我可以绘制 10 x 10 像素框,然后根据从第一个草图中的文本文件中获取的参数移动。我的问题很简单:如何绘制特定帧的运动,而不让我在前一帧中对屏幕进行 blit 的内容影响下一帧的绘制内容。我获得 10 x 10 像素框的唯一方法是使用 get() 函数获取已经绘制到屏幕上的像素。
对于我的问题的长度和复杂性深表歉意。任何提示将不胜感激!我将为第二个草图添加代码。如果需要,我也可以添加第一个草图,但它相当长,而且很多不是我自己的。这是第二个草图:
import processing.video.*;
Movie video;
PImage [] naturalMovie = new PImage [0];
String xlengths [];
String ylengths [];
String xpositions [];
String ypositions [];
int a = 0;
int c = 0;
int d = 0;
int p;
int gs = 10;
void setup(){
size(640, 480, JAVA2D);
xlengths = loadStrings("xlengths.txt");
ylengths = loadStrings("ylengths.txt");
xpositions = loadStrings("xpositions.txt");
ypositions = loadStrings("ypositions.txt");
video = new Movie(this, "sample1.mov");
video.play();
rectMode(CENTER);
}
void movieEvent(Movie m) {
m.read();
PImage f = createImage(m.width, m.height, ARGB);
f.set(0, 0, m);
f.resize(width, height);
naturalMovie = (PImage []) append(naturalMovie, f);
println("naturalMovie length: " + naturalMovie.length);
p = naturalMovie.length - 1;
}
void draw() {
if(naturalMovie.length >= p && p > 0){
if (c == 0){
image(naturalMovie[0], 0, 0);
}
d = c;
while (c == d && c < xlengths.length){
float u, v, x0, y0;
u = float(xlengths[a]);
v = float(ylengths[a]);
x0 = float(xpositions[a]);
y0 = float(ypositions[a]);
if (u != 1.0E-19){
//stroke(255,255,255);
//line(x0,y0,x0+u,y0+v);
PImage box;
box = get(int(x0-gs/2), int(y0 - gs/2), gs, gs);
image(box, x0-gs/2 +u, y0 - gs/2 +v, gs, gs);
if (a < xlengths.length - 1){
a += 1;
}
}
else if (u == 1.0E-19){
if (a < xlengths.length - 1){
c += 1;
a += 1;
}
}
}
}
}
明智的话:大多数人不会阅读那堵文字墙。尝试 "dumb down" 您的 post 以便他们立即了解详细信息,而无需任何额外信息。如果您 post 一个 MCVE 而不是只给我们一半的代码,您也会过得更好。请注意,这 而不是 意味着 post 您的整个项目。相反,从一个空白的草图开始,只创建显示问题所需的最基本的代码。不要包含任何电影逻辑,并尽可能进行硬编码。我们应该能够将您的代码复制并粘贴到我们自己的机器上 运行 并查看问题。
说了这么多,我想我明白你在问什么了。
How do I draw the motion of a particular frame without letting what I've have blitted to the screen in the previous frame affect what will be drawn for the next frame. My only way of getting my 10 by 10 pixel box is by using the get() function which gets pixels that are already drawn to the screen.
将您的程序分成 view 和 model。现在你正在使用屏幕(视图)来存储你所有的信息,这会让你头疼。相反,将程序的 state 存储到一组变量(模型)中。对于您来说,这可能只是一堆 PVector
个实例。
假设我有一个 ArrayList<PVector>
保存我所有向量的当前位置:
ArrayList<PVector> currentPositions = new ArrayList<PVector>();
void setup() {
size(500, 500);
for (int i = 0; i < 100; i++) {
currentPositions.add(new PVector(random(width), random(height)));
}
}
void draw(){
background(0);
for(PVector vector : currentPositions){
ellipse(vector.x, vector.y, 10, 10);
}
}
请注意,我只是将他们的位置硬编码为随机的。这也是您的 MCVE 应该做的。然后在 draw()
函数中,我只是简单地绘制每个向量。这就像给你画了一个框架。
现在我们已经有了,我们可以创建一个 nextFrame()
函数,它根据 ArrayList
(我们的模型)而不是屏幕上绘制的内容来移动向量!
void nextFrame(){
for(PVector vector : currentPositions){
vector.x += random(-2, 2);
vector.y += random(-2, 2);
}
}
同样,我只是对随机运动进行硬编码,但您会从文件中读取这些内容。然后我们就调用nextFrame()
函数作为draw()
函数的最后一行:
如果您仍然遇到问题,我强烈建议您 post 使用与我的类似的 MCVE 并 post 使用一个新问题。祝你好运。