人脸特征标注——OpenCV

news2024/11/27 18:45:37

特征标注

    • 导入必要的库
    • 创建窗口
    • 显示原始图片和标注后的图片
    • 存储用户选择的图片路径
    • 字体样式和大小
    • 定义了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_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("提示", "请先选择一张图片"): 如果未选择图像,则在弹出窗口中显示相应提示信息。

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函数,文本颜色为黑色。

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 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()

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

docker 环境部署

1.Redis部署 用docker拉取redis镜像 docker pull redis 用docker查看拉取的镜像版本号,这里查到的是 6.2.6 版本 docker inspect redis 通过wget指令下载对应版本的tar包,下载完成后解压 wget https://download.redis.io/releases/redis-6.2.6.tar.gz …

多客陪玩系统源码支持二次开发陪玩预约系统搭建,打造专业游戏陪玩平台

简述 随着电竞行业的快速发展,电竞陪玩APP正在逐渐成为用户在休闲娱乐时的首选。为了吸引用户和提高用户体验,电竞陪玩APP开发需要定制一些特色功能,并通过合适的盈利模式来获得收益。本文将为您介绍电竞陪玩APP开发需要定制的特色功能以及常…

算法05 模拟算法之二维数组相关内容详解【C++实现】

大家好,我是bigbigli,前面一节我们一节讲过一维数组的模拟了,如果还没看的话,可以👉点击此处。模拟算法还有很多内容需要讲,比如图像、日期相关的模拟算法,后续将继续更新,今天先来讲…

遗传算法求解时间窗车辆路径规划问题(附python代码)

摘要 本研究提出了一种基于遗传算法的车辆路径规划(VRP)问题求解框架,它能够有效地处理一系列复杂约束,包括软时间窗、硬时间窗、行驶距离限制、车辆最大载重量、多个配送中心的协调、特定的配送顺序,以及多种车型的选…

MyBatis-Plus 查询不到数据,但使用 SQL 可以查询到数据的问题排查

目录 前言 一、问题描述 示例代码 二、排查步骤 1. 检查数据源配置 2. 检查实体类与数据库表结构 3. 检查 Mapper 接口 4. 检查 MyBatis-Plus 配置 5. 排查查询条件 6. 检查日志输出 7. 检查数据库连接问题 8. 检查全局配置和插件 三、解决方案 前言 在开发过程中&…

【docker入门】

在软件开发过程中,环境配置是一个至关重要的步骤,它不仅影响开发效率,也直接关联到软件的最终质量。正确的环境配置可以极大地减少开发中的潜在问题,提升软件发布的流畅度和稳定性。以下是几个关键方面,以及如何优化环…

《窄门》读后感

《窄门》这本书是端午节期间在地铁和高铁上看完的,书的故事很简单,描绘的是一段爱而不得的感情。但是,这本书写的爱而不得和其他地方的爱而不得完全不是一码事,其他地方的爱而不得要么是“落花有意随流水,流水无意恋落…

EasyX 文本输出(自定义)函数报错

EasyX 文本输出(自定义)函数报错记录 原因:EasyX与字符串相关的函数,都有字符集问题 UNICODE 多字节字符集

java干货,spring声明式事务

文章目录 一、编程式事务1.1 什么是编程式事务1.2 编程式事务的优缺点 二、声明式事务2.1 什么是声明式事务2.2 声明式事务的优点2.3 Spring 事务管理器2.4 spring 声明式事务使用 一、编程式事务 1.1 什么是编程式事务 编程式事务是指通过手动编写程序来管理事务&#xff0c…

C#利用SignalR实现通信事例Demo

1.服务端安装SignalR的Nuget包 dotnet add package Microsoft.AspNet.SignalR --version 2.4.3 2.接下来,创建一个ChatHub类,它是SignalR通信的核心: using Microsoft.AspNetCore.SignalR;public class ChatHub : Hub {public static Dict…

苹果mac电脑救星CleanMyMac让我的电脑重获新生!

🎉 发现电脑的救星!CleanMyMac让我的电脑重获新生! CleanMyMac绿色免费版下载如下:记得保存哈,以防失效: https://pan.quark.cn/s/9b08114cf404 CleanMyMac X2024全新版下载如下: https://wm.makeding.…

awdawdad

作者主页: 作者主页 本篇博客专栏:C 创作时间 :2024年6月20日 最后: 十分感谢你可以耐着性子把它读完和我可以坚持写到这里,送几句话,对你,也对我: 1.一个冷知识: …

多路h265监控录放开发-(9)通过拖拽到窗口完成渲染

xcamera_widget.h class XCameraWidget :public QWidget {Q_OBJECTpublic:XCameraWidget(QWidget* p nullptr);//渲染视频void Draw();//123//清理资源,再一个窗口被覆盖后 清理之前窗口生成的资源1~XCameraWidget();//123 private:XDecodeTask* decode_ nullptr;//123XDemu…

高考填报志愿选专业,要善于发掘自身优势

每年的高考季,如何填报志愿又再成为困扰家长以及学生的难题,可能在面对大量的专业时,无论是考生还是家长都不知道应该如何选择,好的专业孩子不一定有优势,感兴趣的冷门专业又担心日后找工作难。 实际上,专业…

购买服务器,并安装宝塔

前言: 我们在开发项目时,总会遇到一个问题,就是将我们开发好的项目上传的公网中。对于中小型的项目,我们可以通过购买服务器进行项目的上线。 我们的项目一般是部署在Linux环境中。如果你不是专业的运维人员,可能对于…

『这世界上有无忧无虑的孩子,和永远焦虑的父母』

昨天,准确说是今天,凌晨两点多,被队友薅起来,严肃认真地讨论孩子的教育问题。 我们家的小神兽六岁,一年级了。从去年幼升小的阶段,我们就计划着好好培养孩子,在这一年间,给小朋友报过…

Linux下VSCode的安装和基本使用

应用场景:嵌入式开发。 基本只需要良好的编辑环境,能支持文件搜索和跳转,就挺OK的。 之所以要在Linux下安装,是因为在WIN11上安装后,搜索功能基本废了,咋弄都弄不好,又不方便重装win系统&#x…

HTTP网络协议

1.HTTP (1)概念: Hyper Text Transfer Protocol,超文本传输协议规定了浏览器和服务器之间数据传输的规则。 (2)特点 基于TCP协议:面向连接,安全基于请求-响应模型的:一次请求对应一次响应HTTP协…

2.APP测试-安卓adb抓取日志

1.打开手机的开发者模式,打开USB调试 (1)小米手机打开开发者模式: 【设置】-【我的设备】-【全部参数信息】-快速多次点击【OS版本】-进入开发者模式 (2)连接手机和电脑,手机打开USB调试 【设置…

“论软件系统建模方法”必过范文,软考高级,系统架构设计师论文

论文真题 软件系统建模(Software System Modeling)是软件开发中的重要环节,通过构建软件系统模型可以帮助系统开发人员理解系统、抽取业务过程和管理系统的复杂性,也可 以方便各类人员之间的交流。软件系统建模是在系统需求分析和系统实现之间架起的一 座桥梁,系统开发人…