From f2966f123df6f67ab70794e3dff87b302437d6ed Mon Sep 17 00:00:00 2001 From: CrbnsCat10n Date: Wed, 13 May 2026 14:28:34 +0800 Subject: [PATCH] new file: PreProcessing/.gitignore new file: PreProcessing/README.md new file: PreProcessing/scripts/compare_manual_matrix17.py new file: PreProcessing/scripts/draw_matrix17.py modified: PreProcessing/scripts/process_characters.py new file: PreProcessing/scripts/run_preprocessing.py --- PreProcessing/.gitignore | 14 + PreProcessing/README.md | 49 + .../篆文字_page_017_text_17_comparison.png | Bin 63921 -> 106471 bytes .../篆文字_page_017_text_17_cleaned.png | Bin 12031 -> 10124 bytes .../篆文字_page_017_text_17_pixelated.png | Bin 8409 -> 7349 bytes .../scripts/compare_manual_matrix17.py | 237 ++++ PreProcessing/scripts/draw_matrix17.py | 364 ++++++ PreProcessing/scripts/process_characters.py | 1065 ++++++++++++++++- PreProcessing/scripts/run_preprocessing.py | 143 +++ .../篆文字_page_017_text_17_pixelated.svg | 186 +-- 10 files changed, 1890 insertions(+), 168 deletions(-) create mode 100644 PreProcessing/.gitignore create mode 100644 PreProcessing/README.md create mode 100644 PreProcessing/scripts/compare_manual_matrix17.py create mode 100644 PreProcessing/scripts/draw_matrix17.py create mode 100644 PreProcessing/scripts/run_preprocessing.py diff --git a/PreProcessing/.gitignore b/PreProcessing/.gitignore new file mode 100644 index 0000000..ce78dca --- /dev/null +++ b/PreProcessing/.gitignore @@ -0,0 +1,14 @@ +# Generated preprocessing outputs +comparisons/ +manual_diffs/ +manual_matrices/ +original_characters/ +processed_characters/ +svg_characters/ +out_cleaned/ +out_matrix/ + +# Local caches +.matplotlib-cache/ +scripts/__pycache__/ +*.pyc diff --git a/PreProcessing/README.md b/PreProcessing/README.md new file mode 100644 index 0000000..cf117dc --- /dev/null +++ b/PreProcessing/README.md @@ -0,0 +1,49 @@ +# PreProcessing 预处理 + +这个目录包含17*17型特殊种类篆文字图像的预处理流程。日常批量处理请使用 `scripts/run_preprocessing.py`。 + +## 脚本用法 + +依赖见 `scripts/requirements.txt`。如果环境里还没有安装,可以先运行: + +```bash +.venv/bin/pip install -r PreProcessing/scripts/requirements.txt +``` + +从项目根目录运行: + +```bash +.venv/bin/python PreProcessing/scripts/run_preprocessing.py \ + --input-dir PreProcessing/original_characters \ + --cleaned-dir PreProcessing/out_cleaned \ + --matrix-dir PreProcessing/out_matrix +``` + +参数含义: + +- `--input-dir`:原始图像输入文件夹 +- `--cleaned-dir`:cleaned 二值图输出文件夹 +- `--matrix-dir`:17x17 矩阵文本输出文件夹 + +输出命名会和输入文件名对齐: + +- cleaned 图像:`原文件名_cleaned.png` +- 矩阵文本:`原文件名_matrix.txt` + +矩阵文本是纯 17 行,每行 17 个字符,只包含 `0` 和 `1`。 + +## 可选调参 + +默认参数会输出 17x17 矩阵。必要时可以追加这些参数: + +- `--grid-size`,默认 `17` +- `--cell-samples`,默认 `32` +- `--open-kernel-size` +- `--close-kernel-size` +- `--median-size` +- `--min-component-area` +- `--triangle-threshold` + +## 目录说明 + +`comparisons/`、`manual_diffs/`、`manual_matrices/`、`processed_characters/`、`svg_characters/` 等测试和比较用目录已经在 `PreProcessing/.gitignore` 中忽略。 diff --git a/PreProcessing/comparisons/篆文字_page_017_text_17_comparison.png b/PreProcessing/comparisons/篆文字_page_017_text_17_comparison.png index 57a69020609d36f742430dd0f5b96cb7224ef9a0..ce2ee5ef67512604a557c292351f09597df3e319 100644 GIT binary patch literal 106471 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 literal 63921 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

fx@d7HL^A{zxxo%cgNo!b?I65SPX9N)l1a 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 R*@M1$(d!MX1$W>a|efNA(;* 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 literal 12031 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 W{WVt)PLN-=YjTTnE-QX>^#1|}IQd8b diff --git a/PreProcessing/processed_characters/篆文字_page_017_text_17_pixelated.png b/PreProcessing/processed_characters/篆文字_page_017_text_17_pixelated.png index 3a8ebda2bc08063bc0491a11720289a2da107f8c..e83df3a21b490acfdd1ae4997a52c697c7d94d44 100644 GIT binary patch literal 7349 zcmeAS@N?(olHy`uVBq!ia0y~yU^)cEvpIkQ47Yx4wqjtAsqu7i45?szd+=Z{izClr z2d)1LDkUX8?M;(j*EQ$!X{G0XHl48CuTykRznjY3<^r=Ng6GkCj6XPhu^g%tjq1%a{5`*RtzQW&)qTwM;f;Du&bU{u{#f#+FJo}7)yw!rjJGZ~R{ zf$1ZE5VR@U={hK7EwR$(MME{z=kWhTLi2bKkY+Qi}%Fg z74eDRh*}ufwuN-HfK~8&Zg~AWYB+_#GTP=GnrARqyQ5vaA=Nnrj>`f2WTVvz zWMmT92_1a3?dUkkARj)O;{+NZ0S$a?IH3t1@&G!Rzk5`8P=v|o$RTjr3)o^9!~?3d eneW4#NwjBrw6ep|BEuUrAL;4p=d#Wzp$PympK2ih literal 8409 zcmeHNT})GF7_Jh#7U~26+d>lyhGKLUB@Kgx2rW`UQ>Tjw%T{Crw!spllqEt&M5T2x zjGxL3TO}AG7bZ(|$+A!ak$6mO2}>{}yBS2&w8opMrMoFf)9!h{b7*n9Stf>RxM;%9 zIp2AIpZ9s*(<>)W9NnIrl`Im8wpUjj`A8(%%HeZeftSbNTe23AJL!g*z)Y2 z{$0OuYtp^nqGir+bYC|aGQN0r)>NtJ_YEsI>a)w57Rj@wJu>zW7#cqIRECB!>stKCP(4!!4h?U(VsuE$}ay`}kb?~}$< zdj0^{ZcRILLQGFd{C_wtstJ!8IoElM&pPyoRx{VOl-q;EFW7vpN^)ad>Tc_mp=7Gk z`+d8VHUwUyavvy^pl(dX{huN`r5wu?G%$)u#U;Z|cRdZb=$>Nuh078U!Hw&5YYqAGoKs5ek_`Iwlx zNxWct>d&3-dqZv=mnJD~zC9IrJpt>2?V^lZb}-AExpJ{L&(KSxDJ5isIVFUyhmv5%7?iQhu%|#ywxe=; z9(v~Nu$}rrtqWSo_C&h8P=Z#B$~(2;;{Z#g?G7xang`fMdrRe!JUAxfY6gM7NIS4N zS~;2$-Kn%0#oqk{&u9pPGZ4+4w|8HG<2`{)oP$b3!-l#YPq~>RVq`FsjB`+P==Jc7 zryV05fl+sD17xH6027fq|74&5FyEMZ_Yx2tb%^$l76i@U0%~2Mq)rdOM@1&Ax&2cw z1<zEQUm zO(WZz{MqrwMfG-pa_%F-Mvjg-S~KDuj>hgo$r5#AQ8C^Hxm$$-6#DzgsC^oC6vC_( zV;ls~F^|D(k8M8m)xzs_nP_MsypJAOmNYc9fEld~#b<|TXaU$J4yh*C&;pz-D*6}M z&;p3H$lNV76A8MCF8hjTCL;SC+4tM7(@X?RP4{gc|Bv8Qhy?Kh^!^2j7EhsaLys5BV}a^x?sUJ(<=noOw4-hswP~!ni<3Sa&(c- z`yy9Jr#zU1E*qD2%Y`Jl26xk}*)UUthVPt=Bf}YOyqkwpVr}n#632%PynN=9CVwvV z!^#$~f#zwjCZ*5Js=rKaX5&2a)tIA~S_wH!VdJ^(fXNXydELK0^i(o}lf>C+di(F}%9@lARGu$);V{{?@b88_a@J2fByvUuHqaOu*ES3o z5cmsbv$uu$(PLQxM=oOK>1jxJWb+I~bq*Z4kLM*ctsh|o5F2sV0%i8_l!+$(1PN6T zrOo4ss#(*{kD|Rzq2ypDiUO3*pBpYk^Ev~W{{1}l!?LFnD4_$JtPv<;Z{ROrKr>k9 z9f3;9y-$JN3t*>pIXvama`Qm;acQ0Yu7O1ytDzeZD^=-tFLl{bq@b{qlClqhNSdx~ zE6FTd31(1234#A;3@|_VSW2iS%x0ZrKa`L)GCsE*O038^pwHKqBy zo`)vJX5|r9K8*A_10%eMhi=9Krt`WmN}IWMUg$$C)3T*Sn4ja)`B}CMfS{(G%;p2w zK4CRPjj0jEN-L>%Y7M|XgDLW;UF zAg`17y#RwvKHqqgjCVEV{7QkKRmi&g{~y0tGuMi*1bk251>h0-Uyt&IKEJ#HpJ-CJ X float: + denominator = self.true_positive + self.false_positive + return self.true_positive / denominator if denominator else 1.0 + + @property + def recall(self) -> float: + denominator = self.true_positive + self.false_negative + return self.true_positive / denominator if denominator else 1.0 + + @property + def f1(self) -> float: + denominator = self.precision + self.recall + return 2.0 * self.precision * self.recall / denominator if denominator else 0.0 + + +def read_matrix(path: Path) -> np.ndarray: + rows: list[str] = [] + for line in path.read_text(encoding="utf-8").splitlines(): + stripped = line.strip() + if not stripped or stripped.startswith("#"): + continue + rows.append(stripped) + if len(rows) == GRID_SIZE: + break + + if len(rows) != GRID_SIZE: + raise ValueError(f"{path} has {len(rows)} matrix rows, expected {GRID_SIZE}") + + matrix = np.zeros((GRID_SIZE, GRID_SIZE), dtype=np.uint8) + for row_index, row_text in enumerate(rows): + if len(row_text) < GRID_SIZE: + raise ValueError( + f"{path} row {row_index + 1} has {len(row_text)} columns, " + f"expected {GRID_SIZE}" + ) + for col_index, char in enumerate(row_text[:GRID_SIZE]): + matrix[row_index, col_index] = 1 if char == "1" else 0 + + return matrix + + +def count_2x2_blocks(matrix: np.ndarray) -> int: + total = 0 + for row in range(GRID_SIZE - 1): + for col in range(GRID_SIZE - 1): + total += int(matrix[row : row + 2, col : col + 2].sum() == 4) + return total + + +def diff_image(manual: np.ndarray, generated: np.ndarray, scale: int) -> np.ndarray: + both = (manual == 1) & (generated == 1) + false_positive = (manual == 0) & (generated == 1) + false_negative = (manual == 1) & (generated == 0) + + image = np.full((GRID_SIZE, GRID_SIZE, 3), 255, dtype=np.uint8) + image[both] = (0, 0, 0) + image[false_positive] = (40, 40, 220) + image[false_negative] = (220, 80, 40) + return cv2.resize(image, (GRID_SIZE * scale, GRID_SIZE * scale), interpolation=cv2.INTER_NEAREST) + + +def write_image(path: Path, image: np.ndarray) -> None: + ok, encoded = cv2.imencode(path.suffix, image) + if not ok: + raise ValueError(f"Cannot encode image: {path}") + encoded.tofile(str(path)) + + +def metrics_for_pair(manual_path: Path, generated_path: Path) -> MatrixMetrics: + manual = read_matrix(manual_path) + generated = read_matrix(generated_path) + true_positive = int(((manual == 1) & (generated == 1)).sum()) + false_positive = int(((manual == 0) & (generated == 1)).sum()) + false_negative = int(((manual == 1) & (generated == 0)).sum()) + stem = manual_path.name.removesuffix("_matrix17.txt") + return MatrixMetrics( + stem=stem, + true_positive=true_positive, + false_positive=false_positive, + false_negative=false_negative, + manual_cells=int(manual.sum()), + generated_cells=int(generated.sum()), + manual_2x2=count_2x2_blocks(manual), + generated_2x2=count_2x2_blocks(generated), + ) + + +def print_table(metrics: list[MatrixMetrics]) -> None: + header = ( + "stem", + "P", + "R", + "F1", + "TP", + "FP", + "FN", + "manual", + "gen", + "manual_2x2", + "gen_2x2", + ) + print( + f"{header[0]:42} {header[1]:>6} {header[2]:>6} {header[3]:>6} " + f"{header[4]:>4} {header[5]:>4} {header[6]:>4} {header[7]:>6} " + f"{header[8]:>6} {header[9]:>11} {header[10]:>8}" + ) + for item in metrics: + print( + f"{item.stem:42} {item.precision:6.3f} {item.recall:6.3f} {item.f1:6.3f} " + f"{item.true_positive:4d} {item.false_positive:4d} {item.false_negative:4d} " + f"{item.manual_cells:6d} {item.generated_cells:6d} " + f"{item.manual_2x2:11d} {item.generated_2x2:8d}" + ) + + total_tp = sum(item.true_positive for item in metrics) + total_fp = sum(item.false_positive for item in metrics) + total_fn = sum(item.false_negative for item in metrics) + total_manual = sum(item.manual_cells for item in metrics) + total_generated = sum(item.generated_cells for item in metrics) + total_manual_2x2 = sum(item.manual_2x2 for item in metrics) + total_generated_2x2 = sum(item.generated_2x2 for item in metrics) + total = MatrixMetrics( + stem="TOTAL", + true_positive=total_tp, + false_positive=total_fp, + false_negative=total_fn, + manual_cells=total_manual, + generated_cells=total_generated, + manual_2x2=total_manual_2x2, + generated_2x2=total_generated_2x2, + ) + print("-" * 113) + print( + f"{total.stem:42} {total.precision:6.3f} {total.recall:6.3f} {total.f1:6.3f} " + f"{total.true_positive:4d} {total.false_positive:4d} {total.false_negative:4d} " + f"{total.manual_cells:6d} {total.generated_cells:6d} " + f"{total.manual_2x2:11d} {total.generated_2x2:8d}" + ) + + +def main() -> None: + parser = argparse.ArgumentParser( + description="Compare manual 17x17 labels against generated matrix output." + ) + parser.add_argument( + "--manual-dir", + type=Path, + default=Path("PreProcessing/manual_matrices"), + ) + parser.add_argument( + "--generated-dir", + type=Path, + default=Path("PreProcessing/processed_characters"), + ) + parser.add_argument( + "--diff-dir", + type=Path, + default=Path("PreProcessing/manual_diffs"), + ) + parser.add_argument("--scale", type=int, default=24) + parser.add_argument( + "--include-empty-manual", + action="store_true", + help="Include manual matrices with no black cells instead of treating them as unlabelled.", + ) + args = parser.parse_args() + + manual_paths = sorted(args.manual_dir.glob("*_matrix17.txt")) + if not manual_paths: + raise SystemExit(f"No manual matrices found in {args.manual_dir}") + + args.diff_dir.mkdir(parents=True, exist_ok=True) + metrics: list[MatrixMetrics] = [] + missing: list[Path] = [] + skipped_empty: list[Path] = [] + + for manual_path in manual_paths: + manual = read_matrix(manual_path) + if not args.include_empty_manual and int(manual.sum()) == 0: + skipped_empty.append(manual_path) + continue + + generated_path = args.generated_dir / manual_path.name + if not generated_path.exists(): + missing.append(generated_path) + continue + + generated = read_matrix(generated_path) + metrics.append(metrics_for_pair(manual_path, generated_path)) + stem = manual_path.name.removesuffix("_matrix17.txt") + write_image(args.diff_dir / f"{stem}_diff.png", diff_image(manual, generated, args.scale)) + + if missing: + print("Missing generated matrices:") + for path in missing: + print(f" {path}") + + if skipped_empty: + print("Skipped empty manual matrices:") + for path in skipped_empty: + print(f" {path}") + + if not metrics: + raise SystemExit("No comparable matrix pairs found.") + + print_table(metrics) + print(f"\nDiff images written to: {args.diff_dir}") + print("Diff colors: black=match, red=generated extra, blue=manual missing.") + + +if __name__ == "__main__": + main() diff --git a/PreProcessing/scripts/draw_matrix17.py b/PreProcessing/scripts/draw_matrix17.py new file mode 100644 index 0000000..c8ace35 --- /dev/null +++ b/PreProcessing/scripts/draw_matrix17.py @@ -0,0 +1,364 @@ +from __future__ import annotations + +import argparse +from pathlib import Path +import tkinter as tk +from tkinter import messagebox + +import cv2 +import numpy as np + + +IMAGE_SUFFIXES = {".png", ".jpg", ".jpeg", ".tif", ".tiff", ".bmp", ".webp"} +GRID_SIZE = 17 +CELL_SIZE = 28 +PREVIEW_SIZE = 560 + + +def read_image(path: Path) -> np.ndarray: + raw = np.fromfile(str(path), dtype=np.uint8) + image = cv2.imdecode(raw, cv2.IMREAD_COLOR) + if image is None: + raise ValueError(f"Cannot read image: {path}") + return image + + +def write_image(path: Path, image: np.ndarray) -> None: + ok, encoded = cv2.imencode(path.suffix, image) + if not ok: + raise ValueError(f"Cannot encode image: {path}") + encoded.tofile(str(path)) + + +def matrix_to_text(matrix: np.ndarray) -> str: + lines = [] + for row in matrix: + lines.append("".join("1" if value else "0" for value in row)) + return "\n".join(lines) + "\n" + + +def text_to_matrix(path: Path) -> np.ndarray: + matrix = np.zeros((GRID_SIZE, GRID_SIZE), dtype=np.uint8) + if not path.exists(): + return matrix + + rows = [] + for line in path.read_text(encoding="utf-8").splitlines(): + stripped = line.strip() + if not stripped or stripped.startswith("#"): + continue + rows.append(stripped) + if len(rows) == GRID_SIZE: + break + + for row_index, row_text in enumerate(rows[:GRID_SIZE]): + for col_index, char in enumerate(row_text[:GRID_SIZE]): + matrix[row_index, col_index] = 1 if char == "1" else 0 + + return matrix + + +def matrix_to_png(matrix: np.ndarray, scale: int = 24) -> np.ndarray: + image = np.where(matrix > 0, 0, 255).astype(np.uint8) + return cv2.resize( + image, + (GRID_SIZE * scale, GRID_SIZE * scale), + interpolation=cv2.INTER_NEAREST, + ) + + +class MatrixEditor: + def __init__( + self, + root: tk.Tk, + image_paths: list[Path], + output_dir: Path, + load_generated_dir: Path | None, + ) -> None: + self.root = root + self.image_paths = image_paths + self.output_dir = output_dir + self.load_generated_dir = load_generated_dir + self.output_dir.mkdir(parents=True, exist_ok=True) + + self.index = 0 + self.matrix = np.zeros((GRID_SIZE, GRID_SIZE), dtype=np.uint8) + self.paint_value = 1 + self.preview_photo: tk.PhotoImage | None = None + self.preview_temp = Path("/private/tmp/matrix17_editor_preview.png") + + self.root.title("17x17 Matrix Editor") + self._build_ui() + self._bind_keys() + self.load_current_image() + + @property + def image_path(self) -> Path: + return self.image_paths[self.index] + + @property + def answer_path(self) -> Path: + return self.output_dir / f"{self.image_path.stem}_matrix17.txt" + + @property + def answer_png_path(self) -> Path: + return self.output_dir / f"{self.image_path.stem}_matrix17.png" + + def _build_ui(self) -> None: + main = tk.Frame(self.root) + main.pack(fill=tk.BOTH, expand=True, padx=10, pady=10) + + left = tk.Frame(main) + left.pack(side=tk.LEFT, fill=tk.BOTH, expand=True) + right = tk.Frame(main) + right.pack(side=tk.LEFT, fill=tk.Y, padx=(12, 0)) + + self.preview_canvas = tk.Canvas( + left, + width=PREVIEW_SIZE, + height=PREVIEW_SIZE, + bg="white", + highlightthickness=1, + highlightbackground="#999", + ) + self.preview_canvas.pack(fill=tk.BOTH, expand=True) + + self.grid_canvas = tk.Canvas( + right, + width=GRID_SIZE * CELL_SIZE + 1, + height=GRID_SIZE * CELL_SIZE + 1, + bg="white", + highlightthickness=1, + highlightbackground="#777", + ) + self.grid_canvas.pack() + self.grid_canvas.bind("", self._on_left_click) + self.grid_canvas.bind("", self._on_left_drag) + self.grid_canvas.bind("", self._on_right_click) + self.grid_canvas.bind("", self._on_right_drag) + + buttons = tk.Frame(right) + buttons.pack(fill=tk.X, pady=(10, 0)) + + tk.Button(buttons, text="上一张", command=self.prev_image).grid( + row=0, column=0, sticky="ew", padx=2, pady=2 + ) + tk.Button(buttons, text="下一张", command=self.next_image).grid( + row=0, column=1, sticky="ew", padx=2, pady=2 + ) + tk.Button(buttons, text="保存", command=self.save_answer).grid( + row=1, column=0, sticky="ew", padx=2, pady=2 + ) + tk.Button(buttons, text="清空", command=self.clear_matrix).grid( + row=1, column=1, sticky="ew", padx=2, pady=2 + ) + tk.Button(buttons, text="载入生成结果", command=self.load_generated).grid( + row=2, column=0, columnspan=2, sticky="ew", padx=2, pady=2 + ) + + buttons.columnconfigure(0, weight=1) + buttons.columnconfigure(1, weight=1) + + self.status = tk.Label(right, text="", anchor="w", justify="left") + self.status.pack(fill=tk.X, pady=(8, 0)) + + def _bind_keys(self) -> None: + self.root.bind("", lambda _event: self.prev_image()) + self.root.bind("", lambda _event: self.next_image()) + self.root.bind("s", lambda _event: self.save_answer()) + self.root.bind("S", lambda _event: self.save_answer()) + self.root.bind("c", lambda _event: self.clear_matrix()) + self.root.bind("C", lambda _event: self.clear_matrix()) + self.root.bind("1", lambda _event: self.set_paint_value(1)) + self.root.bind("0", lambda _event: self.set_paint_value(0)) + + def set_paint_value(self, value: int) -> None: + self.paint_value = 1 if value else 0 + self._update_status() + + def load_current_image(self) -> None: + self.matrix = text_to_matrix(self.answer_path) + self._draw_preview() + self._draw_grid() + self._update_status() + + def _draw_preview(self) -> None: + image = read_image(self.image_path) + height, width = image.shape[:2] + scale = min(PREVIEW_SIZE / height, PREVIEW_SIZE / width) + new_width = max(1, int(round(width * scale))) + new_height = max(1, int(round(height * scale))) + resized = cv2.resize(image, (new_width, new_height), interpolation=cv2.INTER_NEAREST) + + canvas = np.full((PREVIEW_SIZE, PREVIEW_SIZE, 3), 255, dtype=np.uint8) + x = (PREVIEW_SIZE - new_width) // 2 + y = (PREVIEW_SIZE - new_height) // 2 + canvas[y : y + new_height, x : x + new_width] = resized + write_image(self.preview_temp, canvas) + self.preview_photo = tk.PhotoImage(file=str(self.preview_temp)) + self.preview_canvas.delete("all") + self.preview_canvas.create_image(0, 0, anchor="nw", image=self.preview_photo) + + def _draw_grid(self) -> None: + self.grid_canvas.delete("all") + for row in range(GRID_SIZE): + for col in range(GRID_SIZE): + x1 = col * CELL_SIZE + y1 = row * CELL_SIZE + x2 = x1 + CELL_SIZE + y2 = y1 + CELL_SIZE + fill = "black" if self.matrix[row, col] else "white" + self.grid_canvas.create_rectangle( + x1, + y1, + x2, + y2, + fill=fill, + outline="#888", + ) + + for index in range(GRID_SIZE + 1): + pos = index * CELL_SIZE + width = 2 if index in (0, GRID_SIZE) else 1 + self.grid_canvas.create_line(0, pos, GRID_SIZE * CELL_SIZE, pos, fill="#555", width=width) + self.grid_canvas.create_line(pos, 0, pos, GRID_SIZE * CELL_SIZE, fill="#555", width=width) + + def _grid_cell_from_event(self, event: tk.Event) -> tuple[int, int] | None: + col = int(event.x // CELL_SIZE) + row = int(event.y // CELL_SIZE) + if 0 <= row < GRID_SIZE and 0 <= col < GRID_SIZE: + return row, col + return None + + def _set_cell_from_event(self, event: tk.Event, value: int) -> None: + cell = self._grid_cell_from_event(event) + if cell is None: + return + row, col = cell + if self.matrix[row, col] == value: + return + self.matrix[row, col] = value + self._draw_grid() + self._update_status() + + def _on_left_click(self, event: tk.Event) -> None: + cell = self._grid_cell_from_event(event) + if cell is None: + return + row, col = cell + self.paint_value = 0 if self.matrix[row, col] else 1 + self.matrix[row, col] = self.paint_value + self._draw_grid() + self._update_status() + + def _on_left_drag(self, event: tk.Event) -> None: + self._set_cell_from_event(event, self.paint_value) + + def _on_right_click(self, event: tk.Event) -> None: + self.paint_value = 0 + self._set_cell_from_event(event, 0) + self._update_status() + + def _on_right_drag(self, event: tk.Event) -> None: + self._set_cell_from_event(event, 0) + + def save_answer(self) -> None: + self.answer_path.write_text(matrix_to_text(self.matrix), encoding="utf-8") + write_image(self.answer_png_path, matrix_to_png(self.matrix)) + self._update_status(saved=True) + + def clear_matrix(self) -> None: + self.matrix[:, :] = 0 + self._draw_grid() + self._update_status() + + def load_generated(self) -> None: + if self.load_generated_dir is None: + messagebox.showinfo("提示", "未配置生成结果目录") + return + + path = self.load_generated_dir / f"{self.image_path.stem}_matrix17.txt" + if not path.exists(): + messagebox.showinfo("提示", f"找不到生成结果:\n{path}") + return + + self.matrix = text_to_matrix(path) + self._draw_grid() + self._update_status() + + def prev_image(self) -> None: + self.save_answer() + self.index = (self.index - 1) % len(self.image_paths) + self.load_current_image() + + def next_image(self) -> None: + self.save_answer() + self.index = (self.index + 1) % len(self.image_paths) + self.load_current_image() + + def _update_status(self, saved: bool = False) -> None: + filled = int(self.matrix.sum()) + two_by_two = count_2x2_blocks(self.matrix) + saved_text = "已保存\n" if saved else "" + self.status.config( + text=( + f"{saved_text}" + f"{self.index + 1}/{len(self.image_paths)}\n" + f"{self.image_path.name}\n" + f"黑格:{filled}\n" + f"2x2 全黑:{two_by_two}\n" + f"左键:切换/拖拽绘制\n" + f"右键:擦除\n" + f"S 保存,←/→ 切换" + ) + ) + + +def count_2x2_blocks(matrix: np.ndarray) -> int: + image = matrix > 0 + total = 0 + for row in range(GRID_SIZE - 1): + for col in range(GRID_SIZE - 1): + total += int(image[row : row + 2, col : col + 2].sum() == 4) + return total + + +def main() -> None: + parser = argparse.ArgumentParser(description="Draw manual 17x17 matrix labels.") + parser.add_argument( + "--input-dir", + type=Path, + default=Path("PreProcessing/original_characters"), + ) + parser.add_argument( + "--output-dir", + type=Path, + default=Path("PreProcessing/manual_matrices"), + ) + parser.add_argument( + "--load-generated-dir", + type=Path, + default=Path("PreProcessing/processed_characters"), + ) + args = parser.parse_args() + + image_paths = sorted( + path + for path in args.input_dir.iterdir() + if path.is_file() and path.suffix.lower() in IMAGE_SUFFIXES + ) + if not image_paths: + raise SystemExit(f"No images found in {args.input_dir}") + + root = tk.Tk() + MatrixEditor( + root=root, + image_paths=image_paths, + output_dir=args.output_dir, + load_generated_dir=args.load_generated_dir, + ) + root.mainloop() + + +if __name__ == "__main__": + main() diff --git a/PreProcessing/scripts/process_characters.py b/PreProcessing/scripts/process_characters.py index 2012731..94fad66 100644 --- a/PreProcessing/scripts/process_characters.py +++ b/PreProcessing/scripts/process_characters.py @@ -3,6 +3,7 @@ from __future__ import annotations import argparse import html import os +from dataclasses import dataclass from pathlib import Path import cv2 @@ -23,6 +24,23 @@ import numpy as np IMAGE_SUFFIXES = {".png", ".jpg", ".jpeg", ".tif", ".tiff", ".bmp", ".webp"} +@dataclass(frozen=True) +class TriangleConnection: + row: int + col: int + corner: str + + +@dataclass(frozen=True) +class MatrixMapping: + matrix: np.ndarray + rendered_mask: np.ndarray + x_edges: np.ndarray + y_edges: np.ndarray + triangles: tuple[TriangleConnection, ...] = () + grid_overlay: np.ndarray | None = None + + def read_image(path: Path) -> np.ndarray: raw = np.fromfile(str(path), dtype=np.uint8) image = cv2.imdecode(raw, cv2.IMREAD_COLOR) @@ -39,10 +57,13 @@ def write_image(path: Path, image: np.ndarray) -> None: def binarize_foreground(gray: np.ndarray) -> np.ndarray: - blurred = cv2.GaussianBlur(gray, (3, 3), 0) threshold, _ = cv2.threshold( - blurred, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU + gray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU ) + gray_min = int(gray.min()) + gray_max = int(gray.max()) + if threshold <= gray_min or threshold >= gray_max: + threshold = (gray_min + gray_max) / 2.0 border = np.concatenate( [ @@ -62,29 +83,223 @@ def binarize_foreground(gray: np.ndarray) -> np.ndarray: return foreground +def fill_mask_holes(mask: np.ndarray) -> np.ndarray: + foreground = mask > 0 + inverse = (~foreground).astype(np.uint8) + flood = np.zeros((mask.shape[0] + 2, mask.shape[1] + 2), dtype=np.uint8) + cv2.floodFill(inverse, flood, (0, 0), 2) + holes = inverse == 1 + filled = foreground | holes + return filled.astype(np.uint8) * 255 + + +def fill_small_mask_holes(mask: np.ndarray, max_area: int) -> np.ndarray: + if max_area <= 0: + return mask + + foreground = mask > 0 + inverse = (~foreground).astype(np.uint8) + flood = np.zeros((mask.shape[0] + 2, mask.shape[1] + 2), dtype=np.uint8) + cv2.floodFill(inverse, flood, (0, 0), 2) + holes = (flood == 1).astype(np.uint8) + num_labels, labels, stats, _ = cv2.connectedComponentsWithStats( + holes, connectivity=8 + ) + + filled = foreground.copy() + for label in range(1, num_labels): + area = int(stats[label, cv2.CC_STAT_AREA]) + if area <= max_area: + filled[labels == label] = True + + return filled.astype(np.uint8) * 255 + + +def fill_small_background_pockets( + mask: np.ndarray, + max_area: int, + channel_size: int, +) -> np.ndarray: + if max_area <= 0 or channel_size <= 1: + return fill_small_mask_holes(mask, max_area) + + if channel_size % 2 == 0: + channel_size += 1 + + kernel = cv2.getStructuringElement( + cv2.MORPH_ELLIPSE, (channel_size, channel_size) + ) + expanded = cv2.dilate(mask, kernel) + external = (expanded == 0).astype(np.uint8) + flood = np.zeros((mask.shape[0] + 2, mask.shape[1] + 2), dtype=np.uint8) + cv2.floodFill(external, flood, (0, 0), 2) + + pockets = ((mask == 0) & (external != 2)).astype(np.uint8) + num_labels, labels, stats, _ = cv2.connectedComponentsWithStats( + pockets, connectivity=8 + ) + + filled = mask > 0 + for label in range(1, num_labels): + area = int(stats[label, cv2.CC_STAT_AREA]) + if area <= max_area: + filled[labels == label] = True + + return filled.astype(np.uint8) * 255 + + +def remove_small_components(mask: np.ndarray, min_area: int) -> np.ndarray: + if min_area <= 0: + return mask + + num_labels, labels, stats, _ = cv2.connectedComponentsWithStats( + mask, connectivity=8 + ) + cleaned = np.zeros_like(mask) + for label in range(1, num_labels): + if int(stats[label, cv2.CC_STAT_AREA]) >= min_area: + cleaned[labels == label] = 255 + + return cleaned + + +def smooth_binary_edges(mask: np.ndarray, iterations: int = 1) -> np.ndarray: + foreground = mask > 0 + kernel = np.ones((3, 3), dtype=np.uint8) + + for _ in range(iterations): + neighbors = cv2.filter2D( + foreground.astype(np.uint8), + ddepth=-1, + kernel=kernel, + borderType=cv2.BORDER_CONSTANT, + ) + foreground = (foreground & (neighbors >= 3)) | (~foreground & (neighbors >= 7)) + + return foreground.astype(np.uint8) * 255 + + def clean_mask( mask: np.ndarray, open_kernel_size: int, close_kernel_size: int, median_size: int, + min_component_area: int, + grid_size: int = 17, ) -> np.ndarray: if median_size > 1: if median_size % 2 == 0: median_size += 1 mask = cv2.medianBlur(mask, median_size) - open_kernel = cv2.getStructuringElement( - cv2.MORPH_RECT, (open_kernel_size, open_kernel_size) + cleaned = mask + if open_kernel_size > 1: + open_kernel = cv2.getStructuringElement( + cv2.MORPH_RECT, (open_kernel_size, open_kernel_size) + ) + cleaned = cv2.morphologyEx(cleaned, cv2.MORPH_OPEN, open_kernel) + + cleaned = remove_small_components(cleaned, min_component_area) + x1, y1, x2, y2 = _foreground_bbox(cleaned) + cell_size = max(4.0, min(float(x2 - x1), float(y2 - y1)) / float(grid_size)) + burr_size = min(5, max(3, int(round(cell_size * 0.12)) | 1)) + line_length = max(3, int(round(cell_size * 0.64))) + pocket_size = min(5, max(3, int(round(cell_size * 0.10)) | 1)) + gap_fill_length = min(7, max(3, int(round(cell_size * 0.18)) | 1)) + max_hole_area = max(4, int(round(cell_size * cell_size * 0.35))) + + burr_kernel = cv2.getStructuringElement( + cv2.MORPH_RECT, (burr_size, burr_size) ) - opened = cv2.morphologyEx(mask, cv2.MORPH_OPEN, open_kernel) + cleaned = cv2.morphologyEx(cleaned, cv2.MORPH_OPEN, burr_kernel) + cleaned = remove_small_components(cleaned, min_component_area) - close_kernel = cv2.getStructuringElement( - cv2.MORPH_RECT, (close_kernel_size, close_kernel_size) + horizontal_kernel = cv2.getStructuringElement( + cv2.MORPH_RECT, (line_length, 1) ) - return cv2.morphologyEx(opened, cv2.MORPH_CLOSE, close_kernel) + vertical_kernel = cv2.getStructuringElement( + cv2.MORPH_RECT, (1, line_length) + ) + horizontal = cv2.morphologyEx(cleaned, cv2.MORPH_OPEN, horizontal_kernel) + vertical = cv2.morphologyEx(cleaned, cv2.MORPH_OPEN, vertical_kernel) + cleaned = cv2.bitwise_or(horizontal, vertical) + + horizontal_gap_kernel = cv2.getStructuringElement( + cv2.MORPH_RECT, (gap_fill_length, 1) + ) + vertical_gap_kernel = cv2.getStructuringElement( + cv2.MORPH_RECT, (1, gap_fill_length) + ) + horizontal_filled = cv2.morphologyEx( + cleaned, cv2.MORPH_CLOSE, horizontal_gap_kernel + ) + vertical_filled = cv2.morphologyEx(cleaned, cv2.MORPH_CLOSE, vertical_gap_kernel) + cleaned = cv2.bitwise_or(horizontal_filled, vertical_filled) + + cleaned = fill_small_background_pockets( + cleaned, + max_area=max_hole_area, + channel_size=pocket_size, + ) + smooth_size = close_kernel_size if close_kernel_size > 1 else 3 + smooth_kernel = cv2.getStructuringElement( + cv2.MORPH_CROSS, (smooth_size, smooth_size) + ) + cleaned = cv2.morphologyEx(cleaned, cv2.MORPH_CLOSE, smooth_kernel) + cleaned = fill_small_background_pockets( + cleaned, + max_area=max_hole_area, + channel_size=pocket_size, + ) + cleaned = smooth_binary_edges(cleaned, iterations=1) + + return remove_small_components(cleaned, min_component_area) -def pixelate(mask: np.ndarray, factor: int) -> tuple[np.ndarray, np.ndarray]: +def _render_matrix( + matrix: np.ndarray, + x_edges: np.ndarray, + y_edges: np.ndarray, + width: int, + height: int, + triangles: tuple[TriangleConnection, ...] = (), +) -> np.ndarray: + rendered = np.zeros((height, width), dtype=np.uint8) + + rows, cols = matrix.shape + for row_index in range(rows): + y1 = int(y_edges[row_index]) + y2 = int(y_edges[row_index + 1]) + if y2 <= y1: + continue + + for col_index in range(cols): + if matrix[row_index, col_index] == 0: + continue + + x1 = int(x_edges[col_index]) + x2 = int(x_edges[col_index + 1]) + if x2 > x1: + rendered[y1:y2, x1:x2] = 255 + + for triangle in triangles: + x1 = int(x_edges[triangle.col]) + x2 = int(x_edges[triangle.col + 1]) + y1 = int(y_edges[triangle.row]) + y2 = int(y_edges[triangle.row + 1]) + points_by_corner = { + "tl": [(x1, y1), (x2, y1), (x1, y2)], + "tr": [(x2, y1), (x1, y1), (x2, y2)], + "br": [(x2, y2), (x2, y1), (x1, y2)], + "bl": [(x1, y2), (x1, y1), (x2, y2)], + } + points = np.array(points_by_corner[triangle.corner], dtype=np.int32) + cv2.fillConvexPoly(rendered, points, 255) + + return rendered + + +def pixelate(mask: np.ndarray, factor: int) -> MatrixMapping: height, width = mask.shape small_width = max(1, round(width / factor)) small_height = max(1, round(height / factor)) @@ -92,8 +307,671 @@ def pixelate(mask: np.ndarray, factor: int) -> tuple[np.ndarray, np.ndarray]: mask, (small_width, small_height), interpolation=cv2.INTER_AREA ) small = np.where(sampled >= 96, 255, 0).astype(np.uint8) + x_edges = np.rint(np.linspace(0, width, small_width + 1)).astype(int) + y_edges = np.rint(np.linspace(0, height, small_height + 1)).astype(int) large = cv2.resize(small, (width, height), interpolation=cv2.INTER_NEAREST) - return small, large + return MatrixMapping(small, large, x_edges, y_edges) + + +def _order_quad_points(points: np.ndarray) -> np.ndarray: + points = points.astype(np.float32) + sums = points.sum(axis=1) + diffs = np.diff(points, axis=1).reshape(-1) + ordered = np.zeros((4, 2), dtype=np.float32) + ordered[0] = points[int(np.argmin(sums))] + ordered[2] = points[int(np.argmax(sums))] + ordered[1] = points[int(np.argmin(diffs))] + ordered[3] = points[int(np.argmax(diffs))] + return ordered + + +def _foreground_quad(mask: np.ndarray) -> np.ndarray: + points = cv2.findNonZero(mask) + if points is None: + height, width = mask.shape + return np.array( + [[0, 0], [width - 1, 0], [width - 1, height - 1], [0, height - 1]], + dtype=np.float32, + ) + + contour_points = points.reshape(-1, 2) + hull = cv2.convexHull(contour_points) + perimeter = cv2.arcLength(hull, True) + approx = cv2.approxPolyDP(hull, 0.035 * perimeter, True) + if len(approx) == 4: + return _order_quad_points(approx.reshape(4, 2)) + + rect = cv2.minAreaRect(contour_points) + return _order_quad_points(cv2.boxPoints(rect)) + + +def _quad_bbox_square_edges( + quad: np.ndarray, + canvas_width: int, + canvas_height: int, + grid_size: int, +) -> tuple[np.ndarray, np.ndarray]: + x_min, y_min = np.min(quad, axis=0) + x_max, y_max = np.max(quad, axis=0) + center_x = float((x_min + x_max) * 0.5) + center_y = float((y_min + y_max) * 0.5) + side = max(float(x_max - x_min), float(y_max - y_min), 1.0) + + left = center_x - side * 0.5 + top = center_y - side * 0.5 + if left < 0: + left = 0.0 + if top < 0: + top = 0.0 + if left + side > canvas_width: + left = max(0.0, float(canvas_width) - side) + if top + side > canvas_height: + top = max(0.0, float(canvas_height) - side) + + right = min(float(canvas_width), left + side) + bottom = min(float(canvas_height), top + side) + x_edges = np.rint(np.linspace(left, right, grid_size + 1)).astype(int) + y_edges = np.rint(np.linspace(top, bottom, grid_size + 1)).astype(int) + return x_edges, y_edges + + +def _warp_to_grid(mask: np.ndarray, grid_size: int, cell_samples: int) -> np.ndarray: + quad = _foreground_quad(mask) + side = int(grid_size * cell_samples) + destination = np.array( + [[0, 0], [side - 1, 0], [side - 1, side - 1], [0, side - 1]], + dtype=np.float32, + ) + transform = cv2.getPerspectiveTransform(quad, destination) + return cv2.warpPerspective( + mask, + transform, + (side, side), + flags=cv2.INTER_NEAREST, + borderMode=cv2.BORDER_CONSTANT, + borderValue=0, + ) + + +def _foreground_bbox(mask: np.ndarray) -> tuple[int, int, int, int]: + ys, xs = np.where(mask > 0) + if xs.size == 0: + height, width = mask.shape + return 0, 0, width, height + + return int(xs.min()), int(ys.min()), int(xs.max() + 1), int(ys.max() + 1) + + +def _rotate_mask(mask: np.ndarray, angle: float) -> np.ndarray: + if abs(angle) < 1e-6: + return mask + + height, width = mask.shape + center = (width / 2.0, height / 2.0) + transform = cv2.getRotationMatrix2D(center, angle, 1.0) + return cv2.warpAffine( + mask, + transform, + (width, height), + flags=cv2.INTER_NEAREST, + borderMode=cv2.BORDER_CONSTANT, + borderValue=0, + ) + + +def _projection_score(mask: np.ndarray) -> float: + foreground = mask > 0 + row_sums = foreground.sum(axis=1).astype(np.float64) + col_sums = foreground.sum(axis=0).astype(np.float64) + return float(np.square(row_sums).sum() + np.square(col_sums).sum()) + + +def _estimate_skew_angle(mask: np.ndarray, max_angle: float = 4.0) -> float: + best_angle = 0.0 + best_score = _projection_score(mask) + + for angle in np.arange(-max_angle, max_angle + 0.001, 0.25): + if abs(float(angle)) < 1e-6: + continue + rotated = _rotate_mask(mask, float(angle)) + score = _projection_score(rotated) + if score > best_score: + best_score = score + best_angle = float(angle) + + return best_angle + + +def _solidify_hollow_strokes(mask: np.ndarray, grid_size: int) -> np.ndarray: + x1, y1, x2, y2 = _foreground_bbox(mask) + cell_width = max(2.0, float(x2 - x1) / float(grid_size)) + cell_height = max(2.0, float(y2 - y1) / float(grid_size)) + cell_size = max(2.0, min(cell_width, cell_height)) + + long_size = max(3, int(round(cell_size * 0.72)) | 1) + short_size = max(3, int(round(cell_size * 0.14)) | 1) + + vertical_bridge = cv2.getStructuringElement( + cv2.MORPH_RECT, (short_size, long_size) + ) + horizontal_bridge = cv2.getStructuringElement( + cv2.MORPH_RECT, (long_size, short_size) + ) + square_cleanup = cv2.getStructuringElement( + cv2.MORPH_RECT, (max(3, short_size), max(3, short_size)) + ) + + horizontal_strokes = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, vertical_bridge) + vertical_strokes = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, horizontal_bridge) + solid = cv2.bitwise_or(horizontal_strokes, vertical_strokes) + solid = cv2.morphologyEx(solid, cv2.MORPH_CLOSE, square_cleanup) + return solid + + +def _triangle_corner_score(cell: np.ndarray, corner: str) -> float: + size = cell.shape[0] + yy, xx = np.indices(cell.shape) + if corner == "tl": + region = (xx + yy) <= size + elif corner == "tr": + region = ((size - 1 - xx) + yy) <= size + elif corner == "br": + region = ((size - 1 - xx) + (size - 1 - yy)) <= size + else: + region = (xx + (size - 1 - yy)) <= size + + foreground = cell > 0 + inside = float(foreground[region].mean()) if np.any(region) else 0.0 + outside = float(foreground[~region].mean()) if np.any(~region) else 0.0 + return inside - outside + + +def _detect_triangle_connections( + warped: np.ndarray, + matrix: np.ndarray, + cell_samples: int, + triangle_threshold: float, +) -> tuple[TriangleConnection, ...]: + grid_size = matrix.shape[0] + triangles: list[TriangleConnection] = [] + + def add_if_supported(row: int, col: int, corner: str) -> None: + y1 = row * cell_samples + y2 = y1 + cell_samples + x1 = col * cell_samples + x2 = x1 + cell_samples + cell = warped[y1:y2, x1:x2] + coverage = float((cell > 0).mean()) + score = _triangle_corner_score(cell, corner) + if coverage >= triangle_threshold and score >= triangle_threshold: + triangles.append(TriangleConnection(row, col, corner)) + + for row in range(grid_size - 1): + for col in range(grid_size - 1): + nw = matrix[row, col] > 0 + ne = matrix[row, col + 1] > 0 + sw = matrix[row + 1, col] > 0 + se = matrix[row + 1, col + 1] > 0 + + if nw and se and not ne and not sw: + add_if_supported(row, col + 1, "bl") + add_if_supported(row + 1, col, "tr") + elif ne and sw and not nw and not se: + add_if_supported(row, col, "br") + add_if_supported(row + 1, col + 1, "tl") + + return tuple(triangles) + + +def _normalize_raw_strokes( + mask: np.ndarray, + grid_size: int, + cell_samples: int, +) -> tuple[np.ndarray, np.ndarray, np.ndarray, np.ndarray]: + angle = _estimate_skew_angle(mask) + deskewed = _rotate_mask(mask, angle) + x1, y1, x2, y2 = _foreground_bbox(deskewed) + side = int(grid_size * cell_samples) + candidates: list[tuple[float, np.ndarray, tuple[float, ...]]] = [] + scale_values = (0.92, 0.94, 0.96, 0.98, 1.0, 1.02, 1.04, 1.06) + shift_x_values = ( + -0.5, + -0.4, + -0.3, + -0.2, + -0.1, + 0.0, + 0.1, + 0.2, + 0.3, + 0.4, + 0.5, + ) + shift_y_values = (-0.3, -0.2, -0.1, 0.0, 0.1, 0.2, 0.3) + for scale_x in scale_values: + for scale_y in scale_values: + for shift_x in shift_x_values: + for shift_y in shift_y_values: + warped = _warp_bbox_candidate( + deskewed, + x1, + y1, + x2, + y2, + scale_x, + scale_y, + shift_x, + shift_y, + side, + ) + candidates.append( + ( + _grid_fit_score(warped, grid_size), + warped, + ( + scale_x, + scale_y, + shift_x, + shift_y, + 0.0, + 0.0, + 0.0, + 0.0, + ), + ) + ) + + for _score, _warped, params in sorted( + candidates, + reverse=True, + key=lambda item: item[0], + )[:36]: + ( + scale_x, + scale_y, + shift_x, + shift_y, + _shear_x, + _shear_y, + _curve_x, + _curve_y, + ) = params + for shear_x in (-0.8, -0.4, 0.0, 0.4, 0.8): + for shear_y in (-0.6, -0.3, 0.0, 0.3, 0.6): + warped = _warp_bbox_candidate( + deskewed, + x1, + y1, + x2, + y2, + scale_x, + scale_y, + shift_x, + shift_y, + side, + shear_x=shear_x, + shear_y=shear_y, + ) + candidates.append( + ( + _grid_fit_score(warped, grid_size), + warped, + ( + scale_x, + scale_y, + shift_x, + shift_y, + shear_x, + shear_y, + 0.0, + 0.0, + ), + ) + ) + + for _score, _warped, params in sorted( + candidates, + reverse=True, + key=lambda item: item[0], + )[:28]: + ( + scale_x, + scale_y, + shift_x, + shift_y, + shear_x, + shear_y, + _curve_x, + _curve_y, + ) = params + for curve_x, curve_y in ( + (-0.65, 0.0), + (-0.35, 0.0), + (0.35, 0.0), + (0.65, 0.0), + (0.0, -0.65), + (0.0, -0.35), + (0.0, 0.35), + (0.0, 0.65), + (-0.35, -0.35), + (-0.35, 0.35), + (0.35, -0.35), + (0.35, 0.35), + ): + warped = _warp_bbox_candidate( + deskewed, + x1, + y1, + x2, + y2, + scale_x, + scale_y, + shift_x, + shift_y, + side, + shear_x=shear_x, + shear_y=shear_y, + curve_x=curve_x, + curve_y=curve_y, + ) + candidates.append( + ( + _grid_fit_score(warped, grid_size), + warped, + ( + scale_x, + scale_y, + shift_x, + shift_y, + shear_x, + shear_y, + curve_x, + curve_y, + ), + ) + ) + + if candidates: + warped = max(candidates, key=lambda item: item[0])[1] + else: + crop = deskewed[y1:y2, x1:x2] + if crop.size == 0: + crop = deskewed + warped = cv2.resize(crop, (side, side), interpolation=cv2.INTER_NEAREST) + + render_x1, render_y1, render_x2, render_y2 = _foreground_bbox(mask) + x_edges = np.rint(np.linspace(render_x1, render_x2, grid_size + 1)).astype(int) + y_edges = np.rint(np.linspace(render_y1, render_y2, grid_size + 1)).astype(int) + return warped, x_edges, y_edges, _grid_overlay_preview(warped, grid_size) + + +def _grid_overlay_preview(warped: np.ndarray, grid_size: int) -> np.ndarray: + preview = cv2.cvtColor(mask_to_display(warped), cv2.COLOR_GRAY2RGB) + height, width = warped.shape + for index in range(grid_size + 1): + x = int(round(index * width / grid_size)) + y = int(round(index * height / grid_size)) + thickness = 2 if index in (0, grid_size) else 1 + cv2.line(preview, (x, 0), (x, height - 1), (220, 40, 40), thickness) + cv2.line(preview, (0, y), (width - 1, y), (220, 40, 40), thickness) + return preview + + +def _warp_bbox_candidate( + mask: np.ndarray, + x1: int, + y1: int, + x2: int, + y2: int, + scale_x: float, + scale_y: float, + shift_x: float, + shift_y: float, + side: int, + shear_x: float = 0.0, + shear_y: float = 0.0, + curve_x: float = 0.0, + curve_y: float = 0.0, +) -> np.ndarray: + width = max(1.0, float(x2 - x1)) + height = max(1.0, float(y2 - y1)) + center_x = ((x1 + x2) * 0.5) + shift_x * width / 17.0 + center_y = ((y1 + y2) * 0.5) + shift_y * height / 17.0 + crop_width = width * scale_x + crop_height = height * scale_y + left = int(round(center_x - crop_width * 0.5)) + right = int(round(center_x + crop_width * 0.5)) + top = int(round(center_y - crop_height * 0.5)) + bottom = int(round(center_y + crop_height * 0.5)) + + crop = np.zeros((max(1, bottom - top), max(1, right - left)), dtype=np.uint8) + source_left = max(0, left) + source_right = min(mask.shape[1], right) + source_top = max(0, top) + source_bottom = min(mask.shape[0], bottom) + if source_right > source_left and source_bottom > source_top: + crop[ + source_top - top : source_bottom - top, + source_left - left : source_right - left, + ] = mask[source_top:source_bottom, source_left:source_right] + + if ( + abs(shear_x) < 1e-9 + and abs(shear_y) < 1e-9 + and abs(curve_x) < 1e-9 + and abs(curve_y) < 1e-9 + ): + return cv2.resize(crop, (side, side), interpolation=cv2.INTER_NEAREST) + + yy, xx = np.indices((side, side), dtype=np.float32) + u = xx / max(1.0, float(side - 1)) + v = yy / max(1.0, float(side - 1)) + centered_u = u - 0.5 + centered_v = v - 0.5 + map_x = ( + u * float(crop.shape[1] - 1) + + (shear_x * centered_v + curve_x * (centered_v * centered_v - 0.125)) + * float(crop.shape[1]) + / 17.0 + ) + map_y = ( + v * float(crop.shape[0] - 1) + + (shear_y * centered_u + curve_y * (centered_u * centered_u - 0.125)) + * float(crop.shape[0]) + / 17.0 + ) + return cv2.remap( + crop, + map_x, + map_y, + interpolation=cv2.INTER_NEAREST, + borderMode=cv2.BORDER_CONSTANT, + borderValue=0, + ) + + +def _grid_fit_score(warped: np.ndarray, grid_size: int) -> float: + occupancy = cv2.resize( + (warped > 0).astype(np.float32), + (grid_size, grid_size), + interpolation=cv2.INTER_AREA, + ) + polar_score = float((np.abs(occupancy - 0.5) * 2.0).mean()) + mixed_cells = float(((occupancy > 0.08) & (occupancy < 0.70)).mean()) + strong_cells = float((occupancy > 0.20).mean()) + foreground_density = float(occupancy.mean()) + border_density = float( + ( + occupancy[0].mean() + + occupancy[-1].mean() + + occupancy[:, 0].mean() + + occupancy[:, -1].mean() + ) + * 0.25 + ) + expected_strong_cells = 0.76 + expected_density = 0.58 + return ( + polar_score + - 0.18 * mixed_cells + - 0.35 * abs(strong_cells - expected_strong_cells) + - 0.20 * abs(foreground_density - expected_density) + + 0.25 * border_density + ) + + +def _cell_ratio_features( + warped: np.ndarray, + grid_size: int, + cell_samples: int, +) -> tuple[np.ndarray, np.ndarray, np.ndarray]: + occupancy = np.zeros((grid_size, grid_size), dtype=np.float64) + center = np.zeros((grid_size, grid_size), dtype=np.float64) + sides = np.zeros((grid_size, grid_size, 4), dtype=np.float64) + center_margin = max(1, cell_samples // 4) + side_width = max(1, cell_samples // 3) + + for row in range(grid_size): + for col in range(grid_size): + y1 = row * cell_samples + y2 = y1 + cell_samples + x1 = col * cell_samples + x2 = x1 + cell_samples + cell = (warped[y1:y2, x1:x2] > 0).astype(np.float32) + occupancy[row, col] = float(cell.mean()) + center_cell = cell[ + center_margin : cell_samples - center_margin, + center_margin : cell_samples - center_margin, + ] + center[row, col] = float(center_cell.mean()) if center_cell.size else 0.0 + sides[row, col] = ( + float(cell[:, :side_width].mean()), + float(cell[:, -side_width:].mean()), + float(cell[:side_width, :].mean()), + float(cell[-side_width:, :].mean()), + ) + + return occupancy, center, sides + + +def _ratio_matrix( + warped: np.ndarray, + grid_size: int, + cell_samples: int, + threshold: float = 0.44, +) -> np.ndarray: + occupancy, center, sides = _cell_ratio_features( + warped, + grid_size=grid_size, + cell_samples=cell_samples, + ) + score = 0.65 * occupancy + 0.35 * center + matrix = (score >= threshold).astype(np.uint8) + matrix = _resolve_thick_stroke_overlaps(matrix, score, sides) + return matrix.astype(np.uint8) * 255 + + +def _resolve_thick_stroke_overlaps( + matrix: np.ndarray, + score: np.ndarray, + sides: np.ndarray, +) -> np.ndarray: + resolved = matrix.astype(bool).copy() + rows, cols = resolved.shape + + def active_neighbors(row: int, col: int) -> int: + total = 0 + for n_row, n_col in ( + (row - 1, col), + (row + 1, col), + (row, col - 1), + (row, col + 1), + ): + if 0 <= n_row < rows and 0 <= n_col < cols and resolved[n_row, n_col]: + total += 1 + return total + + def bridge_score(row: int, col: int) -> int: + bridge = 0 + if col > 0 and col + 1 < cols and resolved[row, col - 1] and resolved[row, col + 1]: + bridge += 1 + if row > 0 and row + 1 < rows and resolved[row - 1, col] and resolved[row + 1, col]: + bridge += 1 + return bridge + + for _iteration in range(rows * cols): + weakest: tuple[float, int, int] | None = None + for row in range(rows - 1): + for col in range(cols - 1): + if int(resolved[row : row + 2, col : col + 2].sum()) != 4: + continue + + for cell_row in (row, row + 1): + for cell_col in (col, col + 1): + side_imbalance = float( + sides[cell_row, cell_col].max() + - sides[cell_row, cell_col].min() + ) + support = ( + float(score[cell_row, cell_col]) + + 0.10 * active_neighbors(cell_row, cell_col) + + 0.25 * bridge_score(cell_row, cell_col) + - 0.05 * side_imbalance + ) + candidate = (support, cell_row, cell_col) + if weakest is None or candidate[0] < weakest[0]: + weakest = candidate + + if weakest is None: + break + _, row, col = weakest + resolved[row, col] = False + + return resolved.astype(np.uint8) + + +def count_2x2_blocks(matrix: np.ndarray) -> int: + image = (matrix > 0).astype(np.uint8) + total = 0 + for row in range(image.shape[0] - 1): + for col in range(image.shape[1] - 1): + total += int(image[row : row + 2, col : col + 2].sum() == 4) + return total + + +def matrix_map( + mask: np.ndarray, + grid_size: int, + triangle_threshold: float, + cell_samples: int, +) -> MatrixMapping: + height, width = mask.shape + warped, x_edges, y_edges, grid_overlay = _normalize_raw_strokes( + mask, + grid_size=grid_size, + cell_samples=cell_samples, + ) + matrix = _ratio_matrix( + warped, + grid_size=grid_size, + cell_samples=cell_samples, + ) + triangles = _detect_triangle_connections( + warped, + matrix, + cell_samples=cell_samples, + triangle_threshold=triangle_threshold, + ) + + rendered = _render_matrix(matrix, x_edges, y_edges, width, height, triangles) + return MatrixMapping( + matrix, + rendered, + x_edges, + y_edges, + triangles=triangles, + grid_overlay=grid_overlay, + ) def mask_to_display(mask: np.ndarray) -> np.ndarray: @@ -104,17 +982,20 @@ def save_comparison( path: Path, original_bgr: np.ndarray, cleaned_mask: np.ndarray, - pixelated_mask: np.ndarray, + grid_overlay: np.ndarray | None, + mapped_mask: np.ndarray, + mapped_title: str, ) -> None: original_rgb = cv2.cvtColor(original_bgr, cv2.COLOR_BGR2RGB) cleaned = mask_to_display(cleaned_mask) - pixelated = mask_to_display(pixelated_mask) + mapped = mask_to_display(mapped_mask) - fig, axes = plt.subplots(1, 3, figsize=(12, 4), constrained_layout=True) + fig, axes = plt.subplots(1, 4, figsize=(16, 4), constrained_layout=True) panels = [ ("Original", original_rgb, None), ("Cleaned binary", cleaned, "gray"), - ("Pixelated", pixelated, "gray"), + ("Adapted 17x17 grid", grid_overlay if grid_overlay is not None else cleaned, None), + (mapped_title, mapped, "gray"), ] for axis, (title, image, cmap) in zip(axes, panels): @@ -131,10 +1012,11 @@ def small_matrix_to_svg( original_width: int, original_height: int, title: str, + x_edges: np.ndarray, + y_edges: np.ndarray, + triangles: tuple[TriangleConnection, ...], ) -> str: rows, cols = small_mask.shape - cell_width = original_width / cols - cell_height = original_height / rows escaped_title = html.escape(title) parts = [ '', @@ -160,28 +1042,71 @@ def small_matrix_to_svg( while col_index < cols and small_mask[row_index, col_index] > 0: col_index += 1 - x = run_start * cell_width - y = row_index * cell_height - width = (col_index - run_start) * cell_width + x = int(x_edges[run_start]) + y = int(y_edges[row_index]) + width = int(x_edges[col_index]) - x + height = int(y_edges[row_index + 1]) - y parts.append( f' ' + f'width="{width:.4f}" height="{height:.4f}"/>' ) + for triangle in triangles: + x1 = int(x_edges[triangle.col]) + x2 = int(x_edges[triangle.col + 1]) + y1 = int(y_edges[triangle.row]) + y2 = int(y_edges[triangle.row + 1]) + points_by_corner = { + "tl": [(x1, y1), (x2, y1), (x1, y2)], + "tr": [(x2, y1), (x1, y1), (x2, y2)], + "br": [(x2, y2), (x2, y1), (x1, y2)], + "bl": [(x1, y2), (x1, y1), (x2, y2)], + } + points = " ".join( + f"{point_x:.4f},{point_y:.4f}" + for point_x, point_y in points_by_corner[triangle.corner] + ) + parts.append(f' ') + parts.extend([" ", "", ""]) return "\n".join(parts) +def matrix_to_text( + matrix: np.ndarray, + triangles: tuple[TriangleConnection, ...], +) -> str: + lines = [] + for row in matrix: + lines.append("".join("1" if value > 0 else "0" for value in row)) + + lines.append("") + lines.append(f"# 2x2_black_blocks: {count_2x2_blocks(matrix)}") + + if triangles: + lines.append("") + lines.append("# triangles: row,col,corner") + for triangle in triangles: + lines.append(f"{triangle.row},{triangle.col},{triangle.corner}") + + return "\n".join(lines) + "\n" + + def process_image( image_path: Path, processed_dir: Path, comparison_dir: Path, svg_dir: Path, factor: int, + grid_size: int, + cell_samples: int, open_kernel_size: int, close_kernel_size: int, median_size: int, -) -> None: + min_component_area: int, + mode: str, + triangle_threshold: float, +) -> int: original = read_image(image_path) gray = cv2.cvtColor(original, cv2.COLOR_BGR2GRAY) binary = binarize_foreground(gray) @@ -190,24 +1115,60 @@ def process_image( open_kernel_size=open_kernel_size, close_kernel_size=close_kernel_size, median_size=median_size, + min_component_area=min_component_area, + grid_size=grid_size, ) - small, pixelated = pixelate(cleaned, factor=factor) + if mode == "matrix": + mapping = matrix_map( + cleaned, + grid_size=grid_size, + triangle_threshold=triangle_threshold, + cell_samples=cell_samples, + ) + mapped_title = f"{grid_size}x{grid_size} matrix" + else: + mapping = pixelate(cleaned, factor=factor) + mapped_title = "Pixelated" stem = image_path.stem write_image(processed_dir / f"{stem}_cleaned.png", mask_to_display(cleaned)) - write_image(processed_dir / f"{stem}_pixelated.png", mask_to_display(pixelated)) + write_image( + processed_dir / f"{stem}_pixelated.png", mask_to_display(mapping.rendered_mask) + ) + write_image( + processed_dir / f"{stem}_matrix{mapping.matrix.shape[0]}.png", + mask_to_display(mapping.matrix), + ) + (processed_dir / f"{stem}_matrix{mapping.matrix.shape[0]}.txt").write_text( + matrix_to_text(mapping.matrix, mapping.triangles), + encoding="utf-8", + ) save_comparison( - comparison_dir / f"{stem}_comparison.png", original, cleaned, pixelated + comparison_dir / f"{stem}_comparison.png", + original, + cleaned, + mapping.grid_overlay, + mapping.rendered_mask, + mapped_title, ) height, width = gray.shape - svg = small_matrix_to_svg(small, width, height, stem) + svg = small_matrix_to_svg( + mapping.matrix, + width, + height, + stem, + mapping.x_edges, + mapping.y_edges, + mapping.triangles, + ) (svg_dir / f"{stem}_pixelated.svg").write_text(svg, encoding="utf-8") + return count_2x2_blocks(mapping.matrix) def main() -> None: parser = argparse.ArgumentParser( - description="Clean, pixelate, and vectorize scanned seal-script characters." + description="Clean, map, and vectorize scanned seal-script characters." ) parser.add_argument( "--input-dir", @@ -229,10 +1190,45 @@ def main() -> None: type=Path, default=Path("PreProcessing/svg_characters"), ) - parser.add_argument("--factor", type=int, default=15) - parser.add_argument("--open-kernel-size", type=int, default=2) - parser.add_argument("--close-kernel-size", type=int, default=3) - parser.add_argument("--median-size", type=int, default=5) + parser.add_argument( + "--factor", + type=int, + default=15, + help="Only used by --mode resize.", + ) + parser.add_argument( + "--grid-size", + type=int, + default=17, + help="Strict square matrix size used by --mode matrix.", + ) + parser.add_argument( + "--cell-samples", + type=int, + default=32, + help="Samples per grid cell while deskewing and classifying the source.", + ) + parser.add_argument( + "--mode", + choices=("matrix", "resize"), + default="matrix", + help="matrix maps to a strict grid; resize keeps the old mosaic-style downsample.", + ) + parser.add_argument( + "--triangle-threshold", + type=float, + default=0.18, + help="Minimum triangular evidence in an empty diagonal-connection cell.", + ) + parser.add_argument("--open-kernel-size", type=int, default=1) + parser.add_argument( + "--close-kernel-size", + type=int, + default=0, + help="Optional fixed close kernel for clean; 0 uses a grid-relative size.", + ) + parser.add_argument("--median-size", type=int, default=1) + parser.add_argument("--min-component-area", type=int, default=8) args = parser.parse_args() for directory in (args.processed_dir, args.comparison_dir, args.svg_dir): @@ -247,17 +1243,22 @@ def main() -> None: raise SystemExit(f"No images found in {args.input_dir}") for image_path in images: - process_image( + two_by_two_blocks = process_image( image_path=image_path, processed_dir=args.processed_dir, comparison_dir=args.comparison_dir, svg_dir=args.svg_dir, factor=args.factor, + grid_size=args.grid_size, + cell_samples=args.cell_samples, open_kernel_size=args.open_kernel_size, close_kernel_size=args.close_kernel_size, median_size=args.median_size, + min_component_area=args.min_component_area, + mode=args.mode, + triangle_threshold=args.triangle_threshold, ) - print(f"processed: {image_path.name}") + print(f"processed: {image_path.name} (2x2_black_blocks={two_by_two_blocks})") if __name__ == "__main__": diff --git a/PreProcessing/scripts/run_preprocessing.py b/PreProcessing/scripts/run_preprocessing.py new file mode 100644 index 0000000..0240e53 --- /dev/null +++ b/PreProcessing/scripts/run_preprocessing.py @@ -0,0 +1,143 @@ +from __future__ import annotations + +import argparse +from pathlib import Path + +import cv2 +import numpy as np + +from process_characters import ( + IMAGE_SUFFIXES, + binarize_foreground, + clean_mask, + matrix_map, + mask_to_display, + read_image, + write_image, +) + + +def matrix_to_text(matrix: np.ndarray) -> str: + return "\n".join( + "".join("1" if value > 0 else "0" for value in row) for row in matrix + ) + "\n" + + +def iter_image_paths(input_dir: Path) -> list[Path]: + return sorted( + path + for path in input_dir.iterdir() + if path.is_file() and path.suffix.lower() in IMAGE_SUFFIXES + ) + + +def process_image( + image_path: Path, + cleaned_dir: Path, + matrix_dir: Path, + grid_size: int = 17, + cell_samples: int = 32, + open_kernel_size: int = 1, + close_kernel_size: int = 0, + median_size: int = 1, + min_component_area: int = 8, + triangle_threshold: float = 0.18, +) -> None: + original = read_image(image_path) + gray = cv2.cvtColor(original, cv2.COLOR_BGR2GRAY) + binary = binarize_foreground(gray) + cleaned = clean_mask( + binary, + open_kernel_size=open_kernel_size, + close_kernel_size=close_kernel_size, + median_size=median_size, + min_component_area=min_component_area, + grid_size=grid_size, + ) + mapping = matrix_map( + cleaned, + grid_size=grid_size, + triangle_threshold=triangle_threshold, + cell_samples=cell_samples, + ) + + stem = image_path.stem + write_image(cleaned_dir / f"{stem}_cleaned.png", mask_to_display(cleaned)) + (matrix_dir / f"{stem}_matrix.txt").write_text( + matrix_to_text(mapping.matrix), + encoding="utf-8", + ) + + +def process_directory( + input_dir: Path, + cleaned_dir: Path, + matrix_dir: Path, + grid_size: int = 17, + cell_samples: int = 32, + open_kernel_size: int = 1, + close_kernel_size: int = 0, + median_size: int = 1, + min_component_area: int = 8, + triangle_threshold: float = 0.18, +) -> int: + cleaned_dir.mkdir(parents=True, exist_ok=True) + matrix_dir.mkdir(parents=True, exist_ok=True) + + image_paths = iter_image_paths(input_dir) + if not image_paths: + raise SystemExit(f"No images found in {input_dir}") + + for image_path in image_paths: + process_image( + image_path=image_path, + cleaned_dir=cleaned_dir, + matrix_dir=matrix_dir, + grid_size=grid_size, + cell_samples=cell_samples, + open_kernel_size=open_kernel_size, + close_kernel_size=close_kernel_size, + median_size=median_size, + min_component_area=min_component_area, + triangle_threshold=triangle_threshold, + ) + print(f"processed: {image_path.name}") + + return len(image_paths) + + +def build_parser() -> argparse.ArgumentParser: + parser = argparse.ArgumentParser( + description="Clean seal-script images and export 17x17 matrix text files." + ) + parser.add_argument("--input-dir", type=Path, required=True) + parser.add_argument("--cleaned-dir", type=Path, required=True) + parser.add_argument("--matrix-dir", type=Path, required=True) + parser.add_argument("--grid-size", type=int, default=17) + parser.add_argument("--cell-samples", type=int, default=32) + parser.add_argument("--open-kernel-size", type=int, default=1) + parser.add_argument("--close-kernel-size", type=int, default=0) + parser.add_argument("--median-size", type=int, default=1) + parser.add_argument("--min-component-area", type=int, default=8) + parser.add_argument("--triangle-threshold", type=float, default=0.18) + return parser + + +def main() -> None: + args = build_parser().parse_args() + process_directory( + input_dir=args.input_dir, + cleaned_dir=args.cleaned_dir, + matrix_dir=args.matrix_dir, + grid_size=args.grid_size, + cell_samples=args.cell_samples, + open_kernel_size=args.open_kernel_size, + close_kernel_size=args.close_kernel_size, + median_size=args.median_size, + min_component_area=args.min_component_area, + triangle_threshold=args.triangle_threshold, + ) + + +if __name__ == "__main__": + main() diff --git a/PreProcessing/svg_characters/篆文字_page_017_text_17_pixelated.svg b/PreProcessing/svg_characters/篆文字_page_017_text_17_pixelated.svg index 4a91823..569dedb 100644 --- a/PreProcessing/svg_characters/篆文字_page_017_text_17_pixelated.svg +++ b/PreProcessing/svg_characters/篆文字_page_017_text_17_pixelated.svg @@ -3,141 +3,55 @@ 篆文字_page_017_text_17 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +