Files
SignatureSystem/lib/__pycache__/image_processor.cpython-39.pyc

99 lines
8.0 KiB
Plaintext
Raw Normal View History

2026-07-20 13:16:17 +08:00
a
<00><>Xj)<00>@s<>ddlZddlZddlZddlZddlZddlmZddlm Z m
Z
m Z e<03> e <0A>Zddd<07>Zd d d <0A>Zd!dd<0F>Zd"dd<12>Zdd<14>Zdd<16>Zdd<18>Zdd<1A>Zdd<1C>Zdd<1E>ZdS)#<23>N)<01>ndimage)<03>Image<67> ImageDraw<61>
ImageChopsF<EFBFBD> 前端操作c Cs<>t<00>t<02>|<00><01>}tjd|jt|j<08>d|id<03>|r<t ||<05>}t
||<05>}t ||<05>}|dkrdt |||<05>}|dkst|dkr<>t ||||<05>}t||<05>}t||<05>}t<02><03>}|j|dd<06>|<07>d<04>|<07><12>}tjdt|j<08>t|<08>d|id<03>|S)us处理签名/印章图片,返回紧致裁剪后的 PNG 字节。
``height_cm`` **不再在此函数处理**:图片处理始终在原始 DPI 下进行,
保证笔画细节不丢失;最终在 Word 里的显示尺寸由 ``field_codes.insert_image_after_field``
的 ``height_cm`` 参数控制Word 渲染时按文档 DPI 高质量地下采样)。
u1[图片处理] 原始图片: 模式=%s, 尺寸=%s<>
log_source<EFBFBD><01>extrar<00>PNG<4E><01>formatu=[图片处理] 处理完成: 最终尺寸=%s, 大小=%d bytes)r<00>open<65>io<69>BytesIO<49>logger<65>info<66>mode<64>str<74>size<7A> _binarize<7A>_remove_white_background<6E>_crop_transparent_border<65>_add_edge_noise<73> _rotate_image<67>_remove_small_clusters<72>_crop_to_content<6E>save<76>seek<65>read<61>len) <09> image_bytes<65> is_signature<72> noise_level<65>
rotate_min<EFBFBD>
rotate_maxr<00>img<6D>buf<75>result<6C>r(<00>.\lib\image_processor.py<70> process_image s$


 


 r*<00><00><><00>-C<1C><>6?<3F>2c Cs<>|jdkr|<00>d<01>}t<02>|<00>}|dd<02>dd<02>df}|dd<02>dd<02>dd<03>fjdd<05><01>tj<06>}||k||k@} | <09><07>sz|Stjdt d<07>}
t
j | |
d<08>\} } | d kr<>|S| j } t|| |<05>}t
<EFBFBD> | | t| d
<00><01><03>tj<0F>}t<02>||k<00>d }||d k}t|<10>d k<02>rtjd | |d |id <0A>|St<02>| |<10>}t |<11> <0A><00>}t ||<00> <0A><00>}d||<t<15>|d<01>}tjd| t|<10>|d|tt | <09> <0A><00>d
<EFBFBD>||d|d |id <0A> |S)uO剔除零散噪点簇:用连通域分析找出面积过小的内容块并清除。
判定"内容像素"``(alpha > alpha_threshold) AND (亮度 < brightness_threshold)``
(与 :func:`_crop_to_content` 一致。8-连通域分组后,面积低于
``max(min_area_ratio × 图像总像素, min_area_abs)`` 的簇被视为噪点,
对应像素的 alpha 置 0。
双阈值设计:
- ``min_area_ratio=0.0001``0.01%):高分辨率图(如 2025×921的相对阈值
≈ 186 像素,足以剔除孤立黑像素(实测噪点簇 ≤ 13 px又保留真实笔画
(实测最小真实笔画 285 px
- ``min_area_abs=50``:低分辨率图的兜底,防止相对阈值过小失效
若需更激进清洗(如打印文档无小笔画),可把 ``min_area_ratio`` 调到 0.001。
<20>RGBAN<41><00>)Zaxis)r0r0)Zdtype)<01> structurer<00>uT[图片处理] 剔除噪点簇: 共 %d 簇,全部 >= 阈值 %.0f px无需清理rr<00>rrrru<>[图片处理] 剔除噪点簇: 共 %d 簇,移除 %d 簇 (%d 像素,占内容 %.2f%%);阈值=%.0f px (相对 %.3f%% + 绝对 %d px)<29>Y@<40>d)r<00>convert<72>npZarray<61>maxZastypeZint16<31>anyZones<65>intrZlabelr<00>sum<75>rangeZint64<36>whererrrZisinrZ fromarray)r%r<00>alpha_threshold<6C>brightness_thresholdZmin_area_ratioZ min_area_absZarrZalphaZrgb_maxZ content_maskr2ZlabeledZ num_featuresZ total_pixelsZarea_thresholdZsizesZ small_labelsZ
small_maskZremoved_pixelsZremoved_contentZcleanedr(r(r)r6sD


* 
<EFBFBD>   

<06>rcsp|jdkr|<00>d<01>}|<00><02>\}}}}t<03>d|||f<03><02>d<03>}|<07><05>fdd<05><08>} |<08><05>fdd<05><08>}
t<06>| |
<EFBFBD>} | <0B><08>} |j d|j dp<>d} t
| <09> <0B>dd <09><00>}t
|
<EFBFBD> <0B>dd <09><00>}t
| <0B> <0B>dd <09><00>}t j d
t|j <09>t| <0C>|| d || || d || || d || d |id <0A> | <0C>rl| dd|j d|j dfk<03>rl|j }|<00>| <0C>}t j dt|<11>t|j <09>t| <0C>d |id <0A>|S)u<>末尾紧致裁剪:联合 alpha 和 RGB 亮度判断内容区域。
内容判据:``(alpha > 30) AND (亮度 < 210)``
r/ZRGB<47>Lcs|<00>kr dSdS<00>N<><4E>rr(<00><01>p)r?r(r)<00><lambda>~<00>z"_crop_to_content.<locals>.<lambda>cs|<00>kr dSdSrBr(rD)r@r(r)rFrGrr3Nu<4E>[图片处理] 紧致裁剪诊断: 尺寸=%s, bbox=%s, 高alpha像素=%d/%d (%.1f%%), 暗像素=%d/%d (%.1f%%), 内容像素=%d/%d (%.1f%%)r5rru/[图片处理] 紧致裁剪: %s -> %s (bbox=%s))rr7<00>splitr<00>merge<67>pointrZdarker<65>getbboxrr<Z histogramrrr<00>crop)r%rr?r@<00>r<>g<>b<>aZlumaZ
alpha_maskZ luma_maskZcombined<65>bboxZtotal_pxZ alpha_cntZdark_cntZ content_cntZbeforer()r?r@r)rss4

 <06>$
<1A>r<00><>csFtjdd|id<03>|jdkr&|<00>d<04>}|<00><04>fdd<06><08>}|<00>d<07>}|S)Nu0[图片处理] 执行手写签字黑白二值化rrrAcs|<00>kr dSdSrBr()<01>x<><01> thresholdr(r)rF<00>rGz_binarize.<locals>.<lambda>r/)rrrr7rJ)r%rrUr(rTr)r<00>s 


rc Cs<>tjdd|id<03>|jdkr&|<00>d<04>}|<00><04>}g}|D]F}|\}}}}|dkrj|dkrj|dkrj|<03>d<06>q6|<03>||||f<04>q6|<00>|<03>|S)Nu*[图片处理] 执行白底转透明抠图rrr/<00><>)rCrCrCr)rrrr7Zgetdata<74>appendZputdata) r%rZdatasZnew_data<74>itemrMrNrOrPr(r(r)r<00>s

  
rcCs@tjdd|id<03>|jdkr&|<00>d<04>}|<00><04>}|r<|<00>|<02>}|S)Nu'[图片处理] 执行透明边框裁剪rrr/)rrrr7rKrL)r%rrQr(r(r)r<00>s


rc Cstjd|d|id<03>|jdkr(|<00>d<04>}|j\}}|<00><05>}|d}t|<03>D<00>]<5D>}t|<04>D<00>]<5D>}|||f\} }
} } | dkr|qXd} tdd <09>D]|}tdd <09>D]b}||||}}d|kr<>|kr<>nq<>d|kr<>|kr<>nq<>|||fd dkr<>d
} q<>q<EFBFBD>| r<><00>qq<>| rXt<07><07>|d krXt<07>| |<06>}t<07>| |<06>}||}||}d|k<01>r^|krXnqXd|k<01>rx|krXnqXt d t
d| t<07>d d<0E><00><02>}t d t
d|
t<07>d d<0E><00><02>}t d t
d| t<07>d d<0E><00><02>}t d t
d| t<07>dd<10><00><02>}|||fd dkrX||||f|||f<qXqJ|S)Nu+[图片处理] 添加边缘噪声: level=%drrr/r1rF<><46><EFBFBD><EFBFBD><EFBFBD>r0Tg$@rCi<><69><EFBFBD><EFBFBD><EFBFBD>i<><69><EFBFBD><EFBFBD><EFBFBD>
) rrrr7r<00>loadr=<00>random<6F>randint<6E>minr9)r%r"r<00>w<>hZpixelsZ intensityrS<00>yrMrNrOrPZis_edgeZdxZdyZnxZnyZoffset_xZoffset_yZnrZngZnbZnar(r(r)r<00>sD


04rcCsN||kr||}}t<00>||<02>}tjd|||d|id<03>|j|tjddd<06>}|S)Nu+[图片处理] 旋转: %d度 (范围 %d~%d)rrTr4)Zresample<6C>expandZ fillcolor)r]r^rr<00>rotaterZBICUBIC)r%r#r$rZangler(r(r)r<00>s 
 rcCsLt<00>t<02>|<00><01>}t|d<01>}t|d<01>}t<02><03>}|j|dd<03>|<02>d<04>|<02><08>S<00>Nrr
r r) rr rrrrrrr<00>r r%r&r(r(r)<00>preview_remove_white<74>s


rgcCsVt<00>t<02>|<00><01>}t|d<01>}t|d<01>}t|d<01>}t<02><03>}|j|dd<03>|<02>d<04>|<02> <09>Sre)
rr rrrrrrrrrfr(r(r)<00>preview_binarize<7A>s



rh)Frrrr)r+r,r-r.)r+r,)rR)rr]Zmath<74>loggingZnumpyr8Zscipyr<00>PILrrr<00> getLogger<65>__name__rr*rrrrrrrrgrhr(r(r(r)<00><module>s* 
<00>
*<00>
=
$

%