基于讯飞人脸算法(调用API进行人脸比对)

news2024/12/23 18:57:54

先看结果

必须遥遥领先


所需准备

这里我调用了:

人脸比对 API 文档 | 讯飞开放平台文档中心icon-default.png?t=N7T8https://www.xfyun.cn/doc/face/xffaceComparisonRecg/API.html#%E6%8E%A5%E5%8F%A3%E8%AF%B4%E6%98%8E

代码里所涉及的APPID、APISecret、APIKey 皆从讯飞的控制台获取,自己注册去讯飞开放平台-以语音交互为核心的人工智能开放平台申请即可。

话不多说,上代码 

代码实现 

##APPID、APISecret、APIKey一定要填写!!!##

import tkinter as tk
from tkinter import filedialog
from tkinter import Label
from tkinter import ttk
from PIL import Image, ImageTk
import json
import requests
import base64
import hmac
import hashlib
from datetime import datetime
from time import mktime
from wsgiref.handlers import format_date_time
from urllib.parse import urlencode

class AssembleHeaderException(Exception):
    def __init__(self, msg):
        self.message = msg

class Url:
    def __init__(this, host, path, schema):
        this.host = host
        this.path = path
        this.schema = schema

def sha256base64(data):
    sha256 = hashlib.sha256()
    sha256.update(data)
    digest = base64.b64encode(sha256.digest()).decode(encoding='utf-8')
    return digest

def parse_url(request_url):
    stidx = request_url.index("://")
    host = request_url[stidx + 3:]
    schema = request_url[:stidx + 3]
    edidx = host.index("/")
    if edidx <= 0:
        raise AssembleHeaderException("invalid request url:" + request_url)
    path = host[edidx:]
    host = host[:edidx]
    u = Url(host, path, schema)
    return u

def assemble_ws_auth_url(request_url, method="GET", api_key="", api_secret=""):
    u = parse_url(request_url)
    host = u.host
    path = u.path
    now = datetime.now()
    date = format_date_time(mktime(now.timetuple()))
    signature_origin = "host: {}\ndate: {}\n{} {} HTTP/1.1".format(host, date, method, path)
    signature_sha = hmac.new(api_secret.encode('utf-8'), signature_origin.encode('utf-8'),
                             digestmod=hashlib.sha256).digest()
    signature_sha = base64.b64encode(signature_sha).decode(encoding='utf-8')
    authorization_origin = "api_key=\"%s\", algorithm=\"%s\", headers=\"%s\", signature=\"%s\"" % (
        api_key, "hmac-sha256", "host date request-line", signature_sha)
    authorization = base64.b64encode(authorization_origin.encode('utf-8')).decode(encoding='utf-8')
    values = {
        "host": host,
        "date": date,
        "authorization": authorization
    }

    return request_url + "?" + urlencode(values)

def gen_body(appid, img1_path, img2_path, server_id):
    with open(img1_path, 'rb') as f:
        img1_data = f.read()
    with open(img2_path, 'rb') as f:
        img2_data = f.read()
    body = {
        "header": {
            "app_id": appid,
            "status": 3
        },
        "parameter": {
            server_id: {
                "service_kind": "face_compare",
                "face_compare_result": {
                    "encoding": "utf8",
                    "compress": "raw",
                    "format": "json"
                }
            }
        },
        "payload": {
            "input1": {
                "encoding": "jpg",
                "status": 3,
                "image": str(base64.b64encode(img1_data), 'utf-8')
            },
            "input2": {
                "encoding": "jpg",
                "status": 3,
                "image": str(base64.b64encode(img2_data), 'utf-8')
            }
        }
    }
    return json.dumps(body)

def run(appid, apikey, apisecret, img1_path, img2_path, server_id='s67c9c78c'):
    url = 'http://api.xf-yun.com/v1/private/{}'.format(server_id)
    request_url = assemble_ws_auth_url(url, "POST", apikey, apisecret)
    headers = {'content-type': "application/json", 'host': 'api.xf-yun.com', 'app_id': appid}
    response = requests.post(request_url, data=gen_body(appid, img1_path, img2_path, server_id), headers=headers)
    resp_data = json.loads(response.content.decode('utf-8'))
    result = base64.b64decode(resp_data['payload']['face_compare_result']['text']).decode()
    return result

def browse_file(entry_widget, image_label, img_num):
    file_path = filedialog.askopenfilename()
    if file_path:
        entry_widget.delete(0, tk.END)
        entry_widget.insert(0, file_path)
        load_and_display_image(file_path, image_label, img_num)

def load_and_display_image(file_path, image_label, image_num):
    try:
        image = Image.open(file_path)
        image = image.resize((200, 200))
        photo = ImageTk.PhotoImage(image)
        image_label.config(image=photo)
        image_label.image = photo
        if image_num == 1:
            global img1_data
            img1_data = image
        elif image_num == 2:
            global img2_data
            img2_data = image
    except Exception as e:
        result_label.config(text="加载图片出错,请检查文件格式")

def compare_faces():
    if 'img1_data' not in globals() or 'img2_data' not in globals():
        result_label.config(text="请选择两张图片进行比对")
        return
    
    try:
        img1_path = 'img1.jpg'
        img2_path = 'img2.jpg'
        img1_data.save(img1_path)
        img2_data.save(img2_path)

        result = run(appid='',#自行申请填写
                     apisecret='',#自行申请填写
                     apikey='',#自行申请填写
                     img1_path=img1_path,
                     img2_path=img2_path)
        score = float(json.loads(result)['score'])

        if score >= 0.67:
            result_label.config(text=f"这两张图片是同一个人,相似度:{score:.2f}")
        else:
            result_label.config(text=f"这两张图片不是同一个人,相似度:{score:.2f}")
    except Exception as e:
        result_label.config(text="比对出错,请检查图片和配置")

root = tk.Tk()
root.title("人脸比对")

# 设置样式主题
style = ttk.Style()
style.configure('TButton', font=('Helvetica', 12))
style.configure('TLabel', font=('Helvetica', 14))

frame = ttk.LabelFrame(root, text="选择图片")
frame.grid(row=0, column=0, columnspan=2, padx=10, pady=10, sticky="ew")
entry1 = tk.Entry(frame, width=50)
entry2 = tk.Entry(frame, width=50)
entry1.grid(row=0, column=0, padx=10, pady=10)
entry2.grid(row=1, column=0, padx=10, pady=10)

separator = ttk.Separator(root, orient='horizontal')
separator.grid(row=1, column=0, columnspan=2, sticky="ew")

button1 = ttk.Button(root, text="选择图片1", command=lambda: browse_file(entry1, img_label1, 1))
button2 = ttk.Button(root, text="选择图片2", command=lambda: browse_file(entry2, img_label2, 2))
button1.grid(row=2, column=0, padx=10, pady=10)
button2.grid(row=2, column=1, padx=10, pady=10)

compare_button = ttk.Button(root, text="比对图片", command=compare_faces)
compare_button.grid(row=3, column=0, columnspan=2, pady=20)

result_label = Label(root, text="", font=("Helvetica", 14))
result_label.grid(row=4, column=0, columnspan=2, padx=10, pady=10)

img_label1 = tk.Label(root)
img_label1.grid(row=5, column=0, padx=10, pady=10)
img_label2 = tk.Label(root)
img_label2.grid(row=5, column=1, padx=10, pady=10)

root.mainloop()

为了美观并优化弹窗的布局,使用了ttk.LabelFrame来创建一个带有标题的框架,用于容纳选择图片的部件。还在界面中添加了一个水平分隔符ttk.Separator,以提高界面的可读性。

官方代码里图片路径需要自行填写,改进后则使得可以从本地选择需要对比图片。

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

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

相关文章

ARM Linux DIY(十三)Qt5 移植

前言 板子带有屏幕&#xff0c;那当然要设计一下 GUI&#xff0c;对 Qt5 比较熟悉&#xff0c;那就移植它吧。 移植 Qt5 buildroot 使能 Qt5&#xff0c;这里我们只开启核心功能 gui module --> widgets module 编译 $ make ODIY_V3S/ qt5base编译报错&#xff1a;找不…

旅游门户/旅行社网站-pc+移动端+可小程序+app强大功能-适合运营周边游/国内游/出境游

很美观的一款旅游门户/旅行社网站-pc+移动端+强大功能-适合运营周边游/国内游/出境游/酒店/门票/签证/租车/攻略都有,看演示地址 可以封装APP 套餐一:源码+包安装=400 套餐二:全包服务 包服务器+域名+APP+免费认证小程序+H5+PC=1000 可做小程序+app,请提前联系卖家 主…

【C#】【源码】直接可用的远程桌面应用

【背景】 封闭环境无法拷贝外来的远程桌面软件&#xff0c;所以就直接自己用C#写一个。 【效果】 【说明】 本篇会给出完整的编程步骤&#xff0c;照着写就能拥有你自己的远程桌面应用&#xff0c;直接可以运行在局域网。 如果不想自己敲代码&#xff0c;也可以选择直接下载…

LeetCode 周赛上分之旅 #45 精妙的 O(lgn) 扫描算法与树上 DP 问题

⭐️ 本文已收录到 AndroidFamily&#xff0c;技术和职场问题&#xff0c;请关注公众号 [彭旭锐] 和 BaguTree Pro 知识星球提问。 学习数据结构与算法的关键在于掌握问题背后的算法思维框架&#xff0c;你的思考越抽象&#xff0c;它能覆盖的问题域就越广&#xff0c;理解难度…

python 二手车数据分析以及价格预测

二手车交易信息爬取、数据分析以及交易价格预测 引言一、数据爬取1.1 解析数据1.2 编写代码爬1.2.1 获取详细信息1.2.2 数据处理 二、数据分析2.1 统计分析2.2 可视化分析 三、价格预测3.1 价格趋势分析(特征分析)3.2 价格预测 引言 本文着眼于车辆信息&#xff0c;结合当下较…

6. 装饰器

UML 聚合(Aggregation)关系&#xff1a;大雁和雁群&#xff0c;上图中空心菱形箭头表示聚合关系组合(Composition)关系&#xff1a;大雁和翅膀 &#xff0c;实心菱形箭头表示组合(Composition)关系 测试代码 #include <iostream> #include <stdio.h> #include &l…

IDEA2023.2.1中创建第一个Tomcat的web项目

首先&#xff0c;创建一个普通的java项目。点击【file】-【new】-【project】 创建一个TomcatDemo项目 创建如下图 添加web部门。点击【file】-【project structure】 选择【modules】-选中项目“TomcatDemo” 点击项目名上的加号【】&#xff0c;添加【web】模块 我们就会发现…

【微信小程序】文章设置

设置基本字体样式&#xff1a;行高、首行缩进 font-size: 32rpx;line-height: 1.6em;text-indent: 2em;padding: 20rpx 0;border-bottom: 1px dashed var(--themColor); 两端对齐 text-align: justify; css文字两行或者几行显示省略号 css文字两行或者几行显示省略号_css…

FPGA project : dht11 温湿度传感器

没有硬件&#xff0c;过几天上板测试。 module dht11(input wire sys_clk ,input wire sys_rst_n ,input wire key ,inout wire dht11 ,output wire ds ,output wire …

72、Spring Data JPA 的 Specification 动态查询

Specification&#xff1a;规范、规格 ★ Specification查询 它也是Spring Data提供的查询——是对JPA本身 Criteria 动态查询 的包装。▲ 为何要有动态查询 页面上常常会让用户添加不同的查询条件&#xff0c;程序就需要根据用户输入的条件&#xff0c;动态地组合不同的查询…

外星人入侵游戏-(创新版)

&#x1f308;write in front&#x1f308; &#x1f9f8;大家好&#xff0c;我是Aileen&#x1f9f8;.希望你看完之后&#xff0c;能对你有所帮助&#xff0c;不足请指正&#xff01;共同学习交流. &#x1f194;本文由Aileen_0v0&#x1f9f8; 原创 CSDN首发&#x1f412; 如…

不同类型程序的句柄研究

先做一个winform程序&#xff1b;随便放几个控件&#xff1b; 用窗口句柄查看工具看一下&#xff1b;form和上面的每个控件都有一个句柄&#xff1b; 然后看一下记事本&#xff1b;记事本一共包含三个控件&#xff0c;各自有句柄&#xff1b; 这工具的使用是把右下角图标拖到要…

服务器迁移:无缝过渡指南

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…

基于SSM+Vue的高校实验室管理系统的设计与实现

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;采用Vue技术开发 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#x…

线程的方法(未完成)

线程的方法 1、sleep(long millis) 线程休眠&#xff1a;让执行的线程暂停一段时间&#xff0c;进入计时等待状态。 static void sleep(long millis):调用此方法后&#xff0c;当前线程放弃 CPU 资源&#xff0c;在指定的时间内&#xff0c;sleep 所在的线程不会获得可运行的机…

如何使用Java语言判断出geek是字符串参数类型,888是整数参数类型,[hello,world]是数组参数类型,2.5是双精度浮点数类型?

如何使用Java语言判断出geek是字符串参数类型&#xff0c;888是整数参数类型&#xff0c;[hello,world]是数组参数类型&#xff0c;2.5是双精度浮点数类型&#xff1f; Java是一种静态类型的编程语言&#xff0c;这意味着我们需要在编译时为变量指定具体的类型。但是&#xff…

web应用及微信小程序版本更新检测方案实践

背景&#xff1a; 随着项目体量越来越大&#xff0c;用户群体越来越多&#xff0c;用户的声音也越来越明显&#xff1b;关于应用发版之后用户无感知&#xff0c;导致用户用的是仍然还是老版本功能&#xff0c;除非用户手动刷新&#xff0c;否则体验不到最新的功能&#xff1b;这…

ICCV 2023 | MPI-Flow:从单视角构建的多平面图像中学习光流

ICCV 2023 | MPI-Flow&#xff1a;从单视角构建的多平面图像中学习光流 引言&#xff1a;主要贡献&#xff1a;Motivation&#xff1a;算法细节&#xff1a;Optical Flow Data GenerationIndependent Object MotionsDepth-Aware Inpainting 实验结果&#xff1a; 来源&#xff…

QT:使用分组框、单选按钮、普通按钮、标签、行编辑器、垂直分布、水平分布做一个小项目

widget.h #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QRadioButton> //单选按钮 #include <QGroupBox> //分组框 #include <QHBoxLayout> //水平布局 #include <QVBoxLayout> //垂直布局 #include <QPushButton>…

MFC主框架和视类PreCreateWindow()函数学习

在VC生成的单文档应用程序中&#xff0c;主框架类和视类均具有PreCreateWindow函数&#xff1b; 从名字可知&#xff0c;可在此函数中添加一些代码&#xff0c;来控制窗口显示后的效果&#xff1b; 并且它有注释说明&#xff0c; Modify the Window class or styles here by…