我想使用Java计算两个图像之间的归一化互相关。
我的程序工作正常但是当我尝试在MATLAB中验证我的结果时,遗憾的是我没有得到与Java实现相同的结果。
这是我在MATLAB中执行的代码:
Img1 = rgb2gray(imread('image1.png'));
Img2 = rgb2gray(imread('image2.png'));
corr2(Img1, Img2);
这是我的Java实现的一部分。为了更好地理解,删除了一些类:
我不确定我的Java实现有什么问题。
我还有另一个问题。在MATLAB中,我必须在使用corr2
之前将图像转换为灰度。我是否需要在Java中执行相同的操作?
答案 0 :(得分:1)
之所以不相同,是因为您没有考虑PNG文件中的标题。
如果您查看Java代码,则会在readImage
方法中将图像作为字节流读取。对于PNG,涉及标题,例如图像的大小和每个像素的颜色位数。您不仅要抓取图像数据(顺便说一下,使用LZW版本进行压缩,以便您甚至不读取原始图像数据),而且还要抓取相关代码中收集的额外信息。 。
令人困惑的是,您正在使用相关代码开头的BufferedImage
类型读取图像,以获取行和列。为什么在readImage
方法中切换到使用字节流?
因此,您需要更改readImage
方法以接收BufferedImage
对象,或重新读取您在readImage
方法中的关联方法中所做的数据。完成后,使用BufferedImage
方法访问RGB像素。 FWIW,如果你在图像中读取灰度,那么每个通道应该给你相同的强度,这样你就可以单独在一个通道上操作。无关紧要......但要确保你在灰度图像上做相关。当你去上色时,它是模棱两可的,因为目前没有设定标准如何做到这一点。
使用BufferedImage
,您可以使用getRGB
方法在列x
和行y
获取所需的像素。 x
从左到右遍历,而y
从上到下遍历。当您调用getRGB
时,它将以ARGB格式返回单个32位整数。每个通道为8位。因此,前8位(MSB)是alpha值,后8位是红色,第3位是绿色,最后8位是蓝色。根据您想要的频道,您需要进行位移和掩盖您不需要的位来获得所需的值。
举个例子:
int rgb = img.getRGB(x, y);
int alpha = rgb >> 24 & 0xFF;
int red = rgb >> 16 & 0xFF;
int green = rgb >> 8 & 0xFF;
int blue = rgb & 0xFF;
对于alpha值,您需要向右移动24位以使其向下移动到LSB位置,然后使用0xFF
进行屏蔽以仅获得表示alpha值的8位。同样地,您可以对红色,绿色和蓝色通道执行相同操作。由于彩色图像的相关性相当不合适,因此我们可以在readImage
方法中将图像转换为灰度。因此,在运行此方法之前无需转换图像。我们将在方法本身内做到这一点,为您省去一些麻烦。
如果你看看MATLAB如何执行rgb2gray
,它会执行一个加权和,以不同的方式对通道进行加权。权重由SMPTE Rec. 601 standard定义(对于那些想知道我如何知道这一点的人,你可以看一下rgb2gray
的来源并读出他们转换矩阵的第一行这些系数基本上是601标准的定义。
以前版本的MATLAB简单地将所有频道相加,除以3并发言。我不知道您使用的是哪个版本的MATLAB,但为了安全起见,我将使用最新的转换。
public static void readImage(BufferedImage img, int array[][], int nrows, int ncols) {
for (int i = 0; i < nrows; i++)
for (int j = 0; j < ncols; j++) {
int rgb = img.getRGB(j, i);
int red = rgb >> 16 & 0xFF;
int green = rgb >> 8 & 0xFF;
int blue = rgb & 0xFF;
array[i][j] = (int) (0.299*((double)red) + 0.587*((double)green) +
0.114*((double)blue) );
}
}
这应该有希望给你你想要的东西!