forge/testScripts/ports/shotDiff.py
2026-10-06 16:57:52 -05:00

57 lines
2.5 KiB
Python
Executable file

#!/usr/bin/env python3
# The Picture row's check (FORGE.md 14.18): the screenshots an original and its port took at the
# same moments (compare.sh with PORT_SHOTS=N and SINGE_SHOTS=<dir>), paired by number, and how much
# of each picture differs. A pixel differs when any channel is more than TOLERANCE apart, since
# the two runs decode the same video but may round a scaled frame differently.
#
# testScripts/ports/shotDiff.py <shots dir> [<out dir>]
#
# prints one line a pair and a summary; with <out dir>, writes each pair side by side with the
# differing pixels marked in the third panel, for a person to look at.
import os
import re
import sys
import numpy
from PIL import Image
TOLERANCE = 24 # Per channel, out of 255: video rounding, not a missing prompt
MARK = (255, 0, 255)
PAIR = re.compile(r"^(original|port)-shot-((?:run\d+-)?\d+)-(\w+)\.png$")
def main():
shots = sys.argv[1] if len(sys.argv) > 1 else sys.exit("usage: shotDiff.py <shots dir> [<out dir>]")
out = sys.argv[2] if len(sys.argv) > 2 else None
found = {}
for name in os.listdir(shots):
match = PAIR.match(name)
if match:
found.setdefault((match.group(2), match.group(3)), {})[match.group(1)] = os.path.join(shots, name)
if out:
os.makedirs(out, exist_ok=True)
worst = 0.0
for (number, why), pair in sorted(found.items()):
if "original" not in pair or "port" not in pair:
print("%s %-6s only the %s took it" % (number, why, "original" if "original" in pair else "port"))
continue
a = numpy.asarray(Image.open(pair["original"]).convert("RGB"), dtype=numpy.int16)
b = numpy.asarray(Image.open(pair["port"]).convert("RGB"), dtype=numpy.int16)
if a.shape != b.shape:
print("%s %-6s sizes differ: %s and %s" % (number, why, a.shape, b.shape))
continue
differs = (numpy.abs(a - b) > TOLERANCE).any(axis=2)
percent = 100.0 * differs.mean()
worst = max(worst, percent)
print("%s %-6s %6.2f%% of the picture differs" % (number, why, percent))
if out:
marked = a.copy()
marked[differs] = MARK
side = numpy.concatenate([a, b, marked], axis=1).astype(numpy.uint8)
Image.fromarray(side).save(os.path.join(out, "%s-%s.png" % (number, why)))
print("%d pairs; the worst differs in %.2f%% of its picture" % (len(found), worst))
if __name__ == "__main__":
main()