Files
Toolbox/dev_test_scripts/debug/debug_mall_crop_mask.py
T
yangxiangyuan a3e8911deb feat: 新增作息报时器功能并替换短链接前缀为/to/
- 新增作息报时器独立模块,包含完整的日程管理、语音播报和待机功能
- 短链接正式前缀由/l/改为/to/,解决手机小屏下与I、i、1字形混淆问题
- 保留旧前缀/l/、/L/、/I/、/i/兼容已分发的旧短链
- 新增短码大小写兜底匹配,仅唯一匹配时生效避免歧义
- 新增防爆紧急替换功能,可轮换首页鉴权并替换短链接
- 新增多个调试和集成测试脚本,保障数据安全和功能回归
2026-10-09 14:05:36 +08:00

105 lines
3.6 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# -*- coding: utf-8 -*-
# 调试:宝龙导视牌 logo 裁切 · 掩膜参数迭代
# 目标:7 行连通域计数 = [11,11,10,11,11,11,11](r2 行牌子上只有 10 格)
# 用法:python dev_test_scripts\debug\debug_mall_crop_mask.py
import os
import sys
import cv2
import numpy as np
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', 'tools'))
from tool_crop_mall_logos import imread_u, imwrite_u, detect_board_quad, warp_board # noqa: E402
SRC = r'D:\Temp文件\baolong-mall\照片.jpg'
HERE = os.path.dirname(os.path.abspath(__file__))
img = imread_u(SRC)
quad = detect_board_quad(img)
warped = warp_board(img, quad)
wh, ww = warped.shape[:2]
gray = cv2.cvtColor(warped, cv2.COLOR_BGR2GRAY)
hsv = cv2.cvtColor(warped, cv2.COLOR_BGR2HSV)
S = hsv[:, :, 1].astype(np.float32)
V = hsv[:, :, 2].astype(np.float32)
# 局部纹理(box filter 标准差):过曝区颜色失效时靠纹理兜底
gf = gray.astype(np.float32)
m1 = cv2.boxFilter(gf, -1, (9, 9))
m2 = cv2.boxFilter(gf * gf, -1, (9, 9))
STD = np.sqrt(np.maximum(m2 - m1 * m1, 0))
def build_mask(s_th, v_th, t_th, close_k, open_k):
mask = (((S > s_th) | (V < v_th) | (STD > t_th)).astype(np.uint8)) * 255
mask[:60, :] = 0
mask[-60:, :] = 0
mask[:, :60] = 0
mask[:, -60:] = 0
mask = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, np.ones((close_k, close_k), np.uint8))
mask = cv2.morphologyEx(mask, cv2.MORPH_OPEN, np.ones((open_k, open_k), np.uint8))
return mask
def row_counts(mask):
n, labels, stats, cents = cv2.connectedComponentsWithStats(mask, 8)
blocks = []
for i in range(1, n):
x, y, bw, bh, area = stats[i]
cx, cy = cents[i]
if area < 8000 or bw < 100 or bh < 80 or bw > 0.35 * ww or bh > 0.25 * wh:
continue
if cy < 0.17 * wh or cx < 0.06 * ww:
continue
blocks.append((cy, cx, x, y, bw, bh, area))
blocks.sort()
rows = []
for b in blocks:
if rows and abs(b[0] - rows[-1][-1][0]) < 60:
rows[-1].append(b)
else:
rows.append([b])
return [len(r) for r in rows], blocks, rows
combos = [
(45, 140, 999, 9, 7), # 旧参数(仅颜色)
(30, 170, 12, 21, 9),
(25, 180, 10, 25, 11),
(25, 180, 14, 25, 13),
(20, 190, 12, 29, 13),
(30, 170, 16, 21, 11),
]
best = None
for c in combos:
mask = build_mask(*c)
counts, blocks, rows = row_counts(mask)
print(c, '->', counts)
if counts == [11, 11, 10, 11, 11, 11, 11]:
best = (c, mask, rows)
break
if best:
c, mask, rows = best
scale = 1600.0 / ww
vis = cv2.resize(warped, (1600, int(wh * scale))).copy()
for r in rows:
for (cy, cx, x, y, bw, bh, area) in r:
cv2.rectangle(vis, (int(x * scale), int(y * scale)),
(int((x + bw) * scale), int((y + bh) * scale)), (0, 255, 0), 2)
imwrite_u(os.path.join(HERE, 'blocks_preview.jpg'), vis)
imwrite_u(os.path.join(HERE, 'mask_preview.jpg'), cv2.resize(mask, (1600, int(wh * scale))))
print('BEST', c)
else:
print('无完美组合,取最后一组出预览')
mask = build_mask(*combos[-1])
counts, blocks, rows = row_counts(mask)
scale = 1600.0 / ww
vis = cv2.resize(warped, (1600, int(wh * scale))).copy()
for r in rows:
for (cy, cx, x, y, bw, bh, area) in r:
cv2.rectangle(vis, (int(x * scale), int(y * scale)),
(int((x + bw) * scale), int((y + bh) * scale)), (0, 255, 0), 2)
imwrite_u(os.path.join(HERE, 'blocks_preview.jpg'), vis)
imwrite_u(os.path.join(HERE, 'mask_preview.jpg'), cv2.resize(mask, (1600, int(wh * scale))))