QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 2126|回复: 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将红底证件照转成蓝底/ O' {1 p+ n% j$ c. ^, b1 z6 y
    前言
    9 x; r) z1 V" u8 |2 xemmm…快开学了,手头只有红底证件照,但是学院要求要蓝底,这可咋办呢。懒得下ps了。自己撸起来吧。
    ) F! S2 x% q' L7 S) @( v& b& a8 s" i- @( I) d! D9 e8 [
    ( n# `9 h; i8 o  y3 N: d

    ( J8 Y$ J; O( q- F1 j
    2 i8 l6 p3 ~  J方法一: lableme
    9 Q1 e, f! K/ [, P% J$ l5 Elableme标注完后。得到一个json文件,然后将这种json文件转成掩码图.& g4 }* D4 ]* ~8 M2 G8 h& O1 b; H1 a

    0 A. z3 t$ x: X$ R# 代码来自 https://blog.csdn.net/hello_dear_you/article/details/120130155
    7 a/ h. c6 N3 T: Gimport json
    " c! l9 `. G& v- x6 L& U; Cimport numpy as np
    0 f! s  {! \6 u+ @& gimport cv2
    " K/ W8 G6 a( }4 q3 ?# read json file
    ' V6 E  i1 S6 ]( jwith open("origin_json/mypic.json", "r") as f:
      e; v# p4 U1 Y8 {0 Q# A; g    data = f.read()- w3 N+ n# `9 l; L* u) v

    " ?8 t$ `4 a- H' e7 @5 U+ n8 w# convert str to json objs9 X4 y0 f& u5 x- E/ z+ W
    data = json.loads(data)* p' N9 s+ R7 V5 {' }
    3 X& O& q& g( `
    # get the points : e# e7 w7 z' ^1 p5 {1 L
    points = data["shapes"][0]["points"]
    4 u# l9 S! m1 E' M5 t5 g. k. Npoints = np.array(points, dtype=np.int32)   # tips: points location must be int32
    - ]" f6 v  j$ D' t- G8 b" e. t. N7 T' J# o0 F
    # read image to get shape
    1 u, A* X) u, c$ D: F8 ?image = cv2.imread("origin_png/person.jpg")
    + K  t' Z$ {3 {0 u7 y4 F3 Y9 z+ ?( ~4 i
    # create a blank image6 a* k. }) L2 Z. h4 c8 a
    mask = np.zeros_like(image, dtype=np.uint8)
    ( a3 K1 G* p' p9 k1 e+ A; E0 K
    / h4 ^, J, b, f. ~5 {& Z. r- t' `) D# fill the contour with 255
    ( Z- {7 o( L- R) e& Qcv2.fillPoly(mask, [points], (255, 255, 255))
    8 \2 @; @- v, W& Y* Z% ?
    / k% E3 C. x' h% @3 @5 f) Z# save the mask
    : X; K- F5 c2 x, `cv2.imwrite("mask/person_mask.png", mask)
    4 J# n/ l; i0 e1
    ! l1 }5 c: o1 }: {+ S1 ]2 z2( K- U. D2 @% u- t# f9 I
    3# L+ ]4 T: h* N3 }
    4% I) j5 V2 o) K" b. I9 ?$ y/ X$ P
    5
    7 q4 |$ l! f: ~9 g% D66 Z3 C* e1 U. _1 @* W% u
    7
    4 q' `( a; w1 I+ d3 n7 [; _. Y82 g; U& |- n( G- p6 i2 p
    9
    ' @- m# `/ k% W2 g0 O10
    7 q5 |3 g6 M- R6 F" s* Y11: q! m8 n( A( K& E) z* X1 U, s4 r
    12
    9 P6 |4 x* [9 F* _5 J2 a13
    2 }+ \  p) @" g3 F3 T14
    ( |( S* p6 Y4 [  q% |% k5 v2 x1 T5 j151 j5 A4 \/ I, I
    16
    5 Z6 H$ d6 {* r. G5 A# O175 _; [. ~3 w1 W9 V' b( ^
    18
    ( ^3 |' }. |( z) `7 R19
    # G4 `9 S, j. {; K! P- E20
    ; c: m, [1 K, _) \21( M0 Q0 K( S' A7 Q4 U  N- W$ I
    22
    3 z: d; {/ |. i3 d, U/ C+ w23, @1 f4 L( G  B
    24" v6 o5 r6 g$ X; l0 `# @* g
    25
    ; N# S& \2 c+ j* R# E; N& A266 O0 L* V* k" ~8 R/ y
    大概是这样:
    7 ^/ f! x; ]- A2 B2 K7 ?3 Q) {' ~
    & o" r: K. _0 l! f* e* t
    1 `$ K1 a% N! J然后利用这个mask生成图片
    % Y( Q+ f, J4 U/ @5 w: S) c
    ) s3 g: U, p! R6 A( V% K# 参考自: https://www.jianshu.com/p/1961aa0c02ee' t& m; v/ E3 k6 Q. g
    import cv2
    6 a, m6 V9 ?, c- rimport numpy as np4 z% Q  z7 R! v1 H2 N7 y3 v

    " u" g3 s: R2 B* j. m% i: u; D" d4 s  F4 X2 h. r
    origin_png = 'origin_png/person.jpg') y, v( c/ r& L" h1 e
    # maskPath = 'mask/person_mask.png'8 t0 j1 V$ ~. s9 f- r) G  F
    maskPath = 'mask/bmv2.png'
    1 j3 Y* a! n# P( N* N9 D+ Z7 o* @3 Vresult_png = 'result_png/result_png.png'
      ^+ i1 G$ ^  L1 c( m1 r: y" s

    / _/ y/ U. }8 r, W8 N' N# I2 KmaskImg = cv2.imread(maskPath)6 M2 X0 S9 S, `$ A; n, O
    img = cv2.imread(origin_png)2 D/ [/ N( n9 v! T5 x
    assert maskImg.shape == img.shape, 'maskImg.shape != origin_png.shape'; e/ O5 z+ c- r  p( K9 u
    ; ?) i% k% y) u: t0 L
    h, w = img.shape[0], img.shape[1]7 _' H* X$ w+ x0 h
    print('图片宽度: {}, 高度: {}'.format(h, w))
    - b* y& Y( w/ f9 n+ y. X' }3 r4 z) x8 P- q4 k2 e7 l
    rgb = (19,122,171), C; ~; a9 K( q) C  K& |
    bgr = (rgb[2], rgb[1], rgb[0])
    5 s% T; G4 }8 Z# z# N- x# (B, G, R)- m, X2 `" U/ d) o$ W& k  P5 e
    for i in range(h):
    # x" p: L4 L; F0 n5 v    for j in range(w):
    $ Y9 l3 G/ U  A) |2 `* R) E. x        if (maskImg[i, j] == 0).all():
    : Q+ ]' m, y6 i8 r. i& G            img[i, j] = bgr7 _4 M  w* o3 m( ]* u
    cv2.imwrite(result_png, img)
    - I6 U. v& K6 c" p3 `$ O2 Gprint('图片写入 {} 成功'.format(result_png)), S5 i0 i* a1 v$ s8 S! {# c( l* ]8 L9 ?
    1
    # Y  S, z; v5 Y* e& ^$ B+ H& s2) |& K  [% t6 M) W- O2 `3 K0 e
    32 f9 K$ g5 a1 b' [; A. J7 k) y* c
    4
    4 v$ \- H; ~4 R4 x# p5
    0 H  E# d; k- e6! f& ?+ D) ^  w$ ~
    7. h1 Y* r+ p% ]# D) T! z
    8
    4 D( F* t# }3 G* a  s6 `0 ~% s9
    ' e2 {( b- V- k/ L' r10, V) h9 `+ A1 e  x4 W: `) |- j
    11
    - ?- t% o, q, P$ F5 X$ C123 J8 Q% P' [' q
    130 J' h9 U/ D: `% S7 K
    14
    : ?$ k, n+ p, A" w% V15
    , ~' P! d5 F+ i  Z16
    6 o. K  D% I4 }8 d* |$ z17
    ) F, j# ]% S# x: s9 L0 `7 x184 J2 V& c3 r& [) i, [) l0 |6 |, V9 j
    19
    5 @' _! x. A* h" k" o$ X20
    2 `# j0 g1 b4 J1 z! L. Y; g" B21
    ; x0 @# I& {- q# @6 C22' D: y* t! O8 q+ l7 M( H" l$ k7 y( K
    23" r, t8 N4 f: w. @: F+ N! C
    24/ d8 p; C; d4 U! \# q8 _6 l( d6 d
    25
    % t; C9 h6 N$ b+ w4 ~0 k26
    9 V1 d8 \" i+ j2 F; S' C27
    $ ]! d, C" g6 w0 Z' T由于人长得一般,就不放图了…
    ! E, M6 t8 j% k! F: u8 f7 p$ Q0 J  j/ O
    缺点:
    - Y$ M) ]1 `" z# T) p$ w) ^% E9 Y1 Ilableme标注时挺费力,并且难以避免人与背景边缘会有残留红色像素的情况。' I8 J" s0 p+ E% l% g( h" Z" z. k& k* y

    0 N6 k- k  C5 J" u  r3 U  l' d  w  X5 q1 |* o
    ; O! z3 o, d) Y! o- C% j7 _
    4 J7 l3 S6 A, U/ o6 X
    4 B; y7 E: _! B5 m: r0 \
    方法二: 阈值4 D! d: y8 d: i8 s, t$ ^  v
    该方法通过比较像素的RGB与背景的RGB来区分是否为图像背景。
    . E' P: a. `/ q+ ?( v9 A  E# \  w
    & L5 i* C! B* {4 wOpencv
    # c; U6 N+ @: G" g; `# K. @6 Timport cv2) u: w, R+ z2 j% D  f& l* r
    import numpy as np
    , p) r9 z+ N" D; W( ~& l1 H' G0 y$ @

    , \- ^$ K- Q0 Gdef mean_square_loss(a_np, b_np):- g3 p4 t, o9 b3 @6 a
        sl = np.square(a_np - b_np)& S# g8 {0 }' \: O
        return np.mean(sl)! O6 e/ y# l+ ]) B
    , Y, k. h4 B6 D9 d0 x
    4 O/ T4 ^' a# ]2 Y; K
    def change_red2blue(origin_png, result_png):4 C  f7 l3 o' k: }; z
        img = cv2.imread(origin_png)
    4 f  Z9 y7 d( Z# g* l# c7 n% n
    ; b- s7 ?2 c" k& K    h, w = img.shape[0], img.shape[1]
    4 B2 g; Y; Q' y1 Y# t    print('图片宽度: {}, 高度: {}'.format(h, w))
    ; ~2 R/ t. ^0 G& X8 u/ A; [/ w, S0 L! _# S5 t
        origin_rgb = (168,36,32)  # 可以用浏览器啥的控制台工具提取出背景的rgb值; _. f3 d, x% k
        origin_bgr = (origin_rgb[2], origin_rgb[1], origin_rgb[0])& C, E* v/ J5 z. }$ G) _9 R
        target_rgb = (19,122,171) # 蓝底RBG8 x( h) D, X; ^" r* t( }) ~
        target_bgr = (target_rgb[2], target_rgb[1], target_rgb[0])
    8 e& M, x+ J: z! O0 ~) w* p- S" u( U% s
        for i in range(h):2 J' K. a+ u4 j
            for j in range(w):
    % u' p# i" |# f% G1 N  w            # (B, G, R)
    ' f( _" T, h0 `, J2 s            if mean_square_loss(img[i, j], origin_bgr) < 50:# ~4 R6 @+ I) t+ h0 s! t9 |
                    img[i, j] = target_bgr
    # q" }5 h; c5 x! T3 ]+ s% y" l/ P. @7 I9 p8 F: B! Y
        cv2.imwrite(result_png, img)
    2 U% M! r8 X4 Q1 N1 ?, K: l# c2 d    print('图片写入 {} 成功'.format(result_png))
    * n5 c" r) d: ~' x, q8 ]
    $ y) P# o( `: D0 t4 Y. z& k
    $ F; Y8 g/ E' Gif __name__ == '__main__':0 |0 m5 r% K0 D
        # origin_png = 'result_png/result_png.png'& R$ s# A/ e- u; o! g  u" \( H  K
        origin_png = 'origin_png/person.jpg'
    % t" j0 ]. M% C  ^% _    result_png = 'result_png/result_refine.png'9 O4 a: f" C! _' e8 t$ H$ l
        change_red2blue(origin_png, result_png)
    1 r" ^1 G" k/ w6 `+ i* u! ~1
    ! P3 Q2 ]0 r; s8 k' c( u( q3 n3 |3 u, s20 c3 X4 f* |! M4 M( S( x; {( f
    3; |  r, a& u/ y* O' o( ~1 |- Z
    4
    3 ~. N' f6 e) l. K9 |7 g- J5. y) ]  A; F: @& z1 F# n4 H, L- ?
    6
    8 f, g6 W0 Z: {9 L7
    & [6 [4 x8 X) Y4 N2 v2 }! L. B8
    # O1 b) A" J6 E5 K$ H& @9" k2 v; y2 r2 j2 y7 X
    10& D1 A% w# `, V. G1 K0 ]1 f+ [
    117 Q, w( g9 [' w8 f# d. C4 Z; }0 }
    12
    $ t/ Q7 \) ~8 R& _, M0 P13* h8 D! G9 w( p- d# V+ U% a
    14, l( ^. {& M$ t  p) t0 z
    154 `" {( d3 h% j! X# [6 `. O) k* p
    16* t! J* V; J+ {5 ]
    17
    # @" u6 a9 U* ?18, C" Z% L- `  r& b
    19
    + `6 m8 |3 h# G3 H( S$ D( h20. [( j0 W% A" A5 g; B" [& z. Z
    21* P# ?! f3 l/ _9 I7 e" j4 k( Z
    22
    " j1 x) i! u% i234 m' n+ _9 J3 p7 |
    24
    2 P% _0 n: {9 [9 r) V25$ I) z7 u8 \0 O7 @& t
    26
    ' q1 f$ Y) E$ b9 W27
    / ?1 I( v/ E1 u28
    . L9 N$ O+ z1 V5 v! u0 V% @29
    ! O$ ]! \" @: j/ e+ h) j  N30
    ! X' G: V: V/ S& h$ f# h$ I- T- H31& N5 N. `3 O! i$ ~: h: G
    329 U  F) a: r: S9 M$ y' g7 H
    332 M- R9 y/ k8 A
    346 x) J5 o5 J. h" g/ r9 n
    35
    4 @  u/ u# Y6 }; O结果人与背景边缘仍会存在红色像素残留, u, Z- I: h$ M% ~1 E/ z
    % q% c4 W- G- S" O2 n& L: V3 U& v
    + g2 Y( Z8 T% x* d. O* k
    7 q% y) N4 S! Q# ]! A

    / {" R; _6 h5 {7 L2 C1 I4 q; t; y8 [7 H/ i' g0 ?+ s) n! R
    PIL, z* R. r( s- O+ N6 z6 K4 u& ~
    from torchvision.transforms.functional import to_tensor, to_pil_image
    $ ^- L: P! c! B  [. pfrom PIL import Image9 N" E& |/ F, R9 d/ h4 H- b
    import torch
    4 p/ e; z; V' d7 W( {; ]6 u  aimport time
    8 y: S( S, G1 X1 s$ _" L: y$ M  v4 p& }' R9 C
    : {9 ^, h0 M4 H/ x% n- w4 Y
    def mean_square_loss(a_ts, b_ts):
    + C: a, `7 Q4 D; A5 V    # print(a_ts.shape), ]- l: B& X0 c
        # print(b_ts). e% p8 C. _) p- C0 p* `; [
        sl = (a_ts - b_ts) ** 2" N: ?: ?, b) @, t% u$ K4 Z
        return sl.sum()0 |- I$ {8 X' T1 x! n- F& u2 n

    - u) w% |9 ?8 Y- c$ t" f, B9 {- L3 L) C+ ]7 M, p9 F! \4 O) A
    def change_red2blue(origin_png, result_png):( E: X% |2 O$ f& o5 I
        src = Image.open(origin_png)6 u. D3 m. m7 P
        src = to_tensor(src)+ ~. e5 B, P/ E  `& C
        # print(src.shape)  # torch.Size([3, 800, 600])7 i9 C, S6 A  a/ l8 z
        # channel: (R, G, B) / 255
    / B8 t0 N0 [- g% |3 P1 `5 P' g8 c    h, w = src.shape[1], src.shape[2]
    , @, V/ Z% k. H" [( J3 N) }4 r, x# p4 f8 H( P! N& B4 v
        pha = torch.ones(h, w, 3)
    ( K3 u! c. P4 V% P& J9 C* k3 `; p- H9 ]/ R8 s% b6 B  |
        bg = torch.tensor([168,36,32]) / 255# s: C% T* `6 U" G% {$ Z
        target_bg = torch.tensor([19,122,171]) / 255) [) P/ J& o0 E! M6 f* `4 T% x
    ; G3 ]* Z6 k9 Y. x: g' ?& n1 t2 w
        # C, H, W -> H, W, C' ?, Y. u2 R' Y1 y! j5 k! P/ d
        src = src.permute(1, 2, 0)# T6 u+ Z& Q  g( d$ a
        for i in range(h):1 w0 s) `2 l7 f9 y* i1 U; {
            for j in range(w):
    5 ~& b% v: I; j2 i  J( h            if mean_square_loss(src[j], bg) < 0.025: # 0.025是阈值,超参数
    8 y: a8 e* j5 g8 s                pha[j] = torch.tensor([0.0, 0.0, 0.0])
    / P$ @. M- [' S* n4 H2 b; r/ u
    8 W* w" P% P' J" T, C# t    # H, W, C -> C, H, W
    ( Y) Z* ]# M6 B/ Q    src = src.permute(2, 0, 1)" @5 k& s1 E$ l' r1 p6 L
        pha = pha.permute(2, 0, 1)
    ( Q7 n- d6 k* o8 r    com = pha * src + (1 - pha) * target_bg.view(3, 1, 1)0 A# l7 `# N/ v2 ~3 r
        to_pil_image(com).save(result_png)
    8 S8 o+ ?# g! L9 h. }5 m8 _7 v* g: I' t1 t0 A

    ' K& r& e9 [( p$ O2 \if __name__ == '__main__':, t! O9 A5 A1 ?# ]
        origin_png = 'origin_png/person.jpg', ]+ w8 Z5 t1 @; _) Z
        result_png = 'result_png/com.png'1 E2 e5 M# m6 N! w: U7 W& g2 L
        start_time = time.time()3 C" m) H. ]% Y
        change_red2blue(origin_png, result_png)
    % l* h2 v- b: c$ j9 @    spend_time = round(time.time() - start_time, 2)
    # D1 j% Z) B; c; @' j8 g    print('生成成功,共花了 {} 秒'.format(spend_time))# K) U9 E' e6 Y* n
    1
    ( V" {. J' P: b& P2
    / o) J! i. ]- B2 Z4 w: Q: i4 N3) I! s* c* u) d2 ]( Q/ e, k& m
    4
    ' B9 v2 n9 w5 X" {* B5
    $ Q5 L& j+ @3 ]( ^1 ?4 D+ W6- m9 y1 c' {2 o5 R
    70 F' b, O; i$ Q5 J$ ?3 z
    8
    5 U% h* t0 E& Z* B9  x8 v- x; g( O
    10/ Z# Z+ j3 o4 p2 W3 f) F( _% j# F( r4 t
    11
    0 R# U" b( _% T% R; r121 T$ F& t: [& W  D4 F" e. P) e
    13
    6 z$ m2 h( n2 ]: H- x, {+ [( }/ \, s$ R14
    6 R! [6 V/ S" [7 ?% h* E15* |6 f3 v% o7 G
    164 ?$ G) D% I7 Q+ o
    17
    / P/ D) c! i1 ?# m+ d185 O6 g: y; V( j% N6 Z0 F8 _2 `* s) A# o
    19- b0 R+ ]+ _/ ~. X& U1 R6 P
    20
    % o% i% y+ ]* D, W5 `6 U21& D/ b7 u. g2 W2 o0 c
    22* u6 }7 i  P: u8 u! g+ y0 o# R
    23
    6 z3 R4 D; Y: K* y/ g9 E" Q24- d) W" h9 Q6 M% m  Z( G
    25
    5 z* h2 ]. Y* \: p2 F* U26  [0 x8 `) R. s( J
    27
    ' i1 j4 ^9 P' w% c* n28
    ; t; Q) I9 Y# ~' g! Z. v# Q29
    $ d  q/ T$ @0 X: C7 @( r6 d; F30
    6 i5 h9 y3 p( M& S6 i: A7 l31
    0 d- k: V$ }$ e& W0 X32. i) [( Q! \  M& Q
    33
    0 K& M* B' H+ E4 `$ {) m34
    * D6 `- b) ~& ^35
    4 U. p. y8 |. L0 G" U: A3 r36
    ! M6 X/ S- M# o, E/ w4 C" r6 ~37
    ' O1 M, w+ s  s% w0 ~! l+ E38; u9 B9 L4 T  G& t  j) S3 M0 P( ]
    39' D0 O0 k* Z5 ?! L- c/ e
    40
    $ ^3 U! g. R" j5 Q. ]  ~) q411 e% f2 J: y" m$ q0 E% J( e
    42
    6 `3 ^3 N  J2 z" {43; S& c7 U% b/ ]( A& e, p
    44. z0 z; F1 y9 y5 J* v( y
    45
    7 u/ |# H5 n& P8 I46* ?4 d7 \6 c( Z  R/ m  n
    该方法质量较好,但一张图片大概需要12秒。' k* ]* i8 c- B. |7 Z

    7 |# `, |$ u9 ^8 K2 p0 D4 w" m3 y* g5 B4 b" {% ~! f! z( a

    ) s8 A  M# o( c. f9 a" `+ x& D1 L方法四: Background MattingV2
    : A6 F5 h+ {8 {8 vReal-Time High-Resolution Background Matting; T  Z7 [$ |+ }- d$ M
    CVPR 2021 oral! H0 z7 W5 B4 R2 l' h( Z
    6 V" o8 R2 K* s
    论文:https://arxiv.org/abs/2012.078102 X' J- m% I' Y# x+ [; p% w& {
    代码:https://github.com/PeterL1n/BackgroundMattingV2. N& ?* y; U$ p. t& O/ c# O

    " N$ n% g% ~/ Jgithub的readme.md有inference的colab链接,可以用那个跑: K# p+ w" M" _, l, i7 g

    2 o  d) T7 _5 {7 F3 s2 H由于这篇论文是需要输入一张图片(例如有人存在的草地上)和背景图片的(如果草地啥的), 然后模型会把人抠出来。9 W; N  z7 T: N5 u( ^' B

    & C4 W! D# L6 x3 g; c# o于是这里我需要生成一个背景图片。1 R1 t$ x5 s2 W
    首先我先借助firefox的颜色拾取器(或者微信截图,或者一些在线工具,例如菜鸟工具),得到十六进制,再用在线转换工具转成rgb。
    4 `5 f7 T9 D3 P# v5 B! N
    3 \8 }: ^, _8 `然后生成一个背景图片。" B' l* N4 L# \$ R- w, ]5 @

    : Y' Z4 ^4 i/ `& g0 W4 Oimport cv2
    3 l% z; I  w3 y! ]) @import numpy as np1 a7 i6 V! o, D5 O8 a- a
    8 Q. c# j& g$ w8 R. U3 u
    $ D. s1 @" T( J
    image = cv2.imread("origin_png/person.jpg")
    3 Q( R& |7 d9 g1 k/ J% x/ Y. Norigin_rgb = (168,36,32)  # 可以用浏览器啥的控制台工具提取出背景的rgb值+ _( F1 Z& |0 @
    origin_bgr = (origin_rgb[2], origin_rgb[1], origin_rgb[0])
    8 i6 w5 M( w& Q: O( n% J  Z2 ~image[:, :] = origin_bgr1 x0 b/ H5 ~2 Z$ ~* ?7 T( b

    0 Q" v: V& a! t1 v  t& Hcv2.imwrite("mask/bg.png", image)
    5 e% _# I& W4 p9 Q, V8 b$ B- A7 }8 n1
    6 z/ P2 @. Z9 F  R2
    % G9 E) l! E) f9 O' O& D) B* E34 ^, Q9 v7 s! f
    4
    3 e5 i$ \' _7 K) Y2 M; M& n( k5
    : Q5 y" D( H: R1 T: d% m' r6: n& U2 c- f% ~/ m2 \
    7
    # |* C, ^8 O( E% o% W2 z' V8
    0 B+ R3 _$ I2 M, W: W9+ n8 H- U% x% k
    10/ l7 r. w8 A$ B( m9 g7 U1 ]2 y0 }: d

    6 O# j/ r; C) O* s需要上传人的照片和背景照片, 如果名字和路径不一样则需要修改一下代码
    - m% X7 p. x$ x% D
    ' \' U+ J# ^% gsrc = Image.open('src.png')
    1 ~( r) H: ]3 V% `" D% v/ {bgr = Image.open('bgr.png')
    ' I. w1 H8 @, _1 {7 N* X1" T' y7 |5 D$ f8 z
    2) s3 o* w1 V' ]( P+ A, S) V: h
    另外原论文是边绿底,要变蓝底,白底,红底则可以修改RGB值,举个例子,原来是这样的(绿底, RGB120, 255, 155)2 w2 h# P( w0 B

    ' d1 l* P+ a& u: x7 l# C' vcom = pha * fgr + (1 - pha) * torch.tensor([120/255, 255/255, 155/255], device='cuda').view(1, 3, 1, 1)6 F; j" Q% d  _/ f$ ]- X
    1
    ; c. ^6 O+ c( K, ^7 @: [3 X$ R, s% H. p' I( E
    那么加入我要换白底(255, 255, 255),就是
    ' N. R+ H+ x" U) C7 Y, A; h
    1 [, a2 X; n0 x/ k4 U) Fcom = pha * fgr + (1 - pha) * torch.tensor([255/255, 255/255, 255/255], device='cuda').view(1, 3, 1, 1)5 }& u$ I9 R& k! l- e" i8 ~
    1
    - f# U$ ^$ l8 e8 a' g- S- g/ A( b, k$ n3 h0 Q* b0 x% T' B4 ]
    假如像我换蓝底(19,122,171)具体深浅可以调节一下RGB,就是& H6 c1 N& [# |; U  g  e
    # _: d: g; O* `( K9 z1 Z+ U, k
    com = pha * fgr + (1 - pha) * torch.tensor([19/255, 122/255, 171/255], device='cuda').view(1, 3, 1, 1)& k1 I! P. i* r) X+ {
    1
    ! g( @3 n% }7 o" J9 V总结: 其实这种方法从 任何颜色的照片 都可以 换成任何颜色的底。只要换下RGB.
    1 k  K/ b3 m$ x! Y7 a3 W* E. k2 ~% ~- v" x2 Y* W$ D
    然后就输出图片了。可以看到效果相当好。不愧是oral。+ X0 c4 R6 c0 a* Y# c
    / H8 J, h5 I9 E; u1 A
    $ o2 E0 t0 a2 C5 ]& M- M  i
    原论文可以实现发丝级效果
    ) R# K6 [: m8 L+ [: g5 ]1 J) M7 r' T$ D

    ( y: D& {- g, Q, P  R0 I; I' W) \& l" K0 b$ [! b
    ' M; P+ Z8 H( M) T6 _3 n$ s  U

    * z( y) O6 V' a- }报错解决方案
    $ o$ j5 I& x( kcan’t divided by 4 / can’t divided by 16
    . N- b3 `0 z, Z5 r1 X由于该骨干模型可能进行4倍或16倍下采样,因此如果您的证件照不是该倍数的话,有两种选择方案。一种是padding, 填充后再送入模型,然后出结果后再用clip函数裁剪。另一种方式是resize, 给resize到规定倍数的宽和高。
    + Y  C0 m4 l. m' P2 v$ @这两种方案需要的代码都可以从这篇博文找到: python图像填充与裁剪/resize4 O* e; t% b& K2 ^
    ————————————————9 F+ U4 @$ K9 `% @8 e
    版权声明:本文为CSDN博主「Andy Dennis」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    * F8 c  J7 c6 B& l9 B2 L' ?) c原文链接:https://blog.csdn.net/weixin_43850253/article/details/1263767671 n2 W- Q# g3 s1 p, n7 ~( \6 p
    8 f7 m& a4 g. R4 V

    ; B3 A$ c7 l3 C( X1 D% K
    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-7-31 06:50 , Processed in 0.612027 second(s), 51 queries .

    回顶部