灰度图归一化方法JUnit测试像素比对失败求助
问题排查:GrayscaleImage.normalized方法逐像素断言失败
我实现了GrayscaleImage类的normalized方法,目标是通过统一缩放所有像素值,使新生成的灰度图平均亮度接近127。目前该方法能通过JUnit测试中的平均亮度断言,但逐像素的assertEquals断言始终失败——尽管打印显示新图像的平均亮度符合预期。
JUnit测试代码
@Test void normalized() { var smallNorm = smallSquare.normalized(); assertEquals(smallNorm.averageBrightness(), 127, 127 * .001); var scale = 127 / 2.5; var expectedNorm = new GrayscaleImage(new double[][] { { scale, 2 * scale }, { 3 * scale, 4 * scale } }); for (var row = 0; row < 2; row++) { for (var col = 0; col < 2; col++) { assertEquals(smallNorm.getPixel(col, row), expectedNorm.getPixel(col, row), expectedNorm.getPixel(col, row) * .001, "pixel at row: " + row + " col: " + col + " incorrect"); } } }
我的实现代码
/** * Return a new GrayScale image where the new average brightness is 127 * To do this, uniformly scale each pixel (ie, multiply each imageData entry by the same value) * Due to rounding, the new average brightness will not be 127 exactly, but should be very close * The original image should not be modified * @return a GrayScale image with pixel data uniformly rescaled so that its averageBrightness() is 127 */ public GrayscaleImage normalized() { // First we make a 2D array that is the same size as the original image. double[][] normalized2DArray = new double[imageData[0].length][imageData.length]; // Then we figure out what we need to multiply the pixel by to make sure our average brightness is equal to 127 double scaleFactor = 127 / averageBrightness(); // Then we will set the brightness of the specified pixel below. for (int y = 0; y < imageData[0].length; y++) { for (int x = 0; x < imageData.length; x++) { double newPixelValue = getPixel(y, x) * scaleFactor; normalized2DArray[y][x] = newPixelValue; } } // We will then turn the 2DArray into a GrayscaleImage GrayscaleImage normalizedImage = new GrayscaleImage(normalized2DArray); System.out.println(normalizedImage.averageBrightness()); return normalizedImage; }
JUnit测试失败输出

问题分析与修复方案
核心问题:数组维度与像素坐标完全错位
数组初始化错误
原imageData是[行数][列数]的二维数组结构,但你创建新数组时用了new double[imageData[0].length][imageData.length],直接把行和列的维度反转了,导致新数组的结构和测试预期完全不符。遍历与像素取值顺序错误
- 循环中
y遍历的是原数组的列数,x遍历的是原数组的行数,和常规的行优先遍历逻辑相反。 - 调用
getPixel(y, x)时参数顺序错误,通常getPixel的参数是(列, 行)(即x, y),你传递的顺序颠倒,导致取到的原像素值本身就是错的。
- 循环中
修正后的代码
public GrayscaleImage normalized() { // 保持和原数组一致的维度:行数×列数 double[][] normalized2DArray = new double[imageData.length][imageData[0].length]; double scaleFactor = 127 / averageBrightness(); // 行优先遍历:先遍历行,再遍历列 for (int y = 0; y < imageData.length; y++) { for (int x = 0; x < imageData[0].length; x++) { // 按照getPixel的定义传递正确的坐标:(列, 行) double newPixelValue = getPixel(x, y) * scaleFactor; normalized2DArray[y][x] = newPixelValue; } } GrayscaleImage normalizedImage = new GrayscaleImage(normalized2DArray); System.out.println(normalizedImage.averageBrightness()); return normalizedImage; }
验证逻辑
测试中的smallSquare原始像素应为{{1,2},{3,4}},平均亮度是2.5,缩放因子127/2.5和测试代码中的scale变量完全一致。修正后每个像素会被正确缩放,数组结构也和测试预期匹配,逐像素断言即可通过。
内容的提问来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

