欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 科技 > IT业 > 人脸特征标注——OpenCV

人脸特征标注——OpenCV

2025/6/9 0:01:39 来源:https://blog.csdn.net/2301_76794217/article/details/139781780  浏览:    关键词:人脸特征标注——OpenCV

特征标注

    • 导入必要的库
    • 创建窗口
    • 显示原始图片和标注后的图片
    • 存储用户选择的图片路径
    • 字体样式和大小
    • 定义了select_image函数
    • 定义了annotate_landmarks()函数
    • 设置按钮
    • 调整图片标签的位置
    • 设置图片位置
    • 主事件循环
    • 运行显示:
    • 全部代码

导入必要的库

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库,这个库用于人脸检测和关键点标注。

import tkinter as tk
from tkinter import filedialog
import cv2
from PIL import Image, ImageTk
from tkinter import messagebox
import dlib

创建窗口

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

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

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

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

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

存储用户选择的图片路径

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

selected_image_path = None

字体样式和大小

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

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中。

def select_image():global selected_image_pathselected_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("提示", "请先选择一张图片"): 如果未选择图像,则在弹出窗口中显示相应提示信息。

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).xy = landmarks.part(n).ycv2.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_landmarkselse: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函数,文本颜色为黑色。

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像素的位置。

# 计算按钮的高度,并据此调整图片标签的位置
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像素的位置。

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

主事件循环

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

win.mainloop()

运行显示:

在这里插入图片描述

全部代码

import tkinter as tk
from tkinter import filedialog
import cv2
from PIL import Image, ImageTk
from tkinter import messagebox
import dlibwin = tk.Tk()
win.title("特征标注")
win.geometry("800x650")image_label_original = tk.Label(win)
image_label_landmarks = tk.Label(win)selected_image_path = Nonemy_font = ("Times New Roman", 20)def select_image():global selected_image_pathselected_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_tkdef 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).xy = landmarks.part(n).ycv2.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_landmarkselse: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()

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词