Files
MAG160C/tools/StripeCheck.java
T
ZXCLI 948c9d5d3d tools: 照片差异定位三件套(帧剖面 / NUC 直出 / 条纹量化)+ 忽略 .tmp-* 对比目录
为"我们的照片与官方照片到底差在哪"提供可量化的手段,而不是靠肉眼看图:

- FrameProfile:对 160x120 载荷算行/列均值的步进与 3 抽头高频,并给出
  「列高频 / 行高频」比值——列固定图案噪声会表现为该比值显著 >1,场景内容则接近 1。
  同时对压缩块与"官方布局"(DDT 头 + 884B BasePara + 帧)都能定位载荷。
- NucDump:把 NUC 块按线性映射直出 PNG,用来判断成品图里的结构是"数据里有"
  还是"显示级引入的"。
- StripeCheck:在成品图的平坦区域量列抖动,并给出它占局部量程的百分比。

实测结论(本轮):我们的原始帧列高频 675 counts(列噪声主导,符合未校正预期),
而我们的 NUC 块只有 4.1 counts、行/列比 1.25,且成品图上平坦区列抖动仅为局部量程的
0.1% —— 即**校正后没有残留列噪声**,肉眼以为的竖纹是场景纹理。官方的成品帧(其文件
存的是校正后数据)同样干净(colHF 5.5、比值 1.39),两边校正质量等价。

.tmp-*/ 加入忽略:对比用的用户照片与中间产物放在那里,不入库。
2026-10-06 00:46:27 +08:00

26 lines
1.2 KiB
Java

import java.awt.image.BufferedImage;
import java.io.File;
import javax.imageio.ImageIO;
/** Column-jitter (stripe) amplitude inside a flat region of a rendered photo. */
public class StripeCheck {
public static void main(String[] a) throws Exception {
BufferedImage im = ImageIO.read(new File(a[0]));
int x0 = Integer.parseInt(a[1]), y0 = Integer.parseInt(a[2]);
int w = Integer.parseInt(a[3]), h = Integer.parseInt(a[4]);
double[] col = new double[w];
double lo = 255, hi = 0;
for (int y = y0; y < y0 + h; y++)
for (int x = x0; x < x0 + w; x++) {
int c = im.getRGB(x, y);
int l = (((c >> 16) & 0xFF) * 299 + ((c >> 8) & 0xFF) * 587 + (c & 0xFF) * 114) / 1000;
col[x - x0] += l; if (l < lo) lo = l; if (l > hi) hi = l;
}
for (int i = 0; i < w; i++) col[i] /= h;
double hf = 0; int n = 0;
for (int i = 1; i < w - 1; i++) { hf += Math.abs(col[i] - (col[i-1] + col[i+1]) / 2); n++; }
hf /= n;
System.out.printf("%-28s region %dx%d luma %.0f..%.0f (range %.0f) colJitter=%.2f = %.1f%% of local range%n",
new File(a[0]).getName(), w, h, lo, hi, hi - lo, hf, 100 * hf / Math.max(1, hi - lo));
}
}