【问题标题】:What would be a good algorithm to find image shifts (Java)什么是找到图像偏移的好算法(Java)
【发布时间】:2013-05-30 18:20:43
【问题描述】:

我有一个摄像头,我从它接收每个帧的 ByteBuffer。我从 ByteBuffer 中提取 640px x 480px 11 位灰度图像并将其保存到一个短 [640] [480] 中。我这样做是因为我不需要它作为图像并且我认为这会更快(如果我错了请纠正我)。

现在每秒大约执行 30 次。对于每一帧,程序会将任何相差超过 20 且小于当前像素的现有值的值保存到该像素的值中。它有效地在我的 short[640][480] 中创建了背景图像。

现在的问题是,相机可能会移动,从而改变背景。我从一个不动的相机得到的背景已经改变了很多(也有很大的边距)每一帧。实际上,它仅足够稳定以提取大型前景对象。所以我需要一个算法来告诉我相机和图像发生了多少变化,所以我知道图像中哪些区域是新的,但大多数区域仍然可用。

我能想到的唯一方法是扫描图像以查找每个可能的班次,看看哪个最匹配,因为就像我说的那样,它可能无法完全匹配,但仍然是最佳匹配。有没有更好的方法来解决这个问题?因为这样我必须每帧扫描整个图像大约 120 万次......

此外,我不使用处理或 openCV 或任何此类库。

编辑: 我忘了提到一个非常重要的细节,图像是深度图,所以光照不会影响它。

编辑:这是一些代码,我使用 Open Kinect 库从 Kinect 检索深度图。我还不确定如何解析信息,这是迄今为止我让它工作的唯一方法:

public static short[][] background = new short[640][480];

public void onFrameReceived(FrameMode format, ByteBuffer frame, int timestamp) {

    for(int n=0; n<frame.limit()/2; n++) {

        int index = n*2;
        short Gray = (0xff - frame.get(index) & 0xff) | ((3-frame.get(index+1) & 0x3) * 255);

        short x = n%640;
        short y = n/640;

        if(background[x][y] > Gray + 10 || background[x][y] == 0) {
            background[x][y] = Gray;
        }
    }
}

我每帧得到 2 个字节,我尝试从中提取一个 11 位值,该值表示对象与我的 kinect 的距离。我不知道该怎么做,但它的工作原理是这样的,所以我将把这个问题留到以后。

附加信息:frame.limit() 是字节缓冲区中的字节数。 frame.get 从我的字节缓冲区中获取一个字节。由于某种原因,kinect 以倒序向我发送字节...

【问题讨论】:

  • 在场景中的某处放置一个小光源(点标记)以简化移位检测是否可行?
  • 不幸的是,它必须在很多不同的环境中工作,关于背景几乎不能说。另外,它是一张深度图。
  • 我不是专家,但我想我会通过对图像的 4 个角加上中心进行采样来解决此问题,并查看是否在现有图像中找到匹配项。您的样本需要足够大以排除某些东西从角落框架中移出,但要足够小以使其快速。为了排除相机光圈的光照变化或一般光照的变化,我会使用从最亮到最暗的百分比进行匹配。
  • @CodeChimp 的问题是你怎么知道相机是向左还是向右移动?如果它向右移动,左边的角会消失,右边的角会是新的,如果背景足够平淡,所有这些都将是彼此无法确定的。

标签: java algorithm image-processing computer-vision video-processing


【解决方案1】:

这就是我确定相机是否移动的方式。当然,“detectChange()”中会添加一些填充和方差,但由于我不熟悉您的数据结果,因此无法确定:

//pick 100 points at random
private static Point[] keys = new Point[100];

//initially set to the values of background at the key points
private static short[] keyValues = new short[100];


private bool detectChange()
{
    boolean changed = false;
    int amtchanged = 0;
    for(int i = 0; i < 100; i++)
    {
        //point some variance here for leeway
        if(background[keys[i].x][keys[i].y] != keyValues[i])
            amtchanged++;
    }

    if(amtchanged > 75)
        changed = true;

    return changed
}

public void onFrameReceived(FrameMode format, ByteBuffer frame, int timestamp) {

    if(detectChange())
    {
        //find where they went to determine
        //the camera's pan
    }

    //the rest of your code.

    for(int i = 0; i < 100; i++)
    {
        //update the keys to the new data
        keyValues[i] = background[keys[i].x][keys[i].y];
    }
}

【讨论】:

  • 感谢您的努力,因为我会尽可能地 +1(如果有的话)。无论哪种方式,我都决定在这个上另辟蹊径。
【解决方案2】:

您应该使用图像库,它会比您自己的实现更容易、更健壮和更高效。为了检测背景偏移,我会计算图像的梯度并将其与前一个进行比较。模糊图像可能很有趣。您可以使用二次函数来比较前一个梯度和当前梯度之间的误差。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-27
    • 1970-01-01
    • 2010-10-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多