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

2023-09-18 01:22:40

先看结果

必须遥遥领先

基于讯飞人脸算法视频演示


所需准备

这里我调用了:

人脸比对 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,以提高界面的可读性。

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

更多推荐

Qt 面试突击

1.在Qt中,多线程环境下,信号槽分别在什么样的线程中执行,如何控制?(1)信号槽的执行线程如果信号和槽都在同一个线程,就它们就在这个线程中执行如果信号和槽不在同一个线程:Qt::DirectConnection:信号槽会在信号发射的线程中直接执行。(可能导致线程安全问题)Qt::QueuedConnection:信号

9月20日星期三,今日早报简报微语报早读

9月20日,星期三,早报简报微语早读分享。1、大理出台民宿管理新规:住宅用于民宿经营须经有利害关系的业主一致同意;​2、十一假期火车票已售出超1亿张;3、WIPO副总干事:知识产权等无形资产约占全球商业价值的90%;4、外媒:泽连斯基赴美参加联合国大会,系冲突爆发以来首次乘乌飞机出访;5、9月20日24时油价将上调,部

【Flink实战】Flink 商品销量统计-实战Bahir Connetor实战存储 数据到Redis6.X

🚀作者:“大数据小禅”🚀文章简介:Flink商品销量统计-实战BahirConnetor实战存储数据到Redis6.X🚀欢迎小伙伴们点赞👍、收藏⭐、留言💬目录导航Flink怎么操作RedisFlink商品销量统计-转换-分组-聚合-存储自定义的RedisSink实战Flink怎么操作RedisFlink怎么操

100G QSFP28 100km光模块最新解决方案

随着信息时代的到来,数据传输的速度和距离要求越来越高。目前,易天光通信发布了具有超低成本、可实现100G超长距离传输新方案——100GQSFP28100km光模块,该方案是在100GZR480km光模块上的全面升级。一、产品概述100GZR4100km是专为100公里光通信应用而设计的产品。易天光通信(ETU-LINK

线程池使用之自定义线程池

目录一:Java内置线程池原理剖析二:ThreadPoolExecutor参数详解三:线程池工作流程总结示意图四:自定义线程池-参数设计分析1:核心线程数(corePoolSize)2:任务队列长度(workQueue)3:最大线程数(maximumPoolSize)4:最大空闲时间(keepAliveTime)五:自

unity 使用声网(Agora)实现语音通话

第一步、先申请一个声网账号[Agora官网链接](https://console.shengwang.cn/)第二步在官网创建项目,选择无证书模式,证书模式需要tokenh和Appld才能通话第三步官网下载SDK然后导入到unity,也可以直接在unity商店里下载,Agora官网下载链接第四步运行官方Demo1、导入

提取数据和标签

提取数据和标签是指从给定的文本或数据集中提取出有用的信息和相应的标签。数据提取可以用于从结构化或非结构化的数据源中抽取所需的数据。例如,从表格中提取特定的字段值、从网页中提取关键词或从文本中提取实体或关系。标签提取是指从文本或数据中确定或推断出所需的类别或标签。这可以是一个二分类问题(如判断一封电子邮件是否为垃圾邮件)

SpringMVC常用注解

除了@PathVaribale请求方式的不同,要用在方法上,其他注解都用在参数上@RequestMapping,@ResponseBody既可以注解在类上,也可以注解到方法上。目录一.@RequestParam二.@RequestBody三.@PathVaribaleRestful风格Restful风格如何实现缓存机制

新能源汽车运行安全性能检验规程需要哪些CAN数据才符合标准

新能源汽车的前生命周期包括了整车制造、使用、转让市场及报废回收这几个主要阶段,在政策大力扶持下,国内新能源汽车的制造产业链完善,补贴培育市场取得丰硕的果实。目前来说,我国新能源汽车有着技术领先、设计先进、低成本优势,在全球范围内都具备很大的吸引力。纯电动汽车及电车技术的出现和发展,实现了国内新能源汽车弯道超车,跨越了百

Opencv之区域生长和分裂

区域生长1.基本原理区域生长法是较为基础的一种区域分割方法它的基本思想我说的通俗些,即是一开始有一个生长点(可以一个像素也可以是一个小区域),从这个生长点开始往外扩充,扩充的意思就是它会把跟自己有相似特征的像素或者区域拉到自己的队伍里,以此壮大自己的势力范围,每次扩大后的势力范围就是一个新的生长点,一直生长一直生长,直

Matlab进阶绘图第30期—冲击图

冲击图是一种特殊的堆叠柱状图。与堆叠柱状图相比,冲击图添加了相邻柱子中相同组分之间的连线,可以更加清晰地表达各组分占比情况。由于Matlab中未收录冲击图的绘制函数,因此需要大家自行解决。本文使用自制的Fbarstacked小工具进行冲击图的绘制,先来看一下成品效果:特别提示:本期内容『数据+代码』已上传资源群中,加群

热文推荐