From efc6704b14b801a3e298687e4ad2382eb4cc54e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E8=88=AA=E5=AE=87?= <3364451258@qq.com> Date: Fri, 8 May 2026 08:54:47 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20=E5=90=8E=E5=A4=84=E7=90=86min=5Fsi?= =?UTF-8?q?ze=E6=94=B9=E4=B8=BA=E6=A0=BC=E5=AD=90=E9=9D=A2=E7=A7=AF?= =?UTF-8?q?=E7=99=BE=E5=88=86=E6=AF=94=EF=BC=8C=E8=87=AA=E9=80=82=E5=BA=94?= =?UTF-8?q?=E4=B8=8D=E5=90=8C=E5=88=86=E8=BE=A8=E7=8E=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit keep_largest_object: 格子面积的1% remove_small_objects: 格子面积的2% --- src/cDNA_segmentation.py | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/src/cDNA_segmentation.py b/src/cDNA_segmentation.py index 80a348d..878c56a 100644 --- a/src/cDNA_segmentation.py +++ b/src/cDNA_segmentation.py @@ -203,8 +203,9 @@ def gridding(gray: np.ndarray) -> tuple: # 第四部分:后处理(参考choice.m, choosemaxobj.m) # ============================================================ -def remove_small_objects(binary: np.ndarray, min_size: int = 20) -> np.ndarray: - """去除面积小于min_size的连通域""" +def remove_small_objects(binary: np.ndarray, cell_area: int = 1225, pct: float = 0.02) -> np.ndarray: + """去除面积小于 cell_area*pct 的连通域(pct默认2%)""" + min_size = int(cell_area * pct) labeled, num = ndimage.label(binary) result = binary.copy() for i in range(1, num + 1): @@ -213,8 +214,9 @@ def remove_small_objects(binary: np.ndarray, min_size: int = 20) -> np.ndarray: return result -def keep_largest_object(binary: np.ndarray, min_size: int = 20) -> np.ndarray: - """只保留最大连通域""" +def keep_largest_object(binary: np.ndarray, cell_area: int = 1225, pct: float = 0.01) -> np.ndarray: + """只保留最大连通域,若最大块面积 < cell_area*pct 则整块抹黑(pct默认1%)""" + min_size = int(cell_area * pct) labeled, num = ndimage.label(binary) if num == 0: return binary @@ -373,6 +375,11 @@ def main() -> None: # ---- 步骤3: 全图逐块分割(Otsu + TV去噪) ---- print("\n[步骤3] 全图逐块分割...") + # 计算每个格子的面积,用于自适应后处理阈值 + cell_h = int(np.median(np.diff(y_grid))) if len(y_grid) > 1 else 35 + cell_w = int(np.median(np.diff(x_grid))) if len(x_grid) > 1 else 35 + cell_area = cell_h * cell_w + bw_full = np.zeros_like(gray) if len(x_grid) >= 2 and len(y_grid) >= 2: for i in range(len(y_grid) - 1): @@ -396,11 +403,12 @@ def main() -> None: bw_blk = (blk_denoised > T).astype(np.uint8) except ValueError: bw_blk = np.zeros(blk.shape, dtype=np.uint8) - # 后处理:保留最大连通域 - bw_blk = keep_largest_object(bw_blk, min_size=8) + # 后处理:保留最大连通域(最小面积 = 格子面积的1%) + bw_blk = keep_largest_object(bw_blk, cell_area=cell_area) bw_full[r1:r2, c1:c2] = bw_blk - bw_full = remove_small_objects(bw_full, min_size=20) + # 全局去小连通域(最小面积 = 格子面积的2%) + bw_full = remove_small_objects(bw_full, cell_area=cell_area) fig_full = plot_full_segmentation(gray, bw_full, "全图逐块Otsu分割结果") fig_full.savefig(os.path.join(OUTPUT_DIR, 'result_full_segmentation.png'), dpi=150, bbox_inches='tight')