基于AI智能人脸识别,抠图-应用证件照

445 阅读2分钟

人脸识别算法opencv+haarcascade

代码地址:github.com/opencv/open…

抠图算法:modnet

效果展示:

gh_9117fff9738a_1280.jpg

微信图片_20230625100019.jpg

微信图片_20230625100024.jpg

关键代码:

`import numpy as np
import cv2
import os

def crop_face(source_image_path, output_folder_path, tag_width, tag_height):
face_detector = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml')
#images = os.listdir(input_folder_path)

image_path = os.path.join(source_image_path, image)

img = cv2.imread(source_image_path)

height, width, channels = img.shape
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
faces = face_detector.detectMultiScale(gray, scaleFactor=1.3, minNeighbors=5, minSize=(30, 30))

无法识别面部的图片

if len(faces) == 0:
print(f"No face found in {source_image_path}")
return

if len(faces) > 0:

取第一个脸部位置,这里假设一张图片只有一个脸部特征

x, y, w, h = faces[0]
expand_w = int(0.5 * w)
expand_h = int(0.8 * h)

计算扩充后的ROI区域的坐标

x1 = max(0, x - expand_w)
y1 = max(0, y - expand_h)
x2 = min(img.shape[1], x + w + expand_w)
y2 = min(img.shape[0], y + h + expand_h)

绘制扩充后的ROI区域

#cv2.rectangle(img, (x1, y1), (x2, y2), (0, 255, 0), 2)

截取扩充后的ROI区域

roi = img[y1:y2, x1:x2]

resized = cv2.resize(roi, (tag_width, tag_height), interpolation=cv2.INTER_CUBIC)
output_path = os.path.join(output_folder_path)
print(output_path)
cv2.imwrite(output_path, resized)

if name == "main":
input_folder = r"input/33.jpg"
output_folder = r"Output"

创建输出目录

if not os.path.exists(output_folder):
os.makedirs(output_folder)
crop_face(input_folder, output_folder+"33.jpg", 295, 413)
print('Done!')`

`import os
import re

import shortuuid

import handler.base as base
from face_haar.detect_face_haar import crop_face

from resize import resize_image
from utils import date_util
from modnet import onnx_test_image

from face_haar import detect_face_haar

class UploadHandler(base.BaseHandler):

def post(self, *args, **kwargs):

filePath = ""

查看上传文件的完整格式,files以字典形式返回

{'file1':

[{'filename': '新建文本文档.txt', 'body': b'61 60 -83\r\n-445 64 -259', 'content_type': 'text/plain'}],

'file2':

filesDict = self.request.files
config_path = self.get_file_path()
width = self.get_body_argument('width')
height = self.get_body_argument('height')

print('传入的width:',width)
print('传入的height:',height)

num_re = r'^\d+$';
if width and not re.match(num_re, width):
self.write_fail('width参数不正确')
elif height and not re.match(num_re, height):
self.write_fail('height参数不正确')
else:
color = self.get_body_argument('color')
self.handler_image(filesDict, width, height, color, config_path)

def handler_image(self, filesDict, width, height, color, config_path):
today = date_util.todaystr()
parent_folder = config_path['root_folder']
static_folder = config_path['static']
parent_path = os.path.join(parent_folder, static_folder, today)
if not os.path.exists(parent_path):
os.makedirs(parent_path)
filename = shortuuid.uuid()
for inputname in filesDict:

第一层循环取出最外层信息,即input标签传回的name值

用过filename键值对对应,取出对应的上传文件的真实属性

http_file = filesDict[inputname]
for fileObj in http_file:
upload_name = fileObj.filename
upload_name_suffix = upload_name.split('.')[1]
upload_name_suffix = '.' + upload_name_suffix

第二层循环取出完整的对象

取得当前路径下的 upfiles 文件夹+上fileObj.filename属性(即真实文件名)

filePath = os.path.join(parent_path, filename + upload_name_suffix)

with open(filePath, 'wb') as f:
f.write(fileObj.body)

org_img = filePath
self.resize_image(org_img, width, height, color, filename, upload_name_suffix, config_path)

def resize_image(self, org_img, width, height, color, filename, suffix, config_path):
today = date_util.todaystr()
parent_folder = config_path['root_folder']
static_folder = config_path['static']
temp_folder = config_path['temp']
parent_path = os.path.join(parent_folder, static_folder, today)

if not os.path.exists(parent_path):
os.makedirs(parent_path)
temp_path = os.path.join(parent_folder, temp_folder)
if not os.path.exists(temp_path):
os.makedirs(temp_path)

id_image = os.path.join(parent_path, filename + suffix)

crop_face(org_img, id_image, int(width), int(height))

model = onnx_test_image.Matting(model_path='./model/modnet.onnx', input_size=(512, 512))
model.predict_image(id_image, os.path.join(parent_path, filename + "_cutout.png"),color)

info = {}
if width and height:
width = int(width)
height = int(height)

target_image = os.path.join(parent_path, filename + '_finally.jpg')
resize_image.resize_image(id_image, width, height, target_image)
target_iamge_cut = os.path.join(static_folder, today, filename + '_finally.jpg')
info['targetImageCut'] = target_iamge_cut
print('target_iamge_cut===', target_iamge_cut)

最终图包含背景且切图

#原图
source_image = os.path.join(static_folder, today, filename + suffix)
source_image_not_back = os.path.join(static_folder, today, filename + "_cutout.png")
print('source_image_not_back===', source_image_not_back)
info['sourceImage'] = source_image
info['targetImageCut'] = source_image_not_back
info['sourceImageNotBack'] = source_image_not_back
info['targetWidth'] = width
info['targetHeight'] = height
source_height, source_width = resize_image.image_shape(org_img)
info['sourceWidth'] = source_width
info['sourceHeight'] = source_height
image_path = self.get_image_path()
info['imageDomain'] = image_path['image_domain']
self.write_success_data(info)`

小程序源码地址: gitee.com/get-help/ai…