QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 2110|回复: 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将红底证件照转成蓝底
    $ r+ H% V, x' ~* }前言
    5 q: D5 m! L' u/ R4 Uemmm…快开学了,手头只有红底证件照,但是学院要求要蓝底,这可咋办呢。懒得下ps了。自己撸起来吧。* _6 Y# M$ n0 j) |! ~* Q: O

    * x3 Z6 N! k$ G9 L2 s+ N9 b1 b; W; |  F& q& T6 D6 `' J' U
    $ m3 v- |4 ]5 M0 P

    ; P+ j3 E3 `8 u! H方法一: lableme
    0 D. `% c+ E* G2 J4 M/ flableme标注完后。得到一个json文件,然后将这种json文件转成掩码图.- S+ J! a( U; R1 ~, b8 `
    % X1 r, w; N  d; {2 w. B
    # 代码来自 https://blog.csdn.net/hello_dear_you/article/details/120130155
    ( h6 P( c3 w$ s" gimport json
    7 t- V+ ?: w) P: p5 Fimport numpy as np
    8 b7 X) \5 R5 z+ D% Y5 H9 F6 Gimport cv2' o/ v! k5 g: E8 i1 i) d  q* f  s
    # read json file% l' e9 m- z# ]
    with open("origin_json/mypic.json", "r") as f:! L* R# t5 U+ l% E0 R- O
        data = f.read()
    9 L0 {/ D& }( a+ R5 x$ x6 ?; {; h3 Z+ d1 e- _$ D
    # convert str to json objs8 Y1 v4 f& i7 R- ~6 f3 @
    data = json.loads(data)7 E% v) }, V' T1 X8 L& x

    ' h) D$ Z# I7 C" x( o3 A' k# get the points + v; T) {9 L. \9 E+ V- V
    points = data["shapes"][0]["points"]
    3 v& Y; o+ O% P' F. B6 V& lpoints = np.array(points, dtype=np.int32)   # tips: points location must be int32* W" M0 T# ?3 q% e
    6 o, V$ k2 X3 V3 Q, g- }& ~0 a
    # read image to get shape
    / R$ q& E+ A  M. o- m; himage = cv2.imread("origin_png/person.jpg"); Z6 U, ~4 Q$ q

    ; [' D1 A0 |  A9 A/ {1 M# create a blank image. Y3 y7 C& M# p  _
    mask = np.zeros_like(image, dtype=np.uint8)
    7 S* F# V; q  q4 x  n2 p. ?; I1 I; g3 B: L  I+ ~  v1 i
    # fill the contour with 255
    ; p& H! h& @& c6 B2 \cv2.fillPoly(mask, [points], (255, 255, 255))- G1 l  _& S2 e0 \: x
    9 w1 k  v+ t( u, T1 G2 Y* B
    # save the mask 4 z8 I0 ~+ {$ m3 ?5 v! S
    cv2.imwrite("mask/person_mask.png", mask)+ J1 ?3 M0 s/ ^  @7 H' H7 q
    18 B* ^3 v+ `+ i* h% o
    2/ l  ~( P! K% N# X5 K
    3
    0 k- }) A" Z) `( S5 P6 J4
    4 e# \6 f$ v' g7 Z9 d* Z6 }5- m: m: h8 R* ?
    6
    7 j4 L0 C6 A% |) l# p1 f75 v" t* z( j; u6 E) U) A* }
    8
    / ~" g7 s: ?3 ~" [- D7 t* m9
    / Z5 v$ y' G$ r1 f) l7 K* ~5 d4 l, H" n& N109 T# r- q# l. ^! ^
    11
    & A0 l+ H0 O8 m12; A7 G% ^& J! K, |& i
    135 W4 _8 q: |% l. N+ O+ {
    14. n* k% v# d0 I
    15
    , H/ J: F6 }6 W- s* {16
    , Y# G9 h2 p  }$ U& n. A17. `# ~. p: N; H$ a
    18& s' `" P/ a8 _1 a3 g0 g
    199 R, J# X8 c  N- |6 T8 o# G
    202 `. M  v! R) i8 ?& j5 z
    21
    6 _" y5 B0 @7 n5 t22
    9 ^$ Z! l0 w& X; Q9 M. S, r23
    8 B7 q8 H- @! e7 t' r6 T" T24
    # ~1 @3 n1 u( S25
    ' b+ p( R9 w9 W( Q7 W267 `* O* j2 Z2 O2 u( S2 z4 z# G
    大概是这样:9 M+ j. c$ h  m( H3 m
    8 j3 \/ F& Y) F- P9 i4 b' |

    , ?: n+ W# X: n: I! ^( t! ?" A然后利用这个mask生成图片, m5 @3 L! M9 f) z- Z% n

    # |' U3 J) T& ^$ h6 ?; N# D1 C8 K5 ^# 参考自: https://www.jianshu.com/p/1961aa0c02ee
    ' L$ c% e, y  m$ simport cv28 w: s' b0 A3 L
    import numpy as np
    ) |7 |& z, D( M4 \4 G) D: N' Y$ y$ t

    9 F% v0 H% M% u: d& M7 h/ forigin_png = 'origin_png/person.jpg'
    2 B9 s) O5 n. W# maskPath = 'mask/person_mask.png'
    ' Q; I5 S; r4 r8 AmaskPath = 'mask/bmv2.png'
    4 n3 C0 X7 b7 G) d" ?result_png = 'result_png/result_png.png'- f1 c' Y6 {; L

    $ b( L1 ~- _$ I- z$ o2 E5 t9 n* w3 L6 U
    maskImg = cv2.imread(maskPath)0 @  @: X& F7 ]) f, Y7 N- X- j
    img = cv2.imread(origin_png)) o/ b$ M8 T+ L; K/ ]3 |* F# j
    assert maskImg.shape == img.shape, 'maskImg.shape != origin_png.shape'$ v- _$ |1 `( G6 [0 m+ V0 u
    : z0 ^5 W0 t% `/ p
    h, w = img.shape[0], img.shape[1]0 `4 p8 |( x0 p! D3 |! }' R) p% ?
    print('图片宽度: {}, 高度: {}'.format(h, w))
    9 K* c! g9 |% n  T
    " l  h+ u: [+ @  T8 P, a4 ?rgb = (19,122,171)
    $ I. k/ d4 U9 r, Lbgr = (rgb[2], rgb[1], rgb[0])/ c$ g7 y; J: m1 O! T' }# J" L; Q
    # (B, G, R)
    # v4 o- x  L# f* `4 Q9 Lfor i in range(h):/ q% U( }1 n% u4 ]7 n- H
        for j in range(w):
    1 c% p- U4 I9 C7 J& B        if (maskImg[i, j] == 0).all():
    ) i" K4 i5 z3 U6 N            img[i, j] = bgr
    6 |% \2 h( F/ q' S' \3 [5 [! Lcv2.imwrite(result_png, img)+ c7 t3 M1 X8 X0 K+ L
    print('图片写入 {} 成功'.format(result_png))
    2 S2 F2 j6 K, g6 z+ }1
    + z8 C- J0 T: l9 e% {2
    $ j/ {/ d  }/ F8 z) ^6 }3 c. O3- a- T; H8 ]  i4 v: }6 S
    4$ m- [, |( K( Y' r) V  H% ^, ]6 c. j
    5
    ' \& G1 O! I+ g  r; m, \; I: M6
    # Q1 ^" x! K- ?- z; _7/ m7 L2 R+ S2 @( A0 P
    8
    3 d+ U; X! J9 Q4 p' c* m/ Y: V9+ {3 v9 b9 w3 Y" i
    10
    7 g8 q  F0 u! T. ~/ ~5 f- r/ p11
    5 U( y- |+ _/ X2 j3 _' \* f12+ P4 |5 A4 y5 ~
    13* n+ j5 z+ k0 ~( ]% W+ a
    14
    2 T0 O& p  f; X$ q0 ~" f15
    / C7 m& G+ w# l, f; t- d! _; y16
    4 a$ V" b3 a5 s: V" o& u+ w17
    ( G& o& |, z& w; ?) q3 s5 f6 k18( z% z3 G  N: h4 w* f. ^6 h# S7 D
    190 E$ M- q& O' ?6 o. a9 k; j, Y7 M
    20
    : n/ w3 W" C- d1 t21
    ' Q. e1 ?6 P- X" x4 K( r, C22' X. M6 w( K3 q' x% R7 b8 W! z5 C
    235 m+ O9 Z+ `/ {
    249 X. ?* ?2 I+ j8 D3 U7 s+ X3 ?. {2 i
    25
    , t" v2 ^4 Z& ?8 K% X4 L, T26
    1 y. n  F- _5 u1 S3 S% Z274 s: M" {, \8 K4 ?' V
    由于人长得一般,就不放图了…
    : Y: t8 E" J# }5 p& X$ P5 m% F1 T4 ^) S0 M4 F0 V$ }
    缺点:
    - E# i: g0 v* f. C1 Xlableme标注时挺费力,并且难以避免人与背景边缘会有残留红色像素的情况。
    * P$ }1 `0 X+ w6 T# t1 z3 n9 i% q0 k& U5 O5 d) c$ }# ^# X

    5 H; f& x; h, P; x$ j+ G$ L4 H# }; \0 H, L; L$ [! L9 A- T

    0 n8 ~5 |# h% B* n& D& a1 G5 W+ P; ~: Q1 X6 b+ F. \# E
    方法二: 阈值0 }$ o$ p6 f8 b6 ^- p5 g$ C
    该方法通过比较像素的RGB与背景的RGB来区分是否为图像背景。8 n- j6 P9 u+ E0 a

    8 j$ ^% Z9 j4 A  tOpencv2 @3 a7 Q$ b5 }. F2 F
    import cv2
    , s0 a" z, ~# Z  ^) _8 dimport numpy as np
    0 p/ [4 b( i" ?( E! j* P
    % H/ R8 _% W0 ^- V2 f# m
    . j& X& z* \3 r! a9 P# [3 Sdef mean_square_loss(a_np, b_np):
    6 J: n1 \( `$ p  M. R    sl = np.square(a_np - b_np)
    , ^+ A8 y( ^* G* u    return np.mean(sl). R3 v" Q+ p' B- e* d

    . o  ^2 y; V, P; x; W0 K3 b
    5 ]3 p' x" A/ b/ g  n: odef change_red2blue(origin_png, result_png):
      n7 ]. O9 v( n  m$ j7 u    img = cv2.imread(origin_png)
    ! \+ r, m& v; _* N2 Y7 J, L6 q# k& V1 e; t# ~
        h, w = img.shape[0], img.shape[1]
    + I/ M/ ^5 U8 P" e5 g0 B3 L    print('图片宽度: {}, 高度: {}'.format(h, w))
    1 N# `3 Z! c6 {$ j
    9 {* Y4 a* S3 @7 }( Q: K: U    origin_rgb = (168,36,32)  # 可以用浏览器啥的控制台工具提取出背景的rgb值
    ) z: d" }) g1 [8 K    origin_bgr = (origin_rgb[2], origin_rgb[1], origin_rgb[0])
    # A5 _/ ^$ k: d9 [9 |' A    target_rgb = (19,122,171) # 蓝底RBG
    , G2 K) R2 [) m) m, c* ^    target_bgr = (target_rgb[2], target_rgb[1], target_rgb[0])
    5 Y! o' K1 t7 e6 k
    % L3 ^: ^+ U0 l# X! f& ?; `6 x    for i in range(h):
    # p9 f) b5 w( q! d3 |7 C        for j in range(w):2 S. E, ?6 r# i" S6 U
                # (B, G, R)5 Z& j6 M! ]8 Z( U9 m
                if mean_square_loss(img[i, j], origin_bgr) < 50:  k. w2 e5 E7 ~$ D8 N0 g
                    img[i, j] = target_bgr
    / w( o1 n$ M7 n5 o
      l  L9 f6 Y# f! m" P; [* z    cv2.imwrite(result_png, img)+ u9 j) x9 C1 R- G$ h# @
        print('图片写入 {} 成功'.format(result_png))$ u" b: o7 s  g8 q: w. d

    0 F( M5 u' c/ i6 j
    ; G7 \* e0 \, X" cif __name__ == '__main__':; c: I9 J" y& ]3 X0 H) I
        # origin_png = 'result_png/result_png.png'# D% m8 G. e0 V8 q# d; j! F  I+ [
        origin_png = 'origin_png/person.jpg'
    4 A7 u: H1 d4 [4 t5 Y! _    result_png = 'result_png/result_refine.png'
    ; R* I& W! _$ m5 B" m    change_red2blue(origin_png, result_png)
    4 p0 S4 Y9 s4 r6 R+ x1 V) B3 `1
    " ?& O& j7 L$ I) G' x, P* S2
      C' e1 H5 \: f0 i, v- c; _) N6 p3
    * i, P7 g7 y; a, C0 m1 M' x4 A4
    1 _+ w- Y. k. `9 T5
    7 z! Q& e# Z& m9 K8 y: Y) G6# {# {! ~9 L  @& T: u) _3 \0 C
    7$ O+ Q. V9 Y5 z3 W  ]) a" c# }
    8
    + n* ~; A  c+ T5 e( V! t: |9
    , e5 l: U% H' Y7 H, f10
    5 v' ~8 Z3 i/ S# J0 {$ _) Z11$ E, j2 N+ ~* d; V* a% T7 a3 c9 ]
    12& j% H0 `! C) a
    13! L! ~( \$ m9 K  n/ @6 J
    14$ Q6 A2 u3 D2 _, r4 [6 e4 g) Z0 E0 b
    15: P0 V) c0 ]& T5 y
    16
    5 o8 h$ E$ d9 }1 ?1 x17+ o! N9 ~  [; v* N% p# v
    18: }& R* Z+ G+ U
    19! X% L! w- N; C" P- R
    20  V" N; \' K0 M5 z" T1 J9 K
    21
    8 w  r) M4 q% [1 e222 M$ }# ~7 w0 ^% `8 O5 T  `% }
    230 C* ^- N; t  O2 r
    24
    % h9 d' r' R2 G$ u" ?9 e9 W25* k2 H/ p. K; l
    26; P1 x# L9 e4 z- W
    279 K9 o$ b" @  C4 ^
    28
    ! @% K& @5 I4 T5 x/ I29
    9 u# k! |, c- }* F% S1 M5 M30! T* T/ g5 [  z
    31. \% I7 e( ~, b- Z
    32
    % ?* b7 K# M/ E6 t8 K1 @337 P4 w% l- d7 V2 ~9 ]  W
    349 D+ s$ ]9 ]  I- W. E4 O& o
    35
    - o+ U  A# j' L  x3 z" y结果人与背景边缘仍会存在红色像素残留9 `" B9 n( d/ \. n* i3 w

    / r' f7 ~7 j5 s7 U6 i* f% r
    , N: o2 p+ z, ~& N
    . S; ?3 D& H* o9 O" E; g. [/ z& z# L% l9 j
      F9 H7 ~2 D" h. ]( }0 y, N
    PIL
    1 K( g( N' ?) _. S5 d9 tfrom torchvision.transforms.functional import to_tensor, to_pil_image9 O; d5 A" ^- U: m# ^
    from PIL import Image0 I. U5 H( o) a! D: n+ i2 z
    import torch/ w1 `( C6 o- q! ]4 u3 L
    import time
    8 R, N) Q: m3 _1 f# c, d1 d
    ) s" ~/ P% g- q$ ~
    0 W; b1 P. C! |; l( ?, r; ~7 h" Idef mean_square_loss(a_ts, b_ts):6 e; {; ^& M! e
        # print(a_ts.shape)0 y9 H. U1 d* D# W4 f+ y- N
        # print(b_ts)
    2 l5 s/ M! |2 N# H    sl = (a_ts - b_ts) ** 2
    & D; j* ^9 I: T; U$ x1 c& w3 ]    return sl.sum()9 H. m+ w6 i* V% ]: f
      u  l+ [7 K; b# j

    2 i  |( }9 t8 h( G. `4 Idef change_red2blue(origin_png, result_png):
    . n$ P# o. R5 p' M    src = Image.open(origin_png)$ c% v) h: L: O6 \* Y
        src = to_tensor(src)$ E0 }4 Q/ V7 ]& K" z5 B2 h* ~
        # print(src.shape)  # torch.Size([3, 800, 600]): s1 m7 w: k4 w" g
        # channel: (R, G, B) / 255: j/ c/ ^6 M5 q8 W9 w6 h; J% [5 J
        h, w = src.shape[1], src.shape[2]4 \9 K: i4 ^' z0 @

    3 x4 V2 F: g% d( ?5 w: C4 k    pha = torch.ones(h, w, 3)
    / u6 n2 h. ~' b" K
    1 J& C# q! |. S: I/ M    bg = torch.tensor([168,36,32]) / 255
    - V; o+ S  i/ U$ J6 N" k& D4 u    target_bg = torch.tensor([19,122,171]) / 255
    / [* o$ u8 E+ t2 k
    5 o$ ~1 a. x) \5 |1 d9 E5 b    # C, H, W -> H, W, C
    ( P9 I/ a7 B& J; b' D# L3 f    src = src.permute(1, 2, 0)* K/ ^- D% i& T$ ?
        for i in range(h):0 Z# o6 `- X" |0 `# R
            for j in range(w):
    7 P7 I0 L- Q2 q! r            if mean_square_loss(src[j], bg) < 0.025: # 0.025是阈值,超参数' Z9 `" D5 O! N0 q
                    pha[j] = torch.tensor([0.0, 0.0, 0.0])
    ) s9 z0 W/ L+ I' V! M$ p4 v# k- Z* \
        # H, W, C -> C, H, W
    , W5 ]1 s$ o7 _7 h% ]- G    src = src.permute(2, 0, 1)
    3 e6 u% K( D$ Z3 R  C9 o1 U    pha = pha.permute(2, 0, 1)
    5 U& r8 ?; Z8 ?  F+ f    com = pha * src + (1 - pha) * target_bg.view(3, 1, 1); c; l+ y. H* Y5 S3 T% T. q! p$ ^
        to_pil_image(com).save(result_png)3 `0 J. S/ |$ O* J; J
    ; @' ~  S. L* J

    9 \  b1 b1 H" @, M/ nif __name__ == '__main__':
    # H, g" z- K0 S5 W3 f9 j- X2 x5 E5 U    origin_png = 'origin_png/person.jpg'
    5 S+ D# w; i1 O9 X( o  y    result_png = 'result_png/com.png'
    ; ~3 {5 z7 M1 x1 B+ {    start_time = time.time()
    ; D  o8 o9 i( d    change_red2blue(origin_png, result_png)
    5 M+ L1 x* }) o6 T    spend_time = round(time.time() - start_time, 2)
    6 A6 f( ~/ J, j- Y  I    print('生成成功,共花了 {} 秒'.format(spend_time))
    4 _) p8 n9 Q" @9 \* @- Z( t6 W11 k6 D% D, c5 y
    27 v/ |. c5 ]1 ^; Q* x; w; V
    3
    ! L- g  M7 P- m0 H. W4
    ' q$ y; H$ S8 F( e& Y/ U+ f- u5+ ?* ^( y* {6 p: w& P/ i( T) p
    6
    : ]8 O0 N! c: |; {, m5 i3 g% m# y0 U7
    , I! E4 F( H6 h" f7 z; R5 z; V0 z8
    6 [1 M3 v" B9 F& k* H/ L9* n0 n! T0 m2 K, S3 h) `
    10" A; i+ ~( `/ [( J
    11
    2 M% j5 u5 k2 h12
    5 I4 ?) L6 V/ Q: o13
    ! ?$ G% ~. g. u# T9 K. {- G14
    " B; ~0 K4 \0 ^15
    7 i3 D8 [# o0 o! Q16
    9 u9 ~( i% S* I# [% I, X" h2 w  @17
    4 s6 R  e5 }3 h1 e1 Q8 W' X5 m8 H186 Q( ~+ r# G6 E3 }: l+ h* p
    19" ]. R! E) _% t
    206 Y) P8 o+ ?, [' f  {  X# M
    21
    $ {  x/ h) v' Z$ K, G223 `0 e& g" p( Z+ ]/ g: x3 {: m
    23
    ( w! V; @+ x& g7 p, }240 ~5 I* E" `" y% f# Y; t7 e$ K
    25
    ( g4 P) A- o% ~% W: A. M26! G& d" I- q& n9 I" t0 m4 N
    27( A: ?# D0 K8 ], o
    280 o/ f$ X# S$ L# G( B3 k5 }6 J9 C
    29' ~7 R( j0 b# ^7 N. f5 ?8 ~$ M
    306 f& F7 \: ]+ _2 p
    312 s8 \, b' k! w) [
    32/ Y8 k8 U$ Y9 K9 f
    33
      F1 B6 l0 _! D$ k34
    4 h. `( B$ v3 A) o6 {0 T7 J, Z35
    3 ]9 I; F/ e7 l9 m6 T+ K36
    9 X& z0 A6 f0 j. T9 H3 X: H- E37
    ) X& Q1 M5 a0 ~  }* S38" ^" n; i7 Z- \" u/ i8 a& ~
    39
    ) E  C3 @5 A9 I' `# S6 D40( A( ?! G1 y" X1 w6 H. `! P- \5 h
    41
    - s3 o5 c& K& G42, L* n; I2 k. F' h: n
    43) |# P: b5 Y+ }
    44
    0 q; R% Z2 {0 X  b/ W( P/ Q45. J( q- k4 O1 {" x2 Q
    462 O% }% F% m8 }+ o( j9 ?" @
    该方法质量较好,但一张图片大概需要12秒。
    6 i" P5 u$ d8 G0 f- o
    " j0 O+ P+ e: l, H9 T& a4 Z$ F6 Q8 c

    # F# @; }% ?3 w- n& @  E7 _6 T( N& e方法四: Background MattingV2: t1 y: ^7 n1 R8 F5 i( Q7 l- K  t
    Real-Time High-Resolution Background Matting
    ) l# M$ ?+ m4 j2 R* q# j* \" nCVPR 2021 oral* d$ L3 t$ R, r

    8 _( d% b, p9 ~5 g) Q4 P0 f论文:https://arxiv.org/abs/2012.07810
    . w1 T; x; f+ t6 Y( _' z代码:https://github.com/PeterL1n/BackgroundMattingV2
    5 k4 I3 V! m* Z/ t; L" J) `  h* T3 B; q7 B/ O+ I, E) x
    github的readme.md有inference的colab链接,可以用那个跑7 Z$ O$ d( A5 M  v6 w# R! @+ S& ^

    5 q$ o7 @5 x9 |' v由于这篇论文是需要输入一张图片(例如有人存在的草地上)和背景图片的(如果草地啥的), 然后模型会把人抠出来。
    / |- x# g6 G% m8 B
    ( ?9 \1 }% E( u& i: W3 p+ G9 M于是这里我需要生成一个背景图片。2 R; b  O* T- q' W
    首先我先借助firefox的颜色拾取器(或者微信截图,或者一些在线工具,例如菜鸟工具),得到十六进制,再用在线转换工具转成rgb。
    . G% k0 L8 @% N  J3 U4 x) h- e8 G* T
    然后生成一个背景图片。
    - p' }3 g) R4 J( R3 M1 z
    ' E7 A  l, z& C& Q. E2 {+ dimport cv2
    1 }' s, g1 u3 X( t9 @- k( x- }import numpy as np' a( B* F  @9 |" L

    2 l1 T' ~% ?0 ^! F% S  ?
    & C( H  G- p3 a3 `) l* a: Z& Yimage = cv2.imread("origin_png/person.jpg")
    " d. |5 G: f" k$ z. Corigin_rgb = (168,36,32)  # 可以用浏览器啥的控制台工具提取出背景的rgb值
    : t! o* ]1 A* [' [1 Korigin_bgr = (origin_rgb[2], origin_rgb[1], origin_rgb[0]). z% |7 P# G6 n0 j/ L
    image[:, :] = origin_bgr
    ' b* ^  p- Q$ w2 D% c( k
    2 e0 y1 t& m% e" dcv2.imwrite("mask/bg.png", image)
    / Y2 Q0 v0 x6 x" y( p1
    ; b5 h. u+ P0 |3 t2
    % ~0 b8 c0 m, x+ {4 ?( x3) g1 ^4 H/ R/ a3 b, H! |
    41 ?/ M& K; B, l! t- B
    5- ~9 R- R+ F" v+ J/ @
    69 h' c5 R) B7 w6 h8 G& U$ {
    7
    ( M5 \) C+ y. I80 I$ i; g; |1 E6 z8 M  z" f0 }
    96 |: B/ |4 i. w* Z; Y; h0 b" r- [3 |
    10
    , p: s4 W/ J3 [8 k: d( v  N+ ]1 [* G
    需要上传人的照片和背景照片, 如果名字和路径不一样则需要修改一下代码
    6 u5 j6 O, f/ T0 D( z* Y" ~
    $ u+ c- x# v* ]$ S; w8 \src = Image.open('src.png')5 {, N' U2 t, x+ R1 D5 s/ }
    bgr = Image.open('bgr.png')1 S. k  [; ~) j6 u
    16 y/ z" q6 B* i! Y; f" I2 J
    27 q& {# y: F& Z# v/ r
    另外原论文是边绿底,要变蓝底,白底,红底则可以修改RGB值,举个例子,原来是这样的(绿底, RGB120, 255, 155)
    " N& |7 B7 T/ D. y
    4 f4 D2 _: a% ^com = pha * fgr + (1 - pha) * torch.tensor([120/255, 255/255, 155/255], device='cuda').view(1, 3, 1, 1)
    5 `5 l4 z) r8 o+ V1
    , s2 h6 d7 P7 _' Z0 m) l# V. H9 A+ b# {: M7 v  R
    那么加入我要换白底(255, 255, 255),就是# j( o2 ]1 P! S+ z+ K7 M0 T0 N+ W

    4 Q1 E1 F7 C, @9 t; V7 vcom = pha * fgr + (1 - pha) * torch.tensor([255/255, 255/255, 255/255], device='cuda').view(1, 3, 1, 1)
    + D, n+ T  X( n6 ?1 l1
    0 H5 Q6 b4 E' y9 b( u, ~9 E2 C% f- _. \  j3 e" r/ a0 I
    假如像我换蓝底(19,122,171)具体深浅可以调节一下RGB,就是
    9 L! X4 F9 s# Q! w* F0 X4 Y+ L# `2 {6 e/ r8 ^
    com = pha * fgr + (1 - pha) * torch.tensor([19/255, 122/255, 171/255], device='cuda').view(1, 3, 1, 1)" ^$ \& l  c% d! C
    1
    " m. A7 X1 ?' j/ f0 B' Z5 V- k总结: 其实这种方法从 任何颜色的照片 都可以 换成任何颜色的底。只要换下RGB.& j# z% j! J, U) r1 {2 U) R
    ! |5 w9 j  c5 Z) B+ r8 b! u5 Z3 V
    然后就输出图片了。可以看到效果相当好。不愧是oral。' W$ \2 C6 U4 d3 F7 w

    " e: d9 j# b& A' `6 m7 L4 h( n1 {, P* S
    原论文可以实现发丝级效果
    # Q! t/ R3 S  g; `: Z2 h
    . n4 l! {; p6 {7 J" O: W# X  I9 [" E) N  w8 N7 G" J! w
    ! u$ Q1 Z+ z  C9 S, \

    1 k) u+ M8 t% Z$ H! g
    ) a9 @4 K- _* x, w* m1 M' q报错解决方案3 N5 M6 o& }# [3 W
    can’t divided by 4 / can’t divided by 169 |3 K- W9 e* D) R* y2 k' ^
    由于该骨干模型可能进行4倍或16倍下采样,因此如果您的证件照不是该倍数的话,有两种选择方案。一种是padding, 填充后再送入模型,然后出结果后再用clip函数裁剪。另一种方式是resize, 给resize到规定倍数的宽和高。; v8 n, f8 r$ r3 D) P
    这两种方案需要的代码都可以从这篇博文找到: python图像填充与裁剪/resize
    9 Z& O5 D0 K/ P  `$ D' R9 A————————————————9 {. ~* H  l) ]* o- }. \
    版权声明:本文为CSDN博主「Andy Dennis」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    ! S3 q$ K2 G/ u# ]6 Q原文链接:https://blog.csdn.net/weixin_43850253/article/details/1263767675 ^/ c1 H$ n$ p

    0 }3 l; O  n  p4 o) n5 l% U) }' u% q( ?
    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-5-30 21:15 , Processed in 0.406704 second(s), 51 queries .

    回顶部