You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

灰度图归一化方法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测试失败输出

JUnit测试失败输出


问题分析与修复方案

核心问题:数组维度与像素坐标完全错位

  1. 数组初始化错误
    原imageData是[行数][列数]的二维数组结构,但你创建新数组时用了new double[imageData[0].length][imageData.length],直接把行和列的维度反转了,导致新数组的结构和测试预期完全不符。

  2. 遍历与像素取值顺序错误

    • 循环中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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 20:20:27