feat: 新增作息报时器功能并替换短链接前缀为/to/
- 新增作息报时器独立模块,包含完整的日程管理、语音播报和待机功能 - 短链接正式前缀由/l/改为/to/,解决手机小屏下与I、i、1字形混淆问题 - 保留旧前缀/l/、/L/、/I/、/i/兼容已分发的旧短链 - 新增短码大小写兜底匹配,仅唯一匹配时生效避免歧义 - 新增防爆紧急替换功能,可轮换首页鉴权并替换短链接 - 新增多个调试和集成测试脚本,保障数据安全和功能回归
This commit is contained in:
@@ -0,0 +1,104 @@
|
||||
# -*- 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))))
|
||||
Reference in New Issue
Block a user