####引入requestments.txt:
face_recognition==1.3.0
fastapi==0.111.0
numpy==1.26.4
opencv_python==4.9.0.80
Pillow==10.3.0
Requests==2.32.1
uvicorn==0.29.0
####二张图片相似度:
# -*- coding: utf-8 -*-
import os
import uuid
from PIL import Image
import requests
from io import BytesIO
# 对图片进行统一化处理
def get_thum(image, size=(64, 64), greyscale=False):
if image is None:
raise ValueError("Cannot process None image")
image = image.resize(size, Image.ANTIALIAS)
if greyscale:
image = image.convert('L')
return image
def getpic(image_url):
random_filename = str(uuid.uuid4()) + '.jpg'
try:
response = requests.get(image_url)
if response.status_code == 200:
image_content = response.content
image_stream = BytesIO(image_content)
image = Image.open(image_stream)
save_path = random_filename
image.save(save_path)
print(f'图片已保存到:{os.path.abspath(save_path)}')
# 这里应该返回 Image 对象,而不是文件路径
# 但是由于我们稍后要关闭文件,所以返回文件路径,并在需要时重新打开
return save_path
else:
print('无法获取图片,服务器响应码:', response.status_code)
except requests.exceptions.InvalidURL as e:
print(f"Invalid URL: {e}")
except requests.exceptions.RequestException as e:
print(f"An error occurred while making the request: {e}")
# 计算图片的余弦距离(实际上计算的是余弦相似度)
def similarity_pics(image_path1, image_path2):
# 打开图像文件并获取 Image 对象
image1 = Image.open(image_path1).convert('L')
image2 = Image.open(image_path2).convert('L')
# 确保图像是相同的大小和模式(例如,都是 RGB 或都是 L(灰度))
# 这里我们假设图像已经是相同的大小,因为它们都经过了 get_thum 的处理
# 将图像转换为向量
# 注意:这里的实现方式可能需要更改,因为直接将像素值平均可能不是最佳方式
# 通常,您可能会将图像转换为特征向量,使用例如 SIFT、SURF 或其他图像特征提取方法
vectors = [list(map(int, image1.getdata())), list(map(int, image2.getdata()))]
# 计算向量的余弦相似度
a, b = vectors
a_norm = sum([x ** 2 for x in a]) ** 0.5
b_norm = sum([x ** 2 for x in b]) ** 0.5
dot_product = sum(a_i * b_i for a_i, b_i in zip(a, b))
similarity = dot_product / (a_norm * b_norm)
return similarity
这里getpic将网上的图片下载到服务器进行比对:
人脸比对代码:
import cv2
import face_recognition
def face_comparison(pic1, pic2):
"""
比较两张图片中的人脸是否相同,并返回相似度结果和欧氏距离。
参数:
pic1 (str): 第一张图片的路径。
pic2 (str): 第二张图片的路径。
返回:
dict: 包含比较结果的字典,包含code、same和re键。
"""
# 加载图片并转换为RGB格式
reference_image = face_recognition.load_image_file(pic1)
reference_image = cv2.cvtColor(reference_image, cv2.COLOR_BGR2RGB)
test_image = face_recognition.load_image_file(pic2)
test_image = cv2.cvtColor(test_image, cv2.COLOR_BGR2RGB)
# 尝试定位人脸并提取特征编码
try:
reference_face_locations = face_recognition.face_locations(reference_image)
if not reference_face_locations:
raise ValueError("No face found in the reference image.")
reference_face_encoding = face_recognition.face_encodings(reference_image)[0]
test_face_locations = face_recognition.face_locations(test_image)
if not test_face_locations:
raise ValueError("No face found in the test image.")
test_face_encoding = face_recognition.face_encodings(test_image)[0]
except IndexError as e:
raise ValueError("An error occurred while processing the images.") from e
# 比较人脸并计算欧氏距离
is_same_person = face_recognition.compare_faces([reference_face_encoding], test_face_encoding)[0]
euclidean_distance = face_recognition.face_distance([reference_face_encoding], test_face_encoding)[0]
# 返回结果字典
return {
"code": 200,
"same": str(is_same_person), # 将布尔值转换为字符串以便在JSON中传输
"re": euclidean_distance
}
# 注意:在实际应用中,您可能还想添加代码来显示或保存带有矩形框的图片。
# 但这通常不是此函数的核心职责,因此我将其省略。
FASTAPI代码:
import os
import uvicorn
from fastapi import FastAPI, Form, HTTPException
from getpic import similarity_pics, getpic
from sameface import face_comparison
app = FastAPI()
@app.get("/")
async def index():
"""
根路径,返回自定义消息。
"""
return {"message": "自定义请求"}
@app.post("/")
async def compare_topics(type: str = Form(...), pic1: str = Form(...), pic2: str = Form(...)):
"""
比较两张图片,根据类型返回相似度或人脸识别结果。
"""
try:
image1_path = getpic(pic1) # 获取图片1的路径
image2_path = getpic(pic2) # 获取图片2的路径
# 验证图片路径是否有效
if not (os.path.exists(image1_path) and os.path.exists(image2_path)):
raise HTTPException(status_code=400, detail="图片获取失败或路径无效")
# 根据类型进行比较
if type == "face":
result = face_comparison(image1_path, image2_path) # 人脸识别比较
else:
result = similarity_pics(image1_path, image2_path) # 图片相似度比较
# 删除临时图片文件(假设不再需要)
os.remove(image1_path)
os.remove(image2_path)
# 返回结果
return result
except Exception as e:
# 捕获并处理任何异常
print(f"发生错误: {e}")
raise HTTPException(status_code=500, detail="服务器内部错误")
@app.get("/about")
async def about():
"""
返回项目信息。
"""
return {
"code": 200,
"message": "人工智能识别",
"version": "v0.0.1"
}
if __name__ == "__main__":
uvicorn.run(app, host="127.0.0.1", port=8333)
#uvicorn main:app --host 127.0.0.1 --port 8333