人脸特征标注——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()
相关推荐
网易独家音乐人Mike Zhou2 小时前
【卡尔曼滤波】数据预测Prediction观测器的理论推导及应用 C语言、Python实现(Kalman Filter)
c语言·python·单片机·物联网·算法·嵌入式·iot
安静读书2 小时前
Python解析视频FPS(帧率)、分辨率信息
python·opencv·音视频
小陈phd2 小时前
OpenCV从入门到精通实战(九)——基于dlib的疲劳监测 ear计算
人工智能·opencv·计算机视觉
Guofu_Liao3 小时前
大语言模型---LoRA简介;LoRA的优势;LoRA训练步骤;总结
人工智能·语言模型·自然语言处理·矩阵·llama
小二·4 小时前
java基础面试题笔记(基础篇)
java·笔记·python
小喵要摸鱼5 小时前
Python 神经网络项目常用语法
python
一念之坤6 小时前
零基础学Python之数据结构 -- 01篇
数据结构·python
wxl7812277 小时前
如何使用本地大模型做数据分析
python·数据挖掘·数据分析·代码解释器
NoneCoder7 小时前
Python入门(12)--数据处理
开发语言·python
ZHOU_WUYI7 小时前
3.langchain中的prompt模板 (few shot examples in chat models)
人工智能·langchain·prompt