绘制口罩maskTheFace数据源是300w_lp

官网下载mask the face 代码,增加代码draw_face.py
在这里插入图片描述

import argparse
import cv2
import scipy.io
from tqdm import tqdm
from utils.aux_functions_2 import *

# 设置命令行输入参数
parser = argparse.ArgumentParser(
    description="MaskTheFace - Python code to mask faces dataset"
)

# 图像路径参数,可以是文件夹或单个图像
parser.add_argument(
    "--path",
    type=str,
    default="D:\MaskTheFace-master\\test",
    help="Path to either the folder containing images or the image itself",
)

# 口罩类型参数
parser.add_argument(
    "--mask_type",
    type=str,
    default="surgical_blue",
    choices=["surgical", "N95", "KN95", "cloth", "gas", "inpaint", "random", "all"],
    help="Type of the mask to be applied. Available options: all, surgical, N95, cloth",
)

# 口罩图案参数
parser.add_argument(
    "--pattern",
    type=str,
    default="",
    help="Type of the pattern. Available options in masks/textures",
)

# 图案权重参数
parser.add_argument(
    "--pattern_weight",
    type=float,
    default=0.5,
    help="Weight of the pattern. Must be between 0 and 1",
)

# 口罩颜色参数
parser.add_argument(
    "--color",
    type=str,
    default="#0473e2",
    help="Hex color value that need to be overlayed to the mask",
)

# 颜色权重参数
parser.add_argument(
    "--color_weight",
    type=float,
    default=0.5,
    help="Weight of the color intensity. Must be between 0 and 1",
)

# 生成特定格式的口罩代码参数
parser.add_argument(
    "--code",
    type=str,
    default="",
    help="Generate specific formats",
)

# 是否开启详细模式参数
parser.add_argument(
    "--verbose", dest="verbose", action="store_true", help="Turn verbosity on"
)

# 是否保存原始图像参数
parser.add_argument(
    "--write_original_image",
    dest="write_original_image",
    action="store_true",
    help="If true, original image is also stored in the masked folder",
)

# 设置默认参数
parser.set_defaults(feature=False)

# 解析参数
args = parser.parse_args()
args.write_path = args.path + "_masked2"

# 检查路径是文件夹、文件还是其他
is_directory, is_file, is_other = check_path(args.path)

def process_image(image_path, args, write_path):
    if image_path.__contains__("_pts.mat"):
        return
    # 获取对应的 .mat 文件路径
    mat_path = os.path.splitext(image_path)[0] + '_pts.mat'
    if not os.path.exists(mat_path):
        print(f"MAT file for {image_path} not found.")
        return

    if is_image(image_path):
        print("image_path:"+image_path)
        # 如果是图像文件,处理图像
        if args.verbose:
            str_p = "Processing: " + image_path
            tqdm.write(str_p)

        # 加载 MATLAB 文件
        mat = scipy.io.loadmat(mat_path)
        # 获取关键点
        landmarks = mat['pts_2d']

        masked_image, mask, mask_binary_array, original_image = mask_image(
            image_path, args, landmarks
        )
        for i in range(len(mask)):
            split_path = os.path.splitext(image_path)
            w_path = os.path.join(write_path, os.path.basename(split_path[0]) + split_path[1])
            img = masked_image[i]
            cv2.imwrite(w_path, img)
            if args.write_original_image:
                w_path_original = os.path.join(write_path, "original_" + os.path.basename(image_path))
                cv2.imwrite(w_path_original, original_image)

if is_directory:
    # 如果是文件夹,获取其中的文件和子文件夹
    path, dirs, files = next(os.walk(args.path))
    file_count = len(files)
    dirs_count = len(dirs)
    if len(files) > 0:
        print_orderly("Masking image files", 60)

    # 处理文件夹中的每个文件
    for f in tqdm(files):
        image_path = os.path.join(path, f)
        write_path = args.write_path
        if not os.path.isdir(write_path):
            os.makedirs(write_path)

        process_image(image_path, args, write_path)

    print_orderly("Masking image directories", 60)

    # 处理文件夹中的每个子文件夹
    for d in tqdm(dirs):
        dir_path = os.path.join(args.path, d)
        dir_write_path = os.path.join(args.write_path, d)
        if not os.path.isdir(dir_write_path):
            os.makedirs(dir_write_path)
        _, _, files = next(os.walk(dir_path))

        # 处理子文件夹中的每个文件
        for f in files:
            image_path = os.path.join(dir_path, f)
            process_image(image_path, args, dir_write_path)

elif is_file:
    print("Masking image file")
    image_path = args.path
    write_path = args.write_path
    if not os.path.isdir(write_path):
        os.makedirs(write_path)
    process_image(image_path, args, write_path)
else:
    print("Path is neither a valid file or a valid directory")

print("Processing Done")

aux_functions_2.py
计算鼻中线:

从鼻子桥的起点到鼻尖,确定鼻子的垂直方向。
计算嘴唇底线:

获取嘴唇底部的左右嘴角中点,计算它们之间的中线。
计算垂直线:

从鼻子桥的起点垂直于眼睛中线,确定面部的垂直对称线。
获取下巴上的点:

使用鼻中线和嘴唇底线在下巴上找到相交点。
这些点用于确定口罩在面部的下部位置。
根据这些线和点确定口罩的六个关键点:

这些点分别是:面部的上部、中部、下部和两侧的位置。
使用这些点来变形和调整口罩的形状。
代码逻辑说明
get_line函数:

输入:面部关键点(face_landmark),图像(image),类型(type)。
输出:眼睛中线,垂直线,左右点,中点。
get_points_on_chin函数:

输入:线(line),面部关键点(face_landmark)。
输出:在下巴上与输入线相交的点。
get_six_points函数:

输入:面部关键点(face_landmark),图像(image)。
输出:面部的六个关键点,角度(angle)。
mask_face函数:

输入:图像(image),六个关键点(six_points),角度(angle),参数(args),类型(type)。
输出:带有口罩的图像,口罩的二值掩码。
通过以上步骤和角度的计算,可以在面部图像上精确地绘制口罩,使其与面部特征完美贴合。

import bz2
import random
import shutil
from configparser import ConfigParser

import cv2
import math
import os
import requests
from PIL import Image, ImageDraw
from imutils import face_utils

from utils.create_mask import texture_the_mask, color_the_mask
from utils.fit_ellipse import *
from utils.read_cfg import read_cfg


def get_line(face_landmark, image, type="eye", debug=False):
    pil_image = Image.fromarray(image)
    d = ImageDraw.Draw(pil_image)
    left_eye = face_landmark["left_eye"]
    right_eye = face_landmark["right_eye"]
    left_eye_mid = np.mean(np.array(left_eye), axis=0)
    right_eye_mid = np.mean(np.array(right_eye), axis=0)
    eye_line_mid = (left_eye_mid + right_eye_mid) / 2

    if type == "eye":
        left_point = left_eye_mid
        right_point = right_eye_mid
        mid_point = eye_line_mid

    elif type == "nose_mid":
        nose_length = (
                face_landmark["nose_bridge"][-1][1] - face_landmark["nose_bridge"][0][1]
        )
        left_point = [left_eye_mid[0], left_eye_mid[1] + nose_length / 2]
        right_point = [right_eye_mid[0], right_eye_mid[1] + nose_length / 2]
        # mid_point = (
        #     face_landmark["nose_bridge"][-1][1] + face_landmark["nose_bridge"][0][1]
        # ) / 2

        mid_pointY = (
                             face_landmark["nose_bridge"][-1][1] + face_landmark["nose_bridge"][0][1]
                     ) / 2
        mid_pointX = (
                             face_landmark["nose_bridge"][-1][0] + face_landmark["nose_bridge"][0][0]
                     ) / 2
        mid_point = (mid_pointX, mid_pointY)

    elif type == "nose_tip":
        nose_length = (
                face_landmark["nose_bridge"][-1][1] - face_landmark["nose_bridge"][0][1]
        )
        left_point = [left_eye_mid[0], left_eye_mid[1] + nose_length]
        right_point = [right_eye_mid[0], right_eye_mid[1] + nose_length]
        mid_point = (
                            face_landmark["nose_bridge"][-1][1] + face_landmark["nose_bridge"][0][1]
                    ) / 2

    elif type == "bottom_lip":
        bottom_lip = face_landmark["bottom_lip"]
        bottom_lip_mid = np.max(np.array(bottom_lip), axis=0)
        shiftY = bottom_lip_mid[1] - eye_line_mid[1]
        left_point = [left_eye_mid[0], left_eye_mid[1] + shiftY]
        right_point = [right_eye_mid[0], right_eye_mid[1] + shiftY]
        mid_point = bottom_lip_mid

    elif type == "perp_line":
        bottom_lip = face_landmark["bottom_lip"]
        bottom_lip_mid = np.mean(np.array(bottom_lip), axis=0)

        left_point = eye_line_mid
        left_point = face_landmark["nose_bridge"][0]
        right_point = bottom_lip_mid

        mid_point = bottom_lip_mid

    elif type == "nose_long":
        nose_bridge = face_landmark["nose_bridge"]
        left_point = [nose_bridge[0][0], nose_bridge[0][1]]
        right_point = [nose_bridge[-1][0], nose_bridge[-1][1]]

        mid_point = left_point

    # d.line(eye_mid, width=5, fill='red')
    y = [left_point[1], right_point[1]]
    x = [left_point[0], right_point[0]]
    # cv2.imshow('h', image)
    # cv2.waitKey(0)
    eye_line = fit_line(x, y, image)
    d.line(eye_line, width=5, fill="blue")

    # Perpendicular Line
    # (midX, midY) and (midX - y2 + y1, midY + x2 - x1)
    y = [
        (left_point[1] + right_point[1]) / 2,
        (left_point[1] + right_point[1]) / 2 + right_point[0] - left_point[0],
    ]
    x = [
        (left_point[0] + right_point[0]) / 2,
        (left_point[0] + right_point[0]) / 2 - right_point[1] + left_point[1],
    ]
    perp_line = fit_line(x, y, image)
    if debug:
        d.line(perp_line, width=5, fill="red")
        pil_image.show()
    return eye_line, perp_line, left_point, right_point, mid_point


def get_points_on_chin(line, face_landmark, chin_type="chin"):
    chin = face_landmark[chin_type]
    points_on_chin = []
    for i in range(len(chin) - 1):
        chin_first_point = [chin[i][0], chin[i][1]]
        chin_second_point = [chin[i + 1][0], chin[i + 1][1]]

        flag, x, y = line_intersection(line, (chin_first_point, chin_second_point))
        if flag:
            points_on_chin.append((x, y))

    return points_on_chin


def plot_lines(face_line, image, debug=False):
    pil_image = Image.fromarray(image)
    if debug:
        d = ImageDraw.Draw(pil_image)
        d.line(face_line, width=4, fill="white")
        pil_image.show()


def line_intersection(line1, line2):
    # mid = int(len(line1) / 2)
    start = 0
    end = -1
    line1 = ([line1[start][0], line1[start][1]], [line1[end][0], line1[end][1]])

    xdiff = (line1[0][0] - line1[1][0], line2[0][0] - line2[1][0])
    ydiff = (line1[0][1] - line1[1][1], line2[0][1] - line2[1][1])
    x = []
    y = []
    flag = False

    def det(a, b):
        return a[0] * b[1] - a[1] * b[0]

    div = det(xdiff, ydiff)
    if div == 0:
        return flag, x, y

    d = (det(*line1), det(*line2))
    x = det(d, xdiff) / div
    y = det(d, ydiff) / div

    segment_minX = min(line2[0][0], line2[1][0])
    segment_maxX = max(line2[0][0], line2[1][0])

    segment_minY = min(line2[0][1], line2[1][1])
    segment_maxY = max(line2[0][1], line2[1][1])

    if (
            segment_maxX + 1 >= x >= segment_minX - 1
            and segment_maxY + 1 >= y >= segment_minY - 1
    ):
        flag = True

    return flag, x, y


def fit_line(x, y, image):
    if x[0] == x[1]:
        x[0] += 0.1
    coefficients = np.polyfit(x, y, 1)
    polynomial = np.poly1d(coefficients)
    x_axis = np.linspace(0, image.shape[1], 50)
    y_axis = polynomial(x_axis)
    eye_line = []
    for i in range(len(x_axis)):
        eye_line.append((x_axis[i], y_axis[i]))

    return eye_line


def get_six_points(face_landmark, image):
    _, perp_line1, _, _, m = get_line(face_landmark, image, type="nose_mid")
    face_b = m

    perp_line, _, _, _, _ = get_line(face_landmark, image, type="perp_line")
    points1 = get_points_on_chin(perp_line1, face_landmark)
    points = get_points_on_chin(perp_line, face_landmark)
    if not points1:
        face_e = tuple(np.asarray(points[0]))
    elif not points:
        face_e = tuple(np.asarray(points1[0]))
    else:
        face_e = tuple((np.asarray(points[0]) + np.asarray(points1[0])) / 2)
    nose_mid_line, _, _, _, _ = get_line(face_landmark, image, type="nose_long")

    angle = get_angle(perp_line, nose_mid_line)
    # print("angle: ", angle)
    nose_mid_line, _, _, _, _ = get_line(face_landmark, image, type="nose_tip")
    points = get_points_on_chin(nose_mid_line, face_landmark)
    if len(points) < 2:
        face_landmark = get_face_ellipse(face_landmark)
        points = get_points_on_chin(
            nose_mid_line, face_landmark, chin_type="chin_extrapolated"
        )
        if len(points) < 2:
            points = []
            points.append(face_landmark["chin"][0])
            points.append(face_landmark["chin"][-1])
    face_a = points[0]
    face_c = points[-1]

    nose_mid_line, _, _, _, _ = get_line(face_landmark, image, type="bottom_lip")
    points = get_points_on_chin(nose_mid_line, face_landmark)
    face_d = points[0]
    face_f = points[-1]

    six_points = np.float32([face_a, face_b, face_c, face_f, face_e, face_d])

    return six_points, angle


def get_angle(line1, line2):
    delta_y = line1[-1][1] - line1[0][1]
    delta_x = line1[-1][0] - line1[0][0]
    perp_angle = math.degrees(math.atan2(delta_y, delta_x))
    if delta_x < 0:
        perp_angle = perp_angle + 180
    if perp_angle < 0:
        perp_angle += 360
    if perp_angle > 180:
        perp_angle -= 180

    delta_y = line2[-1][1] - line2[0][1]
    delta_x = line2[-1][0] - line2[0][0]
    nose_angle = math.degrees(math.atan2(delta_y, delta_x))

    if delta_x < 0:
        nose_angle = nose_angle + 180
    if nose_angle < 0:
        nose_angle += 360
    if nose_angle > 180:
        nose_angle -= 180

    angle = nose_angle - perp_angle

    return angle


def mask_face(image, six_points, angle, args, type="surgical"):
    debug = False

    # Find the face angle
    threshold = 13
    if angle < -threshold:
        type += "_right"
    elif angle > threshold:
        type += "_left"

    w = image.shape[0]
    h = image.shape[1]
    if not "empty" in type and not "inpaint" in type:
        cfg = read_cfg(config_filename="masks/masks.cfg", mask_type=type, verbose=False)
    else:
        if "left" in type:
            str = "surgical_blue_left"
        elif "right" in type:
            str = "surgical_blue_right"
        else:
            str = "surgical_blue"
        cfg = read_cfg(config_filename="masks/masks.cfg", mask_type=str, verbose=False)
    img = cv2.imread(cfg.template, cv2.IMREAD_UNCHANGED)

    # Process the mask if necessary
    if args.pattern:
        # Apply pattern to mask
        img = texture_the_mask(img, args.pattern, args.pattern_weight)

    if args.color:
        # Apply color to mask
        img = color_the_mask(img, args.color, args.color_weight)

    mask_line = np.float32(
        [cfg.mask_a, cfg.mask_b, cfg.mask_c, cfg.mask_f, cfg.mask_e, cfg.mask_d]
    )
    # Warp the mask
    M, mask = cv2.findHomography(mask_line, six_points)
    dst_mask = cv2.warpPerspective(img, M, (h, w))
    dst_mask_points = cv2.perspectiveTransform(mask_line.reshape(-1, 1, 2), M)
    mask = dst_mask[:, :, 3]

    image_face = image

    # Adjust Brightness
    mask_brightness = get_avg_brightness(img)
    img_brightness = get_avg_brightness(image_face)
    delta_b = 1 + (img_brightness - mask_brightness) / 255
    dst_mask = change_brightness(dst_mask, delta_b)

    # Adjust Saturation
    mask_saturation = get_avg_saturation(img)
    img_saturation = get_avg_saturation(image_face)
    delta_s = 1 - (img_saturation - mask_saturation) / 255
    dst_mask = change_saturation(dst_mask, delta_s)

    # Apply mask
    mask_inv = cv2.bitwise_not(mask)
    img_bg = cv2.bitwise_and(image, image, mask=mask_inv)
    img_fg = cv2.bitwise_and(dst_mask, dst_mask, mask=mask)
    out_img = cv2.add(img_bg, img_fg[:, :, 0:3])
    if "empty" in type or "inpaint" in type:
        out_img = img_bg
    # Plot key points

    if "inpaint" in type:
        out_img = cv2.inpaint(out_img, mask, 3, cv2.INPAINT_TELEA)

    if debug:
        for i in six_points:
            cv2.circle(out_img, (i[0], i[1]), radius=4, color=(0, 0, 255), thickness=-1)

        for i in dst_mask_points:
            cv2.circle(
                out_img, (i[0][0], i[0][1]), radius=4, color=(0, 255, 0), thickness=-1
            )

    return out_img, mask


def draw_landmarks(face_landmarks, image):
    pil_image = Image.fromarray(image)
    d = ImageDraw.Draw(pil_image)
    for facial_feature in face_landmarks.keys():
        d.line(face_landmarks[facial_feature], width=5, fill="white")
    pil_image.show()


def get_face_ellipse(face_landmark):
    chin = face_landmark["chin"]
    x = []
    y = []
    for point in chin:
        x.append(point[0])
        y.append(point[1])

    x = np.asarray(x)
    y = np.asarray(y)

    a = fitEllipse(x, y)
    center = ellipse_center(a)
    phi = ellipse_angle_of_rotation(a)
    axes = ellipse_axis_length(a)
    a, b = axes

    arc = 2.2
    R = np.arange(0, arc * np.pi, 0.2)
    xx = center[0] + a * np.cos(R) * np.cos(phi) - b * np.sin(R) * np.sin(phi)
    yy = center[1] + a * np.cos(R) * np.sin(phi) + b * np.sin(R) * np.cos(phi)
    chin_extrapolated = []
    for i in range(len(R)):
        chin_extrapolated.append((xx[i], yy[i]))
    face_landmark["chin_extrapolated"] = chin_extrapolated
    return face_landmark


def get_avg_brightness(img):
    img_hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
    h, s, v = cv2.split(img_hsv)
    return np.mean(v)


def get_avg_saturation(img):
    img_hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
    h, s, v = cv2.split(img_hsv)
    return np.mean(v)


def change_brightness(img, value=1.0):
    img_hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
    h, s, v = cv2.split(img_hsv)
    v = value * v
    v[v > 255] = 255
    v = np.asarray(v, dtype=np.uint8)
    final_hsv = cv2.merge((h, s, v))
    img = cv2.cvtColor(final_hsv, cv2.COLOR_HSV2BGR)
    return img


def change_saturation(img, value=1.0):
    img_hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
    h, s, v = cv2.split(img_hsv)
    s = value * s
    s[s > 255] = 255
    s = np.asarray(s, dtype=np.uint8)
    final_hsv = cv2.merge((h, s, v))
    img = cv2.cvtColor(final_hsv, cv2.COLOR_HSV2BGR)
    return img


def check_path(path):
    is_directory = False
    is_file = False
    is_other = False
    if os.path.isdir(path):
        is_directory = True
    elif os.path.isfile(path):
        is_file = True
    else:
        is_other = True

    return is_directory, is_file, is_other


def shape_to_landmarks(shape):
    face_landmarks = {}
    face_landmarks["left_eyebrow"] = [
        tuple(shape[17]),
        tuple(shape[18]),
        tuple(shape[19]),
        tuple(shape[20]),
        tuple(shape[21]),
    ]
    face_landmarks["right_eyebrow"] = [
        tuple(shape[22]),
        tuple(shape[23]),
        tuple(shape[24]),
        tuple(shape[25]),
        tuple(shape[26]),
    ]
    face_landmarks["nose_bridge"] = [
        tuple(shape[27]),
        tuple(shape[28]),
        tuple(shape[29]),
        tuple(shape[30]),
    ]
    face_landmarks["nose_tip"] = [
        tuple(shape[31]),
        tuple(shape[32]),
        tuple(shape[33]),
        tuple(shape[34]),
        tuple(shape[35]),
    ]
    face_landmarks["left_eye"] = [
        tuple(shape[36]),
        tuple(shape[37]),
        tuple(shape[38]),
        tuple(shape[39]),
        tuple(shape[40]),
        tuple(shape[41]),
    ]
    face_landmarks["right_eye"] = [
        tuple(shape[42]),
        tuple(shape[43]),
        tuple(shape[44]),
        tuple(shape[45]),
        tuple(shape[46]),
        tuple(shape[47]),
    ]
    face_landmarks["top_lip"] = [
        tuple(shape[48]),
        tuple(shape[49]),
        tuple(shape[50]),
        tuple(shape[51]),
        tuple(shape[52]),
        tuple(shape[53]),
        tuple(shape[54]),
        tuple(shape[60]),
        tuple(shape[61]),
        tuple(shape[62]),
        tuple(shape[63]),
        tuple(shape[64]),
    ]

    face_landmarks["bottom_lip"] = [
        tuple(shape[54]),
        tuple(shape[55]),
        tuple(shape[56]),
        tuple(shape[57]),
        tuple(shape[58]),
        tuple(shape[59]),
        tuple(shape[48]),
        tuple(shape[64]),
        tuple(shape[65]),
        tuple(shape[66]),
        tuple(shape[67]),
        tuple(shape[60]),
    ]

    face_landmarks["chin"] = [
        tuple(shape[0]),
        tuple(shape[1]),
        tuple(shape[2]),
        tuple(shape[3]),
        tuple(shape[4]),
        tuple(shape[5]),
        tuple(shape[6]),
        tuple(shape[7]),
        tuple(shape[8]),
        tuple(shape[9]),
        tuple(shape[10]),
        tuple(shape[11]),
        tuple(shape[12]),
        tuple(shape[13]),
        tuple(shape[14]),
        tuple(shape[15]),
        tuple(shape[16]),
    ]
    return face_landmarks


def mask_image(image_path, args, shape):
    # Read the image
    image = cv2.imread(image_path)
    original_image = image.copy()
    gray = image
    # face_locations = args.detector(gray, 1)
    mask_type = args.mask_type
    if args.code:
        ind = random.randint(0, len(args.code_count) - 1)
        mask_dict = args.mask_dict_of_dict[ind]
        mask_type = mask_dict["type"]
        args.color = mask_dict["color"]
        args.pattern = mask_dict["texture"]
        args.code_count[ind] += 1

    elif mask_type == "random":
        available_mask_types = get_available_mask_types()
        mask_type = random.choice(available_mask_types)

    # Process each face in the image
    masked_images = []
    mask_binary_array = []
    # mask = []
    # for (i, face_location) in enumerate(face_locations):
    face_landmarks = shape_to_landmarks(shape)
    six_points_on_face, angle = get_six_points(face_landmarks, image)
    mask = []
    if mask_type != "all":
        if len(masked_images) > 0:
            image = masked_images.pop(0)
        image, mask_binary = mask_face(
            image, six_points_on_face, angle, args, type=mask_type
        )

        # compress to face tight
        masked_images.append(image)
        mask_binary_array.append(mask_binary)
        mask.append(mask_type)
    else:
        available_mask_types = get_available_mask_types()
        for m in range(len(available_mask_types)):
            if len(masked_images) == len(available_mask_types):
                image = masked_images.pop(m)
            img, mask_binary = mask_face(
                image,
                six_points_on_face,
                angle,
                args,
                type=available_mask_types[m],
            )
            masked_images.insert(m, img)
            mask_binary_array.insert(m, mask_binary)
        mask = available_mask_types

    return masked_images, mask, mask_binary_array, original_image


def is_image(path):
    try:
        extensions = path[-4:]
        image_extensions = ["png", "PNG", "jpg", "JPG"]

        if extensions[1:] in image_extensions:
            return True
        else:
            print("Please input image file. png / jpg")
            return False
    except:
        return False


def get_available_mask_types(config_filename="masks/masks.cfg"):
    parser = ConfigParser()
    parser.optionxform = str
    parser.read(config_filename)
    available_mask_types = parser.sections()
    available_mask_types = [
        string for string in available_mask_types if "left" not in string
    ]
    available_mask_types = [
        string for string in available_mask_types if "right" not in string
    ]

    return available_mask_types


def print_orderly(str, n):
    # print("")
    hyphens = "-" * int((n - len(str)) / 2)
    str_p = hyphens + " " + str + " " + hyphens
    hyphens_bar = "-" * len(str_p)
    print(hyphens_bar)
    print(str_p)
    print(hyphens_bar)


def display_MaskTheFace():
    with open("utils/display.txt", "r") as file:
        for line in file:
            print(line, end="")

演示代码逻辑

在这里插入图片描述

import cv2
import numpy as np
from PIL import Image, ImageDraw


def plot_landmarks_and_lines(image, landmarks):
    pil_image = Image.fromarray(image)
    draw = ImageDraw.Draw(pil_image)

    # 绘制关键点
    for part, points in landmarks.items():
        for point in points:
            draw.ellipse((point[0] - 2, point[1] - 2, point[0] + 2, point[1] + 2), fill='red')

    # 绘制眼睛线条
    left_eye = np.mean(np.array(landmarks['left_eye']), axis=0)
    right_eye = np.mean(np.array(landmarks['right_eye']), axis=0)
    draw.line((tuple(left_eye), tuple(right_eye)), fill='blue', width=2)

    # 绘制鼻子中线
    nose_bridge = landmarks['nose_bridge']
    nose_length = nose_bridge[-1][1] - nose_bridge[0][1]
    left_point = [left_eye[0], left_eye[1] + nose_length / 2]
    right_point = [right_eye[0], right_eye[1] + nose_length / 2]
    draw.line((tuple(left_point), tuple(right_point)), fill='green', width=2)

    # 绘制下唇线
    bottom_lip = np.max(np.array(landmarks['bottom_lip']), axis=0)
    shiftY = bottom_lip[1] - (left_eye[1] + right_eye[1]) / 2
    left_point = [left_eye[0], left_eye[1] + shiftY]
    right_point = [right_eye[0], right_eye[1] + shiftY]
    draw.line((tuple(left_point), tuple(right_point)), fill='yellow', width=2)

    # 显示图像
    pil_image.show()


# 示例人脸关键点
landmarks = {
    'left_eye': [(30, 50), (35, 45), (40, 50), (35, 55)],
    'right_eye': [(60, 50), (65, 45), (70, 50), (65, 55)],
    'nose_bridge': [(50, 40), (50, 45), (50, 50), (50, 55)],
    'bottom_lip': [(45, 70), (50, 75), (55, 70), (50, 65)],
    'chin': [(30, 80), (35, 85), (40, 90), (45, 95), (50, 100), (55, 95), (60, 90), (65, 85), (70, 80)]
}

# 加载示例图像(请替换为实际图像路径)
image = np.ones((120, 100, 3), dtype=np.uint8) * 255

# 绘制关键点和线条
plot_landmarks_and_lines(image, landmarks)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/735813.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

用腾讯云语音合成(TTS)批量生成英语绘本的朗读音频

孩子进行英语启蒙&#xff0c;需要看很多英语绘本&#xff0c;而且要听配套的音频来练听力。但有些英语绘本是没有对应音频的&#xff0c;下面简单几步&#xff0c;就可以将任意英语绘本制作出对应的英语朗读音频。 先到电子书资源网站搜索这个绘本名称&#xff0c;如果有电子…

C++学习合集

#整理到一块&#xff0c;方便查东西&#xff0c;顺便补充一些之前没有学习到的东西# 变量 char--1字节 short--2字节 int-4字节 long--4字节 long long(int)--8字节&#xff1b;准确来说变量的大小取决于编译器&#xff0c;1字节8个二进制位&#xff0c;其中最高位为符号位…

不需要new关键字创建实例?jQuery是如何做到的

这篇文章是jQuery源码专栏的开篇文章了&#xff0c;有人会问为什么都2024年了&#xff0c; 还要研究一个已经过时的框架呢&#xff0c;其实&#xff0c;jQuery对比vue和react这种响应式框架&#xff0c;其在使用上算是过时的&#xff0c;毕竟直接操作DOM远不如操作虚拟DOM来的方…

头歌资源库(16)分苹果

一、 问题描述 二、算法思想 首先&#xff0c;我们可以初始化一个数组apple来记录每个孩子分配的苹果数量&#xff0c;将所有元素初始化为1&#xff0c;表示每个孩子至少分配到一个苹果。 然后&#xff0c;从左到右遍历评分数组ratings&#xff0c;判断当前孩子的评分与前一个…

Docker 简介【虚拟化、容器化】

Docker 简介 Docker 简介什么是虚拟化、容器化案例 为什么要虚拟化、容器化&#xff1f;- 资源利用率高- 环境标准化- 资源弹性伸缩- 差异化环境提供- 沙箱安全- 容器对比虚拟机更轻量&#xff0c;启动更快- 维护和扩展容易 虚拟化实现方式应用程序执行环境分层- 硬件层&#x…

SpringBoot-注解@ImportResource引入自定义spring的配置xml文件和配置类

1、注解ImportResource 我们知道Spring的配置文件是可以有很多个的&#xff0c;我们在web.xml中如下配置就可以引入它们&#xff1a; SprongBoot默认已经给我们配置好了Spring&#xff0c;它的内部相当于已经有一个配置文件&#xff0c;那么我们想要添加新的配置文件怎么办&am…

数据仓库和数据库有什么区别?

一、什么是数据仓库二、什么是数据库三、数据仓库和数据库有什么区别 一、什么是数据仓库 数据仓库&#xff08;Data Warehouse&#xff09;是一种专门用于存储和管理大量结构化数据的信息系统。它通过整合来自不同来源的数据&#xff0c;为企业提供统一、一致的数据视图&…

示例:推荐一个自定义的Ribbon皮肤

一、目的&#xff1a;WPF自带的Ribbon控件功能很强大&#xff0c;但使用过程中感觉显示的样式不是很好&#xff0c;或者不适合自己的项目&#xff0c;下面介绍一个基于自带Ribbon控件样式的修改&#xff0c;主要修改了些高度&#xff0c;间距&#xff0c;背景色&#xff0c;前景…

es的检索-DSL语法和Java-RestClient实现

基本语法&#xff1a; GET /索引库名/_search {"query": {"查询类型": {"查询条件"}} }RestClient的导入在RestClient操作索引库和文档有介绍 查询所有&#xff1a; # 查询所有 GET /test/_search {"query": {"match_all"…

Go 三色标记法:一种高效的垃圾回收策略

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:「stormsha的主页」…

2024年6月计算机视觉论文推荐:扩散模型、视觉语言模型、视频生成等

6月还有一周就要结束了&#xff0c;我们今天来总结2024年6月上半月发表的最重要的论文&#xff0c;重点介绍了计算机视觉领域的最新研究和进展。 Diffusion Models 1、Autoregressive Model Beats Diffusion: Llama for Scalable Image Generation LlamaGen&#xff0c;是一个…

学习VXLAN -- 报文结构、原理和配置

目录 VXLAN背景什么是VXLANVXLAN的优势VXLAN报文结构一些特定名词BDVBDIFVAPVSIVSI-InterfaceAC VXLAN的实现原理图VXLAN MAC地址表项MAC地址动态学习 VXLAN隧道VXLAN隧道工作模式L2 GatewayIP Gateway VXLAN隧道的建立与关联VXLAN隧道建立的方式VXLAN对到与VXLAN关联的方式 配…

搭建大型分布式服务(四十一)SpringBoot 整合多个kafka数据源-支持亿级消息生产者

系列文章目录 文章目录 系列文章目录前言一、本文要点二、开发环境三、原项目四、修改项目五、测试一下五、小结 前言 本插件稳定运行上百个kafka项目&#xff0c;每天处理上亿级的数据的精简小插件&#xff0c;快速上手。 <dependency><groupId>io.github.vipjo…

PD虚拟机和VMware有什么区别?PD虚拟机和VMware谁更好用?

随着电脑硬件设备的飞快发展&#xff0c;一些高端的技术已经不再遥不可及&#xff0c;比如虚拟化&#xff0c;虚拟机技术已经成为IT领域和个人用户不可或缺的工具。特别是PD虚拟机&#xff08;Parallels Desktop&#xff09;和VMware&#xff0c;作为市场上两个主流的虚拟机软件…

智能优化算法改进策略之局部搜索算子(四)--梯度搜索法

2、仿真实验 以海洋捕食者算法&#xff08;MPA&#xff09;为基本算法。考察基于梯度搜索的改进海洋捕食者算法&#xff08;命名为GBSMPA&#xff09; vs. 海洋捕食者算法&#xff08;MPA&#xff09; 在Sphere函数上的比较 在Penalized1函数上的比较 在CEC2017-1上的比较 在C…

本地离线模型搭建指南-本地运行显卡选择

搭建一个本地中文大语言模型&#xff08;LLM&#xff09;涉及多个关键步骤&#xff0c;从选择模型底座&#xff0c;到运行机器和框架&#xff0c;再到具体的架构实现和训练方式。以下是一个详细的指南&#xff0c;帮助你从零开始构建和运行一个中文大语言模型。 本地离线模型搭…

WordPress视频主题Qinmei 2.0

WordPress视频主题Qinmei 2.0&#xff0c;简单漂亮的WP视频站源码 主题功能 可以根据豆瓣ID直接获取到其他详细信息&#xff0c;省去慢慢填写的痛苦&#xff1b;播放器支持直链&#xff0c;解析&#xff0c;m3u8格式&#xff0c;同时解析可匹配正则自动更改&#xff1b;新增动…

独立看门狗窗口开门狗

独立看门狗 接线图&#xff1a;按键用于阻塞喂狗。独立看门狗&窗口开门狗接线一样。 第一步&#xff0c;是开启时钟了&#xff0c;只有这个LSI时钟开启了独立看门狗才能运行&#xff0c;所以初始化独立看门狗之前&#xff0c;LSI必须得开启&#xff0c;但是这个开启LSI的…

【机器学习300问】128、简述什么Word2Vec?

一、一句话说明Word2Vec是什么&#xff1f; Word2Vec是一种常见的词嵌入技术。Word2Vec的目标是将每个词表示为一个向量&#xff0c;使得这些向量能够反映出词语之间的相似性和关联性。 word2vec算法通过预测中心词和上下文词的共现概率来学习词向量&#xff0c;能够捕捉词语之…

WordPress软件下载主题Inpandora

Inpandora&#xff08;中文名为潘多拉&#xff09;是一款基于软件下载站定制的WordPress主题&#xff0c;帮助站长使用WordPress快速搭建一个专业的WordPress软件博客。Inpandora这款WordPress主题可以说是因软件而生&#xff0c;从UI设计到后台设置功能&#xff0c;都充分体现…