Java 出于运动检测目的比较两幅图像

Java 出于运动检测目的比较两幅图像,java,android,detection,motion,getpixel,Java,Android,Detection,Motion,Getpixel,我已经开始用一个简单的算法计算不同像素的数量来区分两幅图像: private int returnCountOfDifferentPixels(String pic1, String pic2) { Bitmap i1 = loadBitmap(pic1); Bitmap i2 = loadBitmap(pic2); int count=0; for (int y = 0; y < i1.getHeight(); +

我已经开始用一个简单的算法计算不同像素的数量来区分两幅图像:

private int returnCountOfDifferentPixels(String pic1, String pic2)
    {
        Bitmap i1 = loadBitmap(pic1);
        Bitmap i2 = loadBitmap(pic2);
        int count=0;

        for (int y = 0; y < i1.getHeight(); ++y)
               for (int x = 0; x < i1.getWidth(); ++x)
                    if (i1.getPixel(x, y) != i2.getPixel(x, y)) 
                        {
                        count++;
                        }

          return count;

    }
private int返回不同像素的计数(字符串pic1、字符串pic2)
{
位图i1=加载位图(pic1);
位图i2=加载位图(pic2);
整数计数=0;
对于(int y=0;y
然而,这种方法在初始形式上似乎效率低下,因为即使在非常相似的照片中,也总是存在大量不同的像素。 我在想一种方法来确定两个像素是否真的那么不同。 android的bitmap.getpixel(x,y)返回一个颜色对象


如何在两个颜色对象之间实现适当的区分,以帮助我进行运动检测?

你是对的,因为噪声和其他因素,视频流中通常会有大量原始像素变化。以下是您可能需要考虑的一些选项:

  • 首先模糊图像,理想情况下使用高斯滤波器或简单的方块滤波器。这只意味着您对相邻像素和像素本身进行(加权)平均。这将大大降低传感器噪声

  • 如果大于某个阈值,则仅将差值添加到
    计数中。这样做的效果是只考虑真正改变了很多的像素。这很容易实现,并且可能已经单独解决了您的问题

  • 考虑一下,首先尝试这两种选择。如果不行,我可以给你更多的选择

    编辑:我刚刚看到,您实际上并不是在总结差异,而是在计算不同的像素。如果您将其与选项2结合使用,这是很好的。选项1仍然有效,但它可能是一种过度使用

    此外,要找出两种颜色之间的差异,请使用以下方法:

    现在,您可以提出一个阈值
    totalDiff
    必须超过该阈值才能对
    计数作出贡献

    当然,你可以用不同的方式处理这些数字。例如,上面的代码仅计算像素强度(亮度)的变化。如果您还想考虑色调和饱和度的变化,则必须计算
    totalDiff
    ,如下所示:

    int totalDiff = Math.abs(Color.red(p1) - Color.red(p2)) + Math.abs(Color.green(p1) - Color.green(p2)) + Math.abs(Color.blue(p1) - Color.blue(p2));
    

    另外,看看其他的
    Color
    方法,例如
    RGBToHSV(…)

    ,我知道这基本上与这里的另一个答案非常相似,但我认为以不同的形式重复它可能对寻求解决方案的人很有用。这涉及到随着时间的推移有两个以上的图像。如果你只是字面意思,那么这将不起作用,但一个等价的方法会起作用

    对每个帧上的所有像素执行历史记录。例如,对于每个像素:
    history[x,y]=(history[x,y]*(w-1)+获取像素(x,y))/w

    其中
    w
    可能是
    w=20
    w
    越高,运动峰值越大,但必须缺少较长的运动才能重置

    然后,要确定是否有变化,可以对每个像素执行此操作:

    changed_delta=abs(历史[x,y]-获取像素(x,y))

    total_delta+=已更改的_delta

    你会发现它稳定了大部分噪音,当运动发生时,你会得到很大的不同。实际上,您正在获取多个帧,并根据最新帧从多个帧中检测运动


    也就是说,为了检测运动的位置,可以把图像分解成小块,然后单独进行。然后,您可以通过将单个图像视为单独图像的网格来查找对象并在屏幕上跟踪它们。

    我想知道,计算满足某个阈值的像素是什么意思。我如何确定一个像素是否值得进入这个领域?我在答案中添加了解释,希望现在更清楚。如果没有,请告诉我。这方面有什么更新吗?你根据我的回答做了些什么吗?很抱歉,我马上就要开始实施你的想法了,我会告诉你进展如何。这看起来效果很好。我使用了inttotaldiff=Math.abs(Color.red(p1)-Color.red(p2)+Color.green(p1)-Color.green(p2)+Color.blue(p1)-Color.blue(p2));经过一些调整后,我认为这个色差中的一个合适数字应该是50。这确实会返回更少的不同像素,使其实际工作。我只是想通过数字来获得最佳的运动检测,我想:-)谢谢你的回答。颜色应该和。相等()比较。不?
    int totalDiff = Math.abs(Color.red(p1) - Color.red(p2)) + Math.abs(Color.green(p1) - Color.green(p2)) + Math.abs(Color.blue(p1) - Color.blue(p2));