File size: 3,517 Bytes
81e69dc
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97

"""
create_no_mouth.py

open_mouth.pyの一部

口のない画像を作ります。

口の部分のをlandpointを取って、その部分を消して、inpaintします。
inpaint部分をぼかして、元の画像の上にはりつけ、ぼかします。



著者: Akihito Miyazaki
作成日: 2024-04-23
更新履歴:
  - 2024-04-23: 最初のリリース

"""

import cv2
import numpy as np
from PIL import Image
import lip_utils

from glibvision.cv2_utils import blend_rgb_images
from glibvision.numpy_utils import apply_binary_mask_to_image

def process_create_no_mouth_image(img,landmarks_list):
    img_h, img_w = lip_utils.get_image_size(img)

    ## 口の範囲をInpaintで消す。
    (bottom_width,bottom_height)=lip_utils.get_bottom_lip_width_height(landmarks_list)
    lip_points = lip_utils.get_lip_mask_points(landmarks_list)
    
    # 選択範囲を丸めてみたけど、それほどメリットが感じなかった。
    #lip_points = lip_utils.bulge_polygon(lip_points,0.1)

    # 唇のマスク範囲を検証
    if lip_utils.DEBUG:
        img_lined = np.copy(img)
        cv2.polylines(img_lined, [np.array(lip_points)], isClosed=True, color=(0,255,0), thickness=1)
        cv2.imwrite("create_no_mouth_image_polyline.jpg",img_lined)
    
    # 唇のエッジ部分は、影やら、ピンクなどあるので、それを削るのに、下唇の高さを元にしている。0.5は根拠ない。
    dilation_size = int(bottom_height*0.5)
    lip_mask = lip_utils.create_mask_from_points(img,lip_points,dilation_size,0) # inpaintで使うので、ぼかしは不要
    if lip_utils.DEBUG:
        lip_utils.print_numpy(lip_mask,"lip mask")

    if lip_utils.DEBUG:
        cv2.imwrite("create_no_mouth_image_mask.jpg",lip_mask)

    img_inpainted = cv2.inpaint(img, lip_mask,3, cv2.INPAINT_TELEA)
    if lip_utils.DEBUG:
        cv2.imwrite("create_no_mouth_image_inpaint.jpg",img_inpainted)

    ## Inpaintした部分をぼかしている。
    blurred_image = cv2.GaussianBlur(img_inpainted, (29, 29), 0) #場合によっては奇数じゃないとエラーが出ることがある
    if lip_utils.DEBUG:
        cv2.imwrite("create_no_mouth_image_blurred.jpg",blurred_image)
    
    apply_binary_mask_to_image(img_inpainted,blurred_image,lip_mask)
    if lip_utils.DEBUG:
        cv2.imwrite("create_no_mouth_image_blurred1_applied.jpg",blurred_image)


    # 全体を少しぼかす
    blurred_image2 = cv2.GaussianBlur(img_inpainted, (9, 9), 0)
    if lip_utils.DEBUG:
        cv2.imwrite("create_no_mouth_image_blurred2.jpg",blurred_image2)

    # Inpaintの境界線から少し広げている
    kernel = np.ones((8, 8), np.uint8)
    lip_mask = cv2.dilate(lip_mask, kernel, iterations=1)

     # 全体を少しぼかす
    blurred_mask = cv2.GaussianBlur(lip_mask, (19, 19), 0)
    if lip_utils.DEBUG:
        cv2.imwrite("create_no_mouth_image_blurred_mask.jpg",blurred_mask)

    # https://github.com/akjava/lip_recognition_tools/issues/12
    #cv2_utils.apply_binary_mask_to_image(img_inpainted,blurred_image2,lip_mask)
    
    img_inpainted = blend_rgb_images(img_inpainted,blurred_image2,lip_mask)
    
    if lip_utils.DEBUG:
        cv2.imwrite("create_no_mouth_image_merged.jpg",img_inpainted)

    return img_inpainted

if __name__ == "__main__":
  # 画像ファイルのパス
  img_path = "straight.jpg"
  img = cv2.imread(img_path)
  landmarks_list = lip_utils.image_to_landmarks_list(img)
  process_create_no_mouth_image(img,landmarks_list)