QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 2089|回复: 0
打印 上一主题 下一主题

python将红底证件照转成蓝底

[复制链接]
字体大小: 正常 放大
杨利霞        

5273

主题

82

听众

17万

积分

  • TA的每日心情
    开心
    2021-8-11 17:59
  • 签到天数: 17 天

    [LV.4]偶尔看看III

    网络挑战赛参赛者

    网络挑战赛参赛者

    自我介绍
    本人女,毕业于内蒙古科技大学,担任文职专业,毕业专业英语。

    群组2018美赛大象算法课程

    群组2018美赛护航培训课程

    群组2019年 数学中国站长建

    群组2019年数据分析师课程

    群组2018年大象老师国赛优

    跳转到指定楼层
    1#
    发表于 2022-9-7 11:41 |只看该作者 |倒序浏览
    |招呼Ta 关注Ta
    python将红底证件照转成蓝底
    " C( N  l( n; q前言
    , D1 u' b( x, t. c* Pemmm…快开学了,手头只有红底证件照,但是学院要求要蓝底,这可咋办呢。懒得下ps了。自己撸起来吧。
    1 F/ Q& T; i3 @. E# H
    9 m& E( L3 k) p) S$ I( T, b) m) Z
    + c2 |3 J5 b$ D' F
    0 }1 \& Q1 w  f+ X+ J( w0 l" w  U7 |! \1 T
    方法一: lableme
    0 o( w- ?2 Y2 ^9 g& e) c1 m1 f) f- [lableme标注完后。得到一个json文件,然后将这种json文件转成掩码图.
    & Z+ Z1 f7 c2 N- i9 C1 b
    ) V1 X6 N- Q% j; i' h, \# 代码来自 https://blog.csdn.net/hello_dear_you/article/details/120130155
    0 e2 R/ e1 P0 S7 I! Y* K8 ^  g8 cimport json
      a) X& S" B5 b$ O( b' l# Simport numpy as np1 n- j) _3 w7 h0 \" D) |
    import cv22 v1 F, H+ K% O* Q
    # read json file
    4 o, U* Q1 x' E2 Z( Gwith open("origin_json/mypic.json", "r") as f:$ `7 g. g& ^7 |4 }5 g% X8 s- b
        data = f.read()' }1 V$ L' n7 N9 i
      G$ W& c6 O  Q% a! y6 [
    # convert str to json objs! t6 D; n" P4 ~0 h7 f3 D
    data = json.loads(data)
    + |% x$ r! N4 q/ L% s, V7 |1 g& U4 e2 |! d0 |' S+ X1 p7 j
    # get the points / B* P  l6 A8 |' F
    points = data["shapes"][0]["points"]
    6 Q! t9 t3 \# U: rpoints = np.array(points, dtype=np.int32)   # tips: points location must be int32: [' u" X) }& E: y! E

    4 c7 L/ o6 h' i5 \8 z# read image to get shape
    * z9 V) S6 |" m; Z# P4 c4 A) K" K) limage = cv2.imread("origin_png/person.jpg"): ^0 A0 ?6 X+ t; t2 U
    6 ?7 P( y; A; E0 i. [8 Q! Z, G2 W
    # create a blank image
    & K3 e; L5 w1 q0 Z- Lmask = np.zeros_like(image, dtype=np.uint8)
    & `- q$ T  d5 R3 z; @+ P
    % d: g& V! H+ g9 }" g  o. d. q# fill the contour with 255! y3 H. P# p% n% U2 O% O  q, F5 T
    cv2.fillPoly(mask, [points], (255, 255, 255))% |3 f( P: o6 U, o: b6 C

    2 m8 T1 f" a7 ?# save the mask % s- w& q" d/ K' }6 k7 b/ D0 d' V
    cv2.imwrite("mask/person_mask.png", mask)
    . o8 R. k6 S1 ~$ M2 s  b0 h5 N1/ Z! A: @, T! S  O
    2
    ' y  u) D( E) I2 K) e  c- Z0 M; W3
    5 G% E2 G1 [  x. a& C3 D* Y- B4& n3 C2 Q* l# g0 L/ e
    5- I9 w5 Q5 Z3 I7 c- \+ o
    62 R7 A" O$ Y+ H* f7 l
    7
    # P# i4 g1 s6 X+ U& \/ k; Q8
    * }/ u6 }( t; `1 F  P9* j3 k0 h; v- O7 V
    10
    2 {3 o0 g: }; J. w: z3 X114 l1 M* P; I# t1 j9 u/ q
    127 Z7 E, I7 b7 R3 F
    13
    ) H" c4 I9 }3 E! x14
    ! M# j4 c9 j- v9 p' l2 Z! J154 M) l* k9 S- N+ i1 \- {4 V1 Y2 m
    16( L) k1 a% Q' Q. H; e9 }3 l
    17
    : c5 x/ n( q- B5 N8 C. r& @18
    6 O. B* K- t+ X0 p6 |19$ o% }/ a6 b) x' x0 E* M6 J
    20
    3 p5 |* Y8 n* T9 @8 z21
    # f1 o* q) x2 S' i226 |5 K( d1 L" E9 f  k) |, U! K4 X
    230 D# _! z" j1 o7 ]- z" F+ A
    242 @5 j( p2 g8 W# v
    25
      F" ~* U% S5 x- u3 h: }8 o26: i4 }5 }5 W+ H; G8 K
    大概是这样:$ ^" M& |5 F8 `7 E" w" X! v7 N# y
    # `) a& f1 Q8 c' j
    / h; A% g( y3 ]* f0 m
    然后利用这个mask生成图片
    ' U  Y: y  N1 Y' {0 y* H1 G% O( L$ g) s3 w, g& g
    # 参考自: https://www.jianshu.com/p/1961aa0c02ee9 z/ |9 J5 h# C0 t2 D9 K+ f9 M1 N
    import cv2
    6 v1 a7 j2 d" i. Q5 u3 Z  |8 aimport numpy as np
    ( r$ L* ]! i2 b- g* X" U7 D& @5 f6 M& N2 W- o8 y
    1 _8 X8 Z* j4 l2 O' q- s# d& \! V
    origin_png = 'origin_png/person.jpg'
    8 z* Q5 M: `7 J$ |; p, U# maskPath = 'mask/person_mask.png'
    ; O, V' {2 J0 w$ YmaskPath = 'mask/bmv2.png', z. l" A7 N7 O1 C# c  ?
    result_png = 'result_png/result_png.png'
    % x- u. K7 ?" a4 Y& l; g% V3 V
    1 q6 [1 r  r4 s' ^4 f* T5 W" O: X8 Y
    ' K7 d3 @5 g5 q8 h. U" n+ d$ KmaskImg = cv2.imread(maskPath)9 N, `9 |: H$ B- c" q
    img = cv2.imread(origin_png)' L% u! `' Y" w  ]3 C- C6 o
    assert maskImg.shape == img.shape, 'maskImg.shape != origin_png.shape'
      z/ ^1 E( i6 j& t8 B- \
    ( Z! m/ d* E% [5 o) p1 H; p2 mh, w = img.shape[0], img.shape[1]. ~2 f  A( E+ W
    print('图片宽度: {}, 高度: {}'.format(h, w))
    , {2 J  W% F" u5 m" p, ^
    " K& ~; h; l4 nrgb = (19,122,171)
    ; B8 _8 {1 L; n1 Pbgr = (rgb[2], rgb[1], rgb[0])
    9 i; p! h* ^1 }2 M) G- |& F# _# (B, G, R)
    % v' j3 T$ ~, Y% f5 ?  hfor i in range(h):# b/ K/ T0 y8 V4 H, e! Y
        for j in range(w):) \! d8 }2 ?6 Q% i2 ?
            if (maskImg[i, j] == 0).all():2 }' U8 l2 g( C3 f% i8 Q
                img[i, j] = bgr" Z0 p- J8 [) ~1 d3 `8 h: g
    cv2.imwrite(result_png, img)
    2 _0 m9 T* k8 n0 h, Iprint('图片写入 {} 成功'.format(result_png))
    % w- f6 P+ J0 c. X1
    : I6 R# S, {( s0 O2 v% z: n& e2! s8 Y* K( ~) Z3 q7 j. O$ E) \$ A. P
    3
    * X1 `/ R) \  X4* b: Y3 `3 L0 P- z! U% J; @
    5
    . h2 r3 T6 Q- N# i- c3 l6
      W* n* L* [2 D& W( S  k  [7
    2 J: k/ z7 G0 }* t1 N8
    ' S% }# J* j; R- M  Q/ C9% f3 U' K1 h, @! G
    10
    * B; M2 u! }% P  @, c3 W$ M8 ^112 n, M6 ^" w: ]- G
    12# U  D/ ]6 @8 h) b% F$ _
    13( }% o; {/ l+ i2 j( F
    14. m/ u; v% G& I+ f; a* x! z
    15
    2 t$ n5 `! w: c- m$ a16
    ! Q: Q6 l! f" z) x- ~17; ]1 x" E1 m7 ?3 |7 q) ^
    18# F$ J% }( g2 ]
    199 k) i" Y) A5 H+ r' Y
    204 Q% @( M% X" Z: A, a. P
    21, \% }; |' L( G$ c- r
    22
      k  @% O5 v9 d) `231 M# e- V4 x" P" q2 _/ @8 J' S( ]( |
    24; J0 ~- g. c- E' D
    25
    , j3 r* J' ^. @  o) C26: {' F1 G: T; N& q6 v# [) r0 J
    27
    3 V/ q& r. a  H$ ]: k由于人长得一般,就不放图了…
    ) L* q: d2 o) z; s8 d* T
    : G. G2 h3 b! t/ Z) N. `缺点:
    , m: Q0 [2 r) ~2 m7 v, R* Plableme标注时挺费力,并且难以避免人与背景边缘会有残留红色像素的情况。
    7 [5 u4 E( }; U% L1 b. n5 Q
    , ]* E! e1 ^7 C+ Q: x4 |- z8 E! \  r8 |. E3 ?

    5 V: }4 X4 F' }* I: n6 y
    3 S7 f' R2 d$ V! f5 W3 N  D: t0 Z
    方法二: 阈值
    3 E$ [  c' {2 l/ z$ V该方法通过比较像素的RGB与背景的RGB来区分是否为图像背景。
    + [4 b& \0 ~: r/ K: j
    ! h8 k& d2 U- X. V5 o- q) y, YOpencv
    $ B; f/ z' j: E9 vimport cv2
    ; D+ S- d1 Z% w. I6 \7 m6 `import numpy as np3 Y" a3 j; }* H6 ]
    : w/ C( c' g- t: s* E
    , n6 {: h; @$ _6 E& y, j
    def mean_square_loss(a_np, b_np):
    8 U9 |# u% w9 i7 @  d! l    sl = np.square(a_np - b_np)
    2 r( p) i, @$ i8 j' F    return np.mean(sl)
    ; U5 r: }. F% j, r
    : j4 T$ x' C# {  ]5 k7 f8 k: ?6 O0 O5 M, u" Y3 Y7 R
    def change_red2blue(origin_png, result_png):
    0 Q/ a8 |. Q  k1 T3 T! c    img = cv2.imread(origin_png)9 z& q+ p$ O( b) U
    & w$ s3 I. ?5 G& }$ ^% `& j
        h, w = img.shape[0], img.shape[1]
    6 t- T9 h9 d+ j    print('图片宽度: {}, 高度: {}'.format(h, w))
    - K8 Z  p. M# U6 X! a7 x& u5 ~2 t  W& \
        origin_rgb = (168,36,32)  # 可以用浏览器啥的控制台工具提取出背景的rgb值9 Z" `( e# y1 X! d$ d
        origin_bgr = (origin_rgb[2], origin_rgb[1], origin_rgb[0])
    7 E; A" @- ?/ w" u/ r  P& |2 U    target_rgb = (19,122,171) # 蓝底RBG- m4 t2 e& i1 m/ I. W: c. S) J6 n
        target_bgr = (target_rgb[2], target_rgb[1], target_rgb[0])
    $ h6 k( \3 f$ ^; H; U5 p( j
    - h1 R: n  d# f, a' J6 l    for i in range(h):8 a9 L/ c# f. p# y& v$ `2 s
            for j in range(w):
      c: b% N6 X" [: y            # (B, G, R)  G% c$ S* r. m0 m: I
                if mean_square_loss(img[i, j], origin_bgr) < 50:
    6 _  L* e9 J$ ?2 n8 X9 z                img[i, j] = target_bgr 3 _2 {. R, R& O
    6 P, \6 x$ x4 ?; m- p
        cv2.imwrite(result_png, img)9 i9 T+ A3 r5 s
        print('图片写入 {} 成功'.format(result_png))) d# s2 E. t* h) @4 P+ o8 F) o; s/ i

    ( v4 X' [8 L9 ?, c0 ^# Q6 }  r% A5 R; {% U
    if __name__ == '__main__':  ~( c, g5 K) V% ?3 q" }0 C/ H5 f
        # origin_png = 'result_png/result_png.png'
    3 _9 p7 z( c+ f1 z; @    origin_png = 'origin_png/person.jpg'; T5 B5 H$ o! S" o, q3 P
        result_png = 'result_png/result_refine.png'
    / u8 R% x7 I9 F1 C    change_red2blue(origin_png, result_png)
      X. t; w1 k9 m* C3 c1
    0 I; Z! {4 A5 N) N, G2 n) M2% x7 x+ k/ c9 g* B4 a7 w
    3
    & b4 f* ~+ B* p: J  r4 m4 Z4
    / G# o, h& Z, v  w' _5, @/ K5 l- I; u+ H
    6# ?! k, v% }4 H! K; x$ M1 D
    7  }; ?5 ]6 A+ j$ h
    80 x2 Q2 X. P) F& q
    9
    1 G4 s9 H2 D& M2 ~10
    / \, z8 D" V7 }$ U# Z; V116 Z* Q! v. y4 R* k6 d2 Q2 ]0 r
    12) J. w9 _0 ]0 l) b. D
    139 }" y* k( o2 d5 l9 h
    14- t3 _# F1 r9 H  s' f$ n5 ?8 ?
    15! {0 h# q  M: s
    16
    + K: D/ L+ d% M, r17
    ! K, c0 W; H% m7 I( I18
    4 V/ o9 _  L; U0 Q9 F, q/ ]198 U- a) T* U; U
    20+ m3 s2 `& g- A
    21
    : J/ a3 }" x0 W" Q' O22
    + l0 |( B: e5 A' G5 q230 f9 u% [" K7 w& W% }& T5 O
    24
    % r: [% v1 L3 V4 Q! K+ H25
    - ]& {7 A7 B( r) \26
    6 D( r) ~3 K" M) ^27
    8 `( L9 x$ {' I284 S( h- T8 Q+ Z' X+ M( z( h
    29
    2 V& @+ L4 c, A* V30
    % Y# V- ~5 j* c313 O4 J" N7 _* l3 |
    32
    & a8 Z# K: _1 i6 g6 a5 E. q331 Y# u, R- ^* V! i% T& H' s
    34( d4 I" B9 N5 Y
    35
    / F8 D, [8 o% Y6 b结果人与背景边缘仍会存在红色像素残留0 |$ S. N1 {% a% M+ Z& G8 j
    - r  s1 B. m# G
    : O' X/ {! Y$ X' M$ Q0 ~

    8 o4 l0 `8 j+ \# t9 K5 x6 P- N
    3 N; v& D6 S2 |+ `6 s/ _
    9 w& F6 T" V9 w+ q. K8 qPIL: a4 b) N* E+ P4 s: P. A' B/ \
    from torchvision.transforms.functional import to_tensor, to_pil_image" C$ }$ g3 v, m& ^# S9 y
    from PIL import Image( y7 O* J% G; h2 i# c
    import torch* h5 e/ N& n1 H7 F
    import time
    8 f& w0 X' O5 p" F; I; {; E; d
    * O, M! C) V; ?% a) p. w2 V
    ' r" |" g1 ~! v: u& Adef mean_square_loss(a_ts, b_ts):; v' n# x6 p. q+ `. F! @
        # print(a_ts.shape)
    7 k, `  P+ t: Z/ O% ]4 Z    # print(b_ts)! r, p$ E* ~. D1 t, t$ d
        sl = (a_ts - b_ts) ** 2
    0 I) S% |4 f* R3 x+ d    return sl.sum()  f  o" q+ i3 x* z" N

    1 r. b; N+ z, {$ t( a6 q7 r) M5 q
    ( n- q7 ~% s( \' n, _def change_red2blue(origin_png, result_png):7 |& u' h1 a" ~) ~5 C' g
        src = Image.open(origin_png)
    & `: |, A  `- k5 E6 a$ E# `    src = to_tensor(src)% v# r7 a$ l- `) \
        # print(src.shape)  # torch.Size([3, 800, 600])% j7 z4 p; V' T* W' q! o: T) Y
        # channel: (R, G, B) / 255# s& W: n( O+ f! s5 C' E. o
        h, w = src.shape[1], src.shape[2]
    ; S4 Y$ f7 a8 n3 y2 h5 H' [$ h, H* Z$ C8 N* T
        pha = torch.ones(h, w, 3)
    8 C1 \' Y* q& w% ~8 S, r4 Z- P
    , C: l9 O$ {6 F* p/ P& ?4 \    bg = torch.tensor([168,36,32]) / 255
    # `7 B& v3 J3 b# @/ t    target_bg = torch.tensor([19,122,171]) / 2556 R& ^3 ~" b+ J4 X) R

    ; P: d4 M* w7 @2 T6 A- e6 R1 h1 N    # C, H, W -> H, W, C
    3 [: P8 R% q+ ~1 |1 S    src = src.permute(1, 2, 0)
    & L2 [' s7 o+ _. S& o3 Z2 P5 m! W% [    for i in range(h):0 A+ d' p) z0 P* f4 }: v4 X
            for j in range(w):' w: i: B1 c. U# a6 W/ b
                if mean_square_loss(src[j], bg) < 0.025: # 0.025是阈值,超参数
    ( E( a4 U5 K% ?, E0 T/ ]                pha[j] = torch.tensor([0.0, 0.0, 0.0])
    0 X7 L5 [2 o& f+ @7 C% Q, s# O
    ; z, o5 ?6 ^/ g$ ]1 x! o3 W    # H, W, C -> C, H, W8 n9 G( I1 R: e2 V5 L  w
        src = src.permute(2, 0, 1)& }5 z/ v$ F0 w( a* l8 o
        pha = pha.permute(2, 0, 1)
    + ~  o8 K# Y# G    com = pha * src + (1 - pha) * target_bg.view(3, 1, 1)8 i$ a9 C' R' c6 U5 @% @
        to_pil_image(com).save(result_png)5 J, }. B+ r# l6 Y8 z- T3 r3 w

    , W; a+ f) t0 J. c; x7 `* |0 ]8 v+ o/ J; b: ^4 A8 Y) H3 Y
    if __name__ == '__main__':" ?) P8 N6 U# C* p+ M4 f
        origin_png = 'origin_png/person.jpg'
    9 X3 d7 I/ t8 l/ N    result_png = 'result_png/com.png'
    4 c" \9 J9 ^6 U. X    start_time = time.time()& _9 D, {" H3 H% X
        change_red2blue(origin_png, result_png)
    ' M9 ^5 x5 m2 _4 q9 H; C2 @% N5 h    spend_time = round(time.time() - start_time, 2)
    - v% L. T" f' E9 t5 r    print('生成成功,共花了 {} 秒'.format(spend_time))
    / F6 e4 b. L, Y- n' u9 l6 H8 b0 S1
    : m0 E& {1 B. m2 r. `2
    ) Z; [5 ]5 e; }$ L6 k3/ D6 ?7 r+ v: M; ~( @/ ^
    4
    8 \" q& s0 z8 @+ _% q* {, R4 ^8 ?5
    # k$ Q% ]/ }2 X; @) _6 x! T8 S! o6; a5 Z5 i* r, O; O2 Z5 v
    7
    1 e5 P$ N2 k0 p+ y9 R/ M! V83 I; t5 }$ k/ c$ D9 u
    95 [# J2 @+ N3 C, w( O  G* s
    10
    4 Z7 C6 t% N9 L+ M, G& a11
    6 A7 p6 P; r3 N# L2 g12
    ; O+ Y, Q% m7 o! }$ j13
    : L% G! X: c* k* t. N14. m! B' ]" B" c% Y7 Y- U  G) {( _
    157 I* g, T: Y$ ?# z% q7 ~; d( {( u
    16
    8 n& y- C0 p3 d! g6 ?1 ?% \5 m* K17
      S3 H" ^9 f; Q  ~: t: ^18
    1 D" }% `% q5 s: n194 W3 b6 k$ H2 Z$ J. s) Y
    204 p0 G% Q, x" ?6 S
    21
    : q$ v6 P$ G' I9 G5 [/ |7 C6 s) K227 P1 L5 l9 P8 {, u0 ~' B; F3 F
    23* Q6 Z( w1 u; u: U* i  Y- Q) Y
    24/ G% ~" s/ e- i  z; \
    25
    ) C) t: d+ O5 K% B1 t26
    % K3 H- @2 r( D# O8 e- N27
    7 B4 e3 `- n; }* u8 f28
    - x- i# m# P3 x6 f1 P, ?1 c1 ~297 L- q: t7 i5 B: g5 X5 ^- b
    30
    " Q9 Q4 e: ?: }& _- V31
    # |3 c: q  }( h! p' k32
    7 r) A0 G7 @: d" A4 u33
    & ~' s) z" @2 d% p348 k/ ?: M- S8 |7 v- E
    35
    4 o7 J& U4 n" |; s: ^3 s$ v# t362 H3 d# K% @, B8 h4 H/ J/ |
    37
    " y8 G+ `0 G  U38
    ) W6 v1 @7 p, h: `& s% p+ p8 e39: d1 s! Y: f. E0 @# r8 D
    40
    + ]( |% q! ]% G3 H3 I415 ]' Z% H7 n4 \$ ]
    42
    + G1 J) \4 b) W1 z" n! g436 C* P) [2 Q- P$ w6 k  X
    44# \  k8 H% y( F' }& Q7 e  ]0 C$ z
    453 |- O1 {: k1 j7 E2 T
    46
    8 p4 v" f  _- q& j9 D0 r9 e# u- a该方法质量较好,但一张图片大概需要12秒。, W: f) m+ q" s2 g, M

    3 k% J; g! y8 ]! y2 f3 X) z- P7 `* m- h6 w9 p8 A' r% A# m$ k
    2 h7 a  F4 ?: ^# |. y% s
    方法四: Background MattingV24 b4 v/ M7 k& x; X- P) }& r
    Real-Time High-Resolution Background Matting
    # t+ d) ~& D& R* v+ `CVPR 2021 oral
      \/ m% z7 ?5 b4 [
    * @8 o1 E$ W1 h' p! _* x. P论文:https://arxiv.org/abs/2012.07810
    % S3 y" Z. N3 @; o& T6 v# `7 r& r代码:https://github.com/PeterL1n/BackgroundMattingV2
    5 k1 G0 U7 E  R  E! V6 j  P$ S) d0 M
    github的readme.md有inference的colab链接,可以用那个跑  z% B; ~; S$ |5 V# R3 s

    0 y  N) \7 J8 l" z8 e" Z9 X  i5 ?由于这篇论文是需要输入一张图片(例如有人存在的草地上)和背景图片的(如果草地啥的), 然后模型会把人抠出来。
    / p, [. E( O0 v: |3 R0 R: M, i3 t4 n/ ~5 b# _
    于是这里我需要生成一个背景图片。5 l3 L6 O$ J) ]- V
    首先我先借助firefox的颜色拾取器(或者微信截图,或者一些在线工具,例如菜鸟工具),得到十六进制,再用在线转换工具转成rgb。
    3 w9 F& `9 E* e2 _/ @  i
    ( j/ e# v/ ^: }# ]然后生成一个背景图片。
    * n6 i4 ]. n1 ]( f$ m6 e3 b+ }# }% o) t6 n5 E( l
    import cv2
    . B6 e, I. v9 v/ Y* ~: z" ^( uimport numpy as np
    " B" ~! R( |* V
    9 ]) @- m# Z* c8 t, p( I0 r6 F
    . ^2 g5 |% _7 u% y/ t; G% [. Qimage = cv2.imread("origin_png/person.jpg")6 e0 P$ h0 X# `, ?; N
    origin_rgb = (168,36,32)  # 可以用浏览器啥的控制台工具提取出背景的rgb值
    : L- V9 ?5 M+ G& ?# O* A+ V& |origin_bgr = (origin_rgb[2], origin_rgb[1], origin_rgb[0])1 X- ]: O. m! t6 V, `# B8 j' V2 |
    image[:, :] = origin_bgr3 U0 G" h3 X$ o' W

    * h; u4 H: n8 xcv2.imwrite("mask/bg.png", image)
    / o( m' |0 o0 V  [1! ?8 Q( ~# A, A! G) L
    2
    , v. n8 G2 i6 B& E! ]4 ]3) u/ ^5 W, D# C$ Y: k+ J- c
    4
      l1 l: e4 e' }. [% I5& z; s- l8 e' u; l1 E
    69 D6 P) V2 v: z- p* S
    7& w* h& z; C3 Z9 A" y+ ?, ^5 j, o# _
    8
    7 c9 M2 K1 b2 E0 k4 T! [5 [8 Y9
    ' Q' i# g! Q8 A' m+ }6 |* ^9 G. e100 ]% d/ R+ q# ?. @9 V2 j" O
    / m4 |! m2 a6 t" y/ k# Y$ j/ w& R
    需要上传人的照片和背景照片, 如果名字和路径不一样则需要修改一下代码3 U$ J. W. T( J! d1 {+ L+ q. p% u/ ?' X
    % q+ K5 u( V9 j  [% X
    src = Image.open('src.png')
    1 J% F" K5 P# t" tbgr = Image.open('bgr.png')
    7 F  r( t  i# g# n9 o) {  P1' W! \" B( C+ p0 ]0 n0 X; Q
    2
    $ {: V+ x' ^$ l6 v另外原论文是边绿底,要变蓝底,白底,红底则可以修改RGB值,举个例子,原来是这样的(绿底, RGB120, 255, 155)
    , v* D# X, A  p; E4 Z* p- @( @6 @  t0 M5 }( p( U
    com = pha * fgr + (1 - pha) * torch.tensor([120/255, 255/255, 155/255], device='cuda').view(1, 3, 1, 1)
    $ B5 E. r9 k0 t/ i  Y17 A" W4 T# J: S0 W

    % @; r& X; T* z% b; _5 A那么加入我要换白底(255, 255, 255),就是
    , u3 Y8 }4 W3 Q' D
    : ^" ~% t7 o' \/ J' |* s  ]1 ccom = pha * fgr + (1 - pha) * torch.tensor([255/255, 255/255, 255/255], device='cuda').view(1, 3, 1, 1)
    1 w5 J2 Y  \4 f5 [7 u1/ K, N3 V2 t/ U4 d+ r$ S
    - J9 b5 R0 O; f( \  r" x4 u, t
    假如像我换蓝底(19,122,171)具体深浅可以调节一下RGB,就是! d! J: l- C  c0 i- B4 X
    " w5 V' C7 i% C
    com = pha * fgr + (1 - pha) * torch.tensor([19/255, 122/255, 171/255], device='cuda').view(1, 3, 1, 1)3 t* u4 l: D- \: J9 U6 y% N
    1
    5 O* X5 }/ e6 F, _  \- ^- ~# p8 G" G总结: 其实这种方法从 任何颜色的照片 都可以 换成任何颜色的底。只要换下RGB.: V( N9 a" ?9 C% m+ `

    0 h! {3 F& V  a5 Y然后就输出图片了。可以看到效果相当好。不愧是oral。: x. n& g* O( B% k

    $ {( X3 g: }" W) o# @, n# Z
    + S7 p0 b' V( w. m& p原论文可以实现发丝级效果
      ~: y# {2 c3 q
    $ z9 L# z, n1 O; B  D2 I6 \' c* H6 y

    2 b& r5 q2 N. u" k: H! a9 F! P
    ( s! A  z* ?( F( \; o0 P% `& p+ y% w
    报错解决方案
    2 D% J2 a/ f0 G- @9 w7 y$ G* H# [can’t divided by 4 / can’t divided by 16+ T5 M1 ^. F3 Z* L
    由于该骨干模型可能进行4倍或16倍下采样,因此如果您的证件照不是该倍数的话,有两种选择方案。一种是padding, 填充后再送入模型,然后出结果后再用clip函数裁剪。另一种方式是resize, 给resize到规定倍数的宽和高。# B+ m( V; s5 z8 Q& \! P
    这两种方案需要的代码都可以从这篇博文找到: python图像填充与裁剪/resize
    * _; N3 Z! e( h————————————————- W: q7 l4 L0 s5 {6 s
    版权声明:本文为CSDN博主「Andy Dennis」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。1 e/ d) C6 u9 ~; m
    原文链接:https://blog.csdn.net/weixin_43850253/article/details/126376767
    : ^6 q5 A6 Z. X) U4 a  d. Y& [# ^0 `- B* {

    9 n: n8 }% M# y& R1 _9 V
    zan
    转播转播0 分享淘帖0 分享分享0 收藏收藏0 支持支持0 反对反对0 微信微信
    您需要登录后才可以回帖 登录 | 注册地址

    qq
    收缩
    • 电话咨询

    • 04714969085
    fastpost

    关于我们| 联系我们| 诚征英才| 对外合作| 产品服务| QQ

    手机版|Archiver| |繁體中文 手机客户端  

    蒙公网安备 15010502000194号

    Powered by Discuz! X2.5   © 2001-2013 数学建模网-数学中国 ( 蒙ICP备14002410号-3 蒙BBS备-0002号 )     论坛法律顾问:王兆丰

    GMT+8, 2026-4-11 09:52 , Processed in 0.441972 second(s), 51 queries .

    回顶部