人脸特征标注——OpenCV

特征标注

导入必要的库

import tkinter as tk: 导入Tkinter库,并将其重命名为tk。
from tkinter import filedialog: 从Tkinter中导入文件对话框功能。
import cv2: 导入OpenCV库。
from PIL import Image, ImageTk: 从PIL库导入Image和ImageTk模块,用于处理图像。
from tkinter import messagebox: 从Tkinter中导入消息框功能,用于显示消息提示框。
import dlib:导入dlib库,这个库用于人脸检测和关键点标注。

python 复制代码
import tkinter as tk
from tkinter import filedialog
import cv2
from PIL import Image, ImageTk
from tkinter import messagebox
import dlib

创建窗口

创建了一个Tkinter窗口实例win,设置窗口标题为"特征标注",大小为800x650像素。

python 复制代码
win = tk.Tk()
win.title("特征标注")
win.geometry("800x650")

显示原始图片和标注后的图片

创建了两个空的标签控件image_label_originalimage_label_landmarks,用于显示原始图像和带有标注的图像。

python 复制代码
mage_label_original = tk.Label(win)
image_label_landmarks = tk.Label(win)

存储用户选择的图片路径

初始化一个变量selected_image_path,用于存储用户选择的图片路径。

python 复制代码
selected_image_path = None

字体样式和大小

定义了字体样式my_font,使用Times New Roman字体,大小为20。

python 复制代码
my_font = ("Times New Roman", 20)

定义了select_image函数

global selected_image_path: 声明selected_image_path为全局变量,以便在函数内部修改其值。

selected_image_path = filedialog.askopenfilename():

使用文件对话框让用户选择一个图像文件,并将选择的文件路径存储在selected_image_path变量中。

if selected_image_path:: 检查是否成功选择了图像文件。

img = cv2.imread(selected_image_path):

使用OpenCV的imread()函数读取选择的图像文件,并将其存储在img变量中。

img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB):

将BGR格式的图像转换为RGB格式,便于后续处理。

img_pil = Image.fromarray(img_rgb): 将RGB格式的图像数据转换为PIL图像对象。

img_pil = img_pil.resize((300, 300), Image.Resampling.LANCZOS):

调整图像大小为300x300像素,使用LANCZOS插值方法保持图像质量。

img_tk = ImageTk.PhotoImage(image=img_pil):

将PIL图像对象转换为Tkinter图像对象,用于在GUI中显示。

image_label_original.config(image=img_tk): 在原始图像标签控件上配置显示图像。

image_label_original.image = img_tk: 更新原始图像标签的图像数据,确保图像正确显示在GUI中。

python 复制代码
def select_image():
    global selected_image_path
    selected_image_path = filedialog.askopenfilename()

    if selected_image_path:
        img = cv2.imread(selected_image_path)
        img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
        img_pil = Image.fromarray(img_rgb)
        img_pil = img_pil.resize((300, 300), Image.Resampling.LANCZOS)
        img_tk = ImageTk.PhotoImage(image=img_pil)

        image_label_original.config(image=img_tk)
        image_label_original.image = img_tk

定义了annotate_landmarks()函数

if selected_image_path:: 检查是否已选择图像文件。

img = cv2.imread(selected_image_path):

使用OpenCV的imread()函数读取已选择的图像文件。

gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY): 将图像转换为灰度图像,便于人脸检测。

detector = dlib.get_frontal_face_detector(): 创建一个人脸检测器对象。

predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat"):

创建一个人脸关键点预测器对象,加载已经训练好的68个关键点模型。

faces = detector(gray, 1): 使用人脸检测器检测输入图像中的人脸,并将结果存储在faces中。

if len(faces) > 0:: 检查是否检测到了人脸。

landmarks = predictor(gray, faces[0]): 使用关键点预测器获取第一个检测到的人脸的关键点坐标。

for n in range(0, 68):: 遍历68个人脸关键点。

x = landmarks.part(n).x: 获取第n个关键点的x坐标。

y = landmarks.part(n).y: 获取第n个关键点的y坐标。

cv2.circle(img, (x, y), 1, (255, 0, 0), -1): 在图像上绘制一个圆圈表示关键点的位置。

img_rgb_landmarks = cv2.cvtColor(img, cv2.COLOR_BGR2RGB):

将图像从BGR颜色空间转换为RGB颜色空间,这是因为OpenCV读取图像时默认使用BGR颜色通道。

img_pil_landmarks = Image.fromarray(img_rgb_landmarks):

使用PIL的Image.fromarray()函数将OpenCV格式的图像转换为PIL图像对象。

img_pil_landmarks = img_pil_landmarks.resize((300, 300), Image.Resampling.LANCZOS): 调整PIL图像的大小为(300,

300),使用LANCZOS插值方法来保持图像质量。

img_tk_landmarks = ImageTk.PhotoImage(image=img_pil_landmarks):

将PIL图像转换为Tkinter GUI所需的PhotoImage对象。

image_label_landmarks.config(image=img_tk_landmarks):

在image_label_landmarks标签控件上配置显示标注后的图像。

image_label_landmarks.image = img_tk_landmarks:

更新image_label_landmarks标签控件的图像数据,确保图像正确显示在GUI中。

messagebox.showinfo("提示", "未检测到人脸"): 如果未检测到人脸,则在弹出窗口中显示相应提示信息。

messagebox.showinfo("提示", "请先选择一张图片"): 如果未选择图像,则在弹出窗口中显示相应提示信息。

python 复制代码
def annotate_landmarks():
    if selected_image_path:
        img = cv2.imread(selected_image_path)
        gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

        detector = dlib.get_frontal_face_detector()
        predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat")
        faces = detector(gray, 1)

        if len(faces) > 0:
            landmarks = predictor(gray, faces[0])
            for n in range(0, 68):
                x = landmarks.part(n).x
                y = landmarks.part(n).y
                cv2.circle(img, (x, y), 1, (255, 0, 0), -1)

            img_rgb_landmarks = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
            img_pil_landmarks = Image.fromarray(img_rgb_landmarks)
            img_pil_landmarks = img_pil_landmarks.resize((300, 300), Image.Resampling.LANCZOS)
            img_tk_landmarks = ImageTk.PhotoImage(image=img_pil_landmarks)
            image_label_landmarks.config(image=img_tk_landmarks)
            image_label_landmarks.image = img_tk_landmarks
        else:
            messagebox.showinfo("提示", "未检测到人脸")
    else:
        messagebox.showinfo("提示", "请先选择一张图片")

设置按钮

button_select = tk.Button(win, text="选择图片", font=my_font, command=select_image, fg='black')

创建一个名为button_select的按钮,显示文本为"选择图片",应用自定义字体my_font,点击按钮时执行select_image函数,文本颜色为黑色。

button_detect = tk.Button(win, text="标注人脸", font=my_font, command=annotate_landmarks, fg='black')

创建一个名为button_detect的按钮,显示文本为"标注人脸",应用自定义字体my_font,点击按钮时执行annotate_landmarks函数,文本颜色为黑色。

python 复制代码
button_select = tk.Button(win, text="选择图片", font=my_font, command=select_image, fg='black')
button_detect = tk.Button(win, text="标注人脸", font=my_font, command=annotate_landmarks, fg='black')

调整图片标签的位置

button_height = 40 : 定义一个名为button_height的变量,值为40,表示按钮的高度为40像素。

button_select.place(x=150, y=50)

:将button_select按钮放置在窗口中x坐标为150像素,y坐标为50像素的位置。

button_detect.place(x=450, y=50)

将button_detect按钮放置在窗口中x坐标为450像素,y坐标为50像素的位置。

python 复制代码
# 计算按钮的高度,并据此调整图片标签的位置
button_height = 40  # 假设按钮的高度为40像素
button_select.place(x=150, y=50)
button_detect.place(x=450, y=50)

设置图片位置

image_label_original.place(x=50, y=100)

将原始图片标签image_label_original放置在窗口中x坐标为50像素,y坐标为100像素的位置。

image_label_landmarks.place(x=420, y=100)

将人脸标记图片标签image_label_landmarks放置在窗口中x坐标为420像素,y坐标为100像素的位置。

python 复制代码
# 将图片标签放置在按钮下方
image_label_original.place(x=50, y=100)
image_label_landmarks.place(x=420, y=100)

主事件循环

win.mainloop() :进入主事件循环,显示窗口并等待用户操作。

python 复制代码
win.mainloop()

运行显示:

全部代码

python 复制代码
import tkinter as tk
from tkinter import filedialog
import cv2
from PIL import Image, ImageTk
from tkinter import messagebox
import dlib

win = tk.Tk()
win.title("特征标注")
win.geometry("800x650")

image_label_original = tk.Label(win)
image_label_landmarks = tk.Label(win)

selected_image_path = None

my_font = ("Times New Roman", 20)

def select_image():
    global selected_image_path
    selected_image_path = filedialog.askopenfilename()

    if selected_image_path:
        img = cv2.imread(selected_image_path)
        img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
        img_pil = Image.fromarray(img_rgb)
        img_pil = img_pil.resize((300, 300), Image.Resampling.LANCZOS)
        img_tk = ImageTk.PhotoImage(image=img_pil)

        image_label_original.config(image=img_tk)
        image_label_original.image = img_tk

def annotate_landmarks():
    if selected_image_path:
        img = cv2.imread(selected_image_path)
        gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

        detector = dlib.get_frontal_face_detector()
        predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat")
        faces = detector(gray, 1)

        if len(faces) > 0:
            landmarks = predictor(gray, faces[0])
            for n in range(0, 68):
                x = landmarks.part(n).x
                y = landmarks.part(n).y
                cv2.circle(img, (x, y), 1, (255, 0, 0), -1)

            img_rgb_landmarks = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
            img_pil_landmarks = Image.fromarray(img_rgb_landmarks)
            img_pil_landmarks = img_pil_landmarks.resize((300, 300), Image.Resampling.LANCZOS)
            img_tk_landmarks = ImageTk.PhotoImage(image=img_pil_landmarks)
            image_label_landmarks.config(image=img_tk_landmarks)
            image_label_landmarks.image = img_tk_landmarks
        else:
            messagebox.showinfo("提示", "未检测到人脸")
    else:
        messagebox.showinfo("提示", "请先选择一张图片")

button_select = tk.Button(win, text="选择图片", font=my_font, command=select_image, fg='black')
button_detect = tk.Button(win, text="标注人脸", font=my_font, command=annotate_landmarks, fg='black')

# 计算按钮的高度,并据此调整图片标签的位置
button_height = 40  # 假设按钮的高度为40像素
button_select.place(x=150, y=50)
button_detect.place(x=450, y=50)

# 将图片标签放置在按钮下方
image_label_original.place(x=50, y=100)
image_label_landmarks.place(x=420, y=100)

win.mainloop()
相关推荐
热爱跑步的恒川1 小时前
【论文复现】基于图卷积网络的轻量化推荐模型
网络·人工智能·开源·aigc·ai编程
API快乐传递者1 小时前
淘宝反爬虫机制的主要手段有哪些?
爬虫·python
阡之尘埃3 小时前
Python数据分析案例61——信贷风控评分卡模型(A卡)(scorecardpy 全面解析)
人工智能·python·机器学习·数据分析·智能风控·信贷风控
孙同学要努力5 小时前
全连接神经网络案例——手写数字识别
人工智能·深度学习·神经网络
Eric.Lee20215 小时前
yolo v5 开源项目
人工智能·yolo·目标检测·计算机视觉
其实吧36 小时前
基于Matlab的图像融合研究设计
人工智能·计算机视觉·matlab
丕羽6 小时前
【Pytorch】基本语法
人工智能·pytorch·python
ctrey_6 小时前
2024-11-1 学习人工智能的Day20 openCV(2)
人工智能·opencv·学习
bryant_meng6 小时前
【python】Distribution
开发语言·python·分布函数·常用分布
SongYuLong的博客6 小时前
Air780E基于LuatOS编程开发
人工智能