438 lines
22 KiB
Python
438 lines
22 KiB
Python
'''
|
||
找到贴图图片中的人脸,并对人脸的鼻孔部分进行肉色填充,去除黑色鼻孔。
|
||
'''
|
||
|
||
import os,platform
|
||
import sys
|
||
import time
|
||
import yaml
|
||
|
||
import cv2
|
||
import dlib
|
||
import numpy as np
|
||
import mediapipe as mp
|
||
import logging
|
||
import shutil
|
||
|
||
|
||
def rotate_img_fill_bound(image, angle):
|
||
'''
|
||
仿射变换,旋转图片angle角度,缺失背景白色(0, 0, 0)填充
|
||
:param image: 需要旋转的图片;
|
||
:param angle: 旋转角度;
|
||
:return: 输出旋转后的图片。
|
||
'''
|
||
if image is None:
|
||
return None
|
||
# 获取图像的尺寸,确定中心
|
||
(h, w) = image.shape[:2]
|
||
(cX, cY) = (w // 2, h // 2)
|
||
# 获取旋转矩阵(应用角度的负数 顺时针旋转),然后抓取正弦和余弦 (即矩阵的旋转分量)
|
||
# -angle位置参数为角度参数负值表示顺时针旋转; 1.0位置参数scale是调整尺寸比例(图像缩放参数),建议0.75
|
||
M = cv2.getRotationMatrix2D((cX, cY), -angle, 1.0)
|
||
cos = np.abs(M[0, 0])
|
||
sin = np.abs(M[0, 1])
|
||
# 计算图像的新边界尺寸
|
||
nW = int((h * sin) + (w * cos))
|
||
nH = int((h * cos) + (w * sin))
|
||
# 调整旋转矩阵以考虑平移
|
||
M[0, 2] += (nW / 2) - cX
|
||
M[1, 2] += (nH / 2) - cY
|
||
# 执行实际旋转并返回图像
|
||
# borderValue 缺失背景填充色彩,此处为白色,默认是黑色,可自定义
|
||
img_result = cv2.warpAffine(image, M, (nW, nH), borderValue=(0, 0, 0))
|
||
|
||
return img_result
|
||
|
||
|
||
def get_face_hog(image):
|
||
'''
|
||
从原始图像中获取人脸位置,并记录信息,没有检测到人脸,坐标使用 [0, 0, 0, 0] 替代。
|
||
:param image: 需要识别到原始图片;
|
||
:return: 从原图抠取的人脸图片face_img,及其坐标信息[x1, y1, x2, y2]。
|
||
'''
|
||
hog_face_detector = dlib.get_frontal_face_detector() # 加载预训练的 HoG 人脸检测器
|
||
# results:存在人脸:rectangles[[(x1, y1) (x2, y2)]],不存在人脸:rectangles[]
|
||
results = hog_face_detector(image, 0) # 对图片进行人脸检测
|
||
# print('face_num:', len(results))
|
||
if results is None:
|
||
return 0, 0, 0, 0, 0
|
||
for bbox in results:
|
||
x1 = bbox.left() # 人脸左上角x坐标
|
||
y1 = bbox.top() # 人脸左上角y坐标
|
||
x2 = bbox.right() # 人脸右下角x坐标
|
||
y2 = bbox.bottom() # 人脸右下角y坐标
|
||
face_img = image[y1:y2, x1:x2]
|
||
|
||
return face_img, x1, y1, x2, y2
|
||
|
||
|
||
def is_face_detected(image):
|
||
'''
|
||
判断图片是否检测到人脸
|
||
:param image: 被判断的图片
|
||
:return: True/False
|
||
'''
|
||
face_detection = mp.solutions.face_detection.FaceDetection(min_detection_confidence=0.5) # 创建FaceDetection对象
|
||
image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
|
||
results = face_detection.process(image_rgb) # 调用process函数来检测人脸
|
||
# 判断是否检测到了人脸
|
||
if results.detections is None:
|
||
return False
|
||
else:
|
||
return True
|
||
|
||
|
||
def cv_show(name, img):
|
||
'''
|
||
展示图片
|
||
:param name: 窗口名
|
||
:param img: 展示的图片
|
||
'''
|
||
cv2.imshow(name, img)
|
||
cv2.waitKey(0)
|
||
cv2.destroyAllWindows()
|
||
|
||
|
||
def get_distance(p1, p2):
|
||
'''
|
||
计算两个像素点之间的距离
|
||
:param p1: 坐标点1
|
||
:param p2: 坐标点2
|
||
:return: p1,p2 像素之间的距离
|
||
'''
|
||
distance = np.sqrt((p1[0] - p2[0]) ** 2 + (p1[1] - p2[1]) ** 2)
|
||
distance = round(distance, 2)
|
||
return distance
|
||
|
||
|
||
def compute_distance(rect1, rect2):
|
||
'''
|
||
rect1, rect2 是鼻孔矩形列表(nose_list)的元素,元素格式:(x, y, w, h, ...)
|
||
:param rect1: (x1, y1, w1, h1, ...1)
|
||
:param rect2: (x2, y2, w2, h2, ...2)
|
||
:return: 矩形中心点之间的距离
|
||
'''
|
||
x1, y1, w1, h1 = rect1[:-1]
|
||
x2, y2, w2, h2 = rect2[:-1]
|
||
center_x1 = x1 + w1 / 2
|
||
center_y1 = y1 + h1 / 2
|
||
center_x2 = x2 + w2 / 2
|
||
center_y2 = y2 + h2 / 2
|
||
distance = get_distance((center_x1, center_y1), (center_x2, center_y2))
|
||
return distance
|
||
|
||
|
||
def filter_rectangles(rectangles):
|
||
'''
|
||
鼻孔筛选条件,限制鼻孔位置,去除非鼻孔轮廓的干扰
|
||
:param rectangles: 列表,元素格式:(x, y, w, h, ...)
|
||
:return: 新列表,元素格式:(x, y, w, h, ...)
|
||
'''
|
||
filtered_rectangles = []
|
||
for i in range(len(rectangles)):
|
||
for j in range(i+1, len(rectangles)):
|
||
rect1 = rectangles[i]
|
||
rect2 = rectangles[j]
|
||
distance = compute_distance(rect1, rect2)
|
||
max_width = max(rect1[2], rect2[2])
|
||
x1, y1, w1, h1 = rect1[:-1]
|
||
x2, y2, w2, h2 = rect2[:-1]
|
||
if max_width < distance < 3 * max_width and 4 * max(w1, w2) > abs(x1 - x2) > w1 and 3 * max(h1, h2) > abs(y1 - y2) >= 0:
|
||
filtered_rectangles.append((rect1, rect2))
|
||
else:
|
||
return None
|
||
return filtered_rectangles
|
||
|
||
|
||
def lock_nose(face_img):
|
||
'''
|
||
锁定人脸图片中的鼻孔位置:通过查找图片轮廓,筛选轮廓,找到鼻孔位置。
|
||
:param face_img: 导入人脸图片
|
||
:return:处理好的 face_img, 鼻孔的位置信息 nose_list
|
||
'''
|
||
face_h2, face_w2, _ = face_img.shape
|
||
face_gray = cv2.cvtColor(face_img, cv2.COLOR_BGR2GRAY)
|
||
retval, thresh = cv2.threshold(face_gray, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)
|
||
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
|
||
nose_list = []
|
||
for cnt in contours:
|
||
area = cv2.contourArea(cnt)
|
||
# 1.面积筛选轮廓
|
||
if 200 <= area <= 1600:
|
||
rect = cv2.boundingRect(cnt)
|
||
x, y, w, h = rect
|
||
# 2.宽高比筛选轮廓
|
||
if 0.5 < w / h < 4: # 鼻孔大致为椭圆形,所以要判断长宽比
|
||
# 3.加一个距离筛选,去除眼睛的轮廓;
|
||
face_center = (int(face_w2 / 2), int(face_h2 / 2))
|
||
cnt_point = (int(x + w / 2), int(y + h / 2))
|
||
cnt_distance = get_distance(face_center, cnt_point)
|
||
if cnt_distance < int(face_h2 / 6): # 距离筛选
|
||
# 4.颜色筛选 ———— 鼻孔中心点像素值较暗
|
||
pixel_center = face_img[int(y + h / 2), int(x + w / 2)]
|
||
nose_list.append((x, y, w, h, sum(pixel_center))) # 存储满足上述条件的鼻孔位置信息
|
||
# print('初步筛选得到的鼻孔列表nose_list:', nose_list)
|
||
if len(nose_list) == 2:
|
||
x1, y1, w1, h1 = nose_list[0][:-1]
|
||
x2, y2, w2, h2 = nose_list[1][:-1]
|
||
max_width = max(w1, w2)
|
||
distance = compute_distance(nose_list[0], nose_list[1])
|
||
if max_width < distance < 3 * max_width and 4 * max(w1, w2) > abs(x1 - x2) > w1 and 3 * max(h1, h2) > abs(
|
||
y1 - y2) >= 0:
|
||
for x, y, w, h, _ in nose_list:
|
||
if draw_nose_rectangle:
|
||
cv2.rectangle(face_img, (x, y), (x + w, y + h), (0, 255, 0), 2)
|
||
return face_img, nose_list
|
||
else:
|
||
# print('两鼻孔未满足筛选条件!')
|
||
return None
|
||
elif len(nose_list) > 2:
|
||
new_nose_list = filter_rectangles(nose_list)
|
||
# print('鼻孔数大于2,筛选后 new_nose_list:', new_nose_list)
|
||
if new_nose_list is None:
|
||
# print('鼻孔不满足筛选条件!')
|
||
logging.info('鼻孔不满足函数filter_rectangles筛选条件!')
|
||
return None
|
||
else:
|
||
for x, y, w, h, _ in new_nose_list:
|
||
if draw_nose_rectangle:
|
||
cv2.rectangle(face_img, (x, y), (x + w, y + h), (0, 255, 0), 2)
|
||
return face_img, new_nose_list
|
||
else:
|
||
# print('未检测到两个鼻孔,跳过...')
|
||
logging.info('未检测到两个鼻孔,跳过...')
|
||
for x, y, w, h, _ in nose_list:
|
||
if draw_nose_rectangle:
|
||
cv2.rectangle(face_img, (x, y), (x + w, y + h), (0, 255, 0), 2)
|
||
return None
|
||
|
||
|
||
def select_nose_contour(image, fill_pixel, iterations=0):
|
||
'''
|
||
挑选出鼻孔轮廓位置,如果鼻孔轮廓和鼻孔图片外轮廓连接到一起,需要分隔开。
|
||
:param image: 待处理的鼻孔原图
|
||
:param fill_pixel: 需要填充鼻孔的像素
|
||
:param iterations: 膨胀次数
|
||
:return: 处理完的鼻孔图片
|
||
'''
|
||
max_cnt = ""
|
||
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
|
||
retval, img_thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)
|
||
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
|
||
# 对黑色区域来说是腐蚀,对白色区域来说是膨胀,闭运算
|
||
image_erode = cv2.morphologyEx(img_thresh, cv2.MORPH_CLOSE, kernel, iterations=2)
|
||
# 选取黑色区域中面积最大的(需要除去图片整体的外轮廓) ———— 鼻孔
|
||
contours, hierarchy = cv2.findContours(image_erode, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
|
||
sum_area = []
|
||
for ccc in contours:
|
||
area1 = cv2.contourArea(ccc)
|
||
sum_area.append((ccc, area1)) # 存储轮廓数据和该轮廓面积
|
||
areas_list = sorted(sum_area, key=lambda x: x[1], reverse=True) # 降序
|
||
# 轮廓数目判断,并且轮廓面积必须达到一定面积,暂定大于图片总面积的 1/6 !
|
||
if len(areas_list) > 1:
|
||
if areas_list[1][1] > (areas_list[0][1] / 6):
|
||
max_cnt = areas_list[1][0]
|
||
else:
|
||
return None
|
||
else:
|
||
# 注意:鼻孔颜色较浅,鼻孔外围颜色较深,那么两者二值化图像黑色块融合在一起了!
|
||
# 此时,总轮廓数目为 1 ,鼻孔轮廓和外轮廓连接在一起,解决办法:将鼻孔二值图片外围一圈以3个像素为单位全部填充为白色
|
||
height, width = gray.shape
|
||
# 构造一个新的大一圈的白色矩阵,并在中心部分复制二值图片。
|
||
new_img = np.ones((height, width), dtype=np.uint8) * 255
|
||
new_img[3:-3, 3:-3] = gray[3:-3, 3:-3]
|
||
# 使用 rectangle 函数填充矩阵外围为白色
|
||
cv2.rectangle(new_img, (0, 0), (width + 5, height + 5), 255, thickness=3)
|
||
# 再重新获取鼻孔轮廓
|
||
new_contours, new_hierarchy = cv2.findContours(new_img, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
|
||
new_sum_area = []
|
||
for ccc2 in new_contours:
|
||
are1 = cv2.contourArea(ccc2)
|
||
new_sum_area.append((ccc2, are1))
|
||
new_areas_list = sorted(new_sum_area, key=lambda x: x[1], reverse=True)
|
||
if len(new_areas_list) > 1:
|
||
# print('图片外轮廓和鼻孔轮廓链接到一起,处理中...')
|
||
logging.info('图片外轮廓和鼻孔轮廓链接到一起,处理中...')
|
||
if new_areas_list[1][1] > (new_areas_list[0][1] / 6):
|
||
max_cnt = new_areas_list[1][0]
|
||
else:
|
||
return None
|
||
hull_cnt = cv2.convexHull(max_cnt)
|
||
# cv2.drawContours(image, [max_cnt], -1, (0, 255, 0), 1) # 展示
|
||
# cv2.polylines(image, [hull], True, (0, 0, 255), 1)
|
||
# cv2.imshow('image', image)
|
||
mask = np.zeros_like(img_thresh)
|
||
cv2.drawContours(mask, [hull_cnt], 0, 255, -1) # 使用白色(255)填充整个轮廓(-1)区域
|
||
mask_dilate = cv2.dilate(mask, kernel, iterations=iterations)
|
||
indices = np.where(mask_dilate == 255)
|
||
# 替换指定像素值
|
||
image[indices[0], indices[1]] = fill_pixel
|
||
|
||
return image
|
||
|
||
|
||
def nose_color_fill(face_img, nose_list, pid):
|
||
'''
|
||
对获取到的左右鼻孔填充像素
|
||
:param face_img: 未处理的人脸图片
|
||
:param nose_list: 人脸图片左右鼻孔位置信息
|
||
:param pid: 图片id,这里主要用于打印处理过程图片
|
||
:return: face_img:鼻孔填充颜色后的人脸图片
|
||
'''
|
||
# 1.获取填充鼻孔的像素 ———— 取左右鼻孔外界矩形中心坐标,鼻尖坐标是两者连线的中间点,以该点像素作为填充像素
|
||
pixel_nose_list = []
|
||
for x, y, w, h, _ in nose_list:
|
||
pixel_nose_list.append((int(x + w / 2), int(y + h / 2)))
|
||
fill_pixel_coor = (int((pixel_nose_list[0][0] + pixel_nose_list[1][0]) / 2),
|
||
int((pixel_nose_list[0][1] + pixel_nose_list[1][1]) / 2)) # 鼻尖点坐标(x, y)
|
||
fill_pixel = face_img[fill_pixel_coor[1], fill_pixel_coor[0]] # 鼻尖像素值
|
||
# 2.找到需要改变像素的鼻孔区域,扩大截取鼻孔矩形范围,包裹整个鼻孔
|
||
# if nose_list[0][0] < nose_list[1][0]: # x1 < x2
|
||
# 左鼻孔:nose_list[0] ====》 x1, y1, w1, h1, sum(pixel_center)1;face_img[(y1-2):(y1+h1+2), (x1-2):(x1+w1+2)]
|
||
# 右鼻孔:nose_list[1] ====》 x2, y2, w2, h2, sum(pixel_center)2;face_img[(y2-2):(y2+h2+2), (x2-2):(x2+w2+2)]
|
||
nose_list = sorted(nose_list, key=lambda z: z[0]) # 以 x 大小进行升序,x1 < x2 ,x1是左鼻孔,x2是右鼻孔
|
||
# 鼻孔尺寸调整外扩矩形框
|
||
l_add_w = int(np.ceil(nose_list[0][2] / 10)) # 向上取整
|
||
l_add_h = int(np.ceil(nose_list[0][3] / 10))
|
||
r_add_w = int(np.ceil(nose_list[1][2] / 10))
|
||
r_add_h = int(np.ceil(nose_list[1][3] / 10))
|
||
# 图片尺寸调整外扩矩形框
|
||
img_h, img_w = face_img.shape[:2]
|
||
add_img_h = int(np.ceil(img_h / 100))
|
||
add_img_w = int(np.ceil(img_w / 100))
|
||
left_nose_img = face_img[(nose_list[0][1] - l_add_h - add_img_h):(nose_list[0][1] + nose_list[0][3] + l_add_h + add_img_h),
|
||
(nose_list[0][0] - l_add_w - add_img_w):(nose_list[0][0] + nose_list[0][2] + l_add_w + add_img_w)]
|
||
right_nose_img = face_img[(nose_list[1][1] - r_add_h - add_img_h):(nose_list[1][1] + nose_list[1][3] + r_add_h + add_img_h),
|
||
(nose_list[1][0] - r_add_w - add_img_w):(nose_list[1][0] + nose_list[1][2] + r_add_w + add_img_w)]
|
||
|
||
# select_nose_contour函数里面的外边界轮廓和内边界轮廓分开
|
||
left_nose_img = select_nose_contour(left_nose_img, fill_pixel, iterations=0)
|
||
right_nose_img = select_nose_contour(right_nose_img, fill_pixel, iterations=0)
|
||
if left_nose_img is None or right_nose_img is None: # 检测到两鼻孔,但是不满足筛选条件的情况
|
||
return None
|
||
# 高斯模糊
|
||
left_nose_gauss = cv2.GaussianBlur(left_nose_img, (7, 7), 0)
|
||
right_nose_gauss = cv2.GaussianBlur(right_nose_img, (7, 7), 0)
|
||
face_img[(nose_list[0][1] - l_add_h - add_img_h):(nose_list[0][1] + nose_list[0][3] + l_add_h + add_img_h),
|
||
(nose_list[0][0] - l_add_w - add_img_w):(nose_list[0][0] + nose_list[0][2] + l_add_w + add_img_w)] = left_nose_gauss
|
||
face_img[(nose_list[1][1] - r_add_h - add_img_h):(nose_list[1][1] + nose_list[1][3] + r_add_h + add_img_h),
|
||
(nose_list[1][0] - r_add_w - add_img_w):(nose_list[1][0] + nose_list[1][2] + r_add_w + add_img_w)] = right_nose_gauss
|
||
|
||
return face_img
|
||
|
||
|
||
def main(pids):
|
||
'''
|
||
批量处理人脸图片。
|
||
:param pids: 待处理图片的id
|
||
:return:
|
||
'''
|
||
# 设置日志等级为最低(DEBUG),并保存到文件中
|
||
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(levelname)s %(message)s',
|
||
filename=os.path.join(workdir, run_logging))
|
||
for item in pids:
|
||
pid, order_id = item.split('_')
|
||
start_time = time.time()
|
||
print('正在处理图片 {} ...'.format(pid))
|
||
logging.info('正在处理图片 {} ...'.format(pid))
|
||
# 判断文件目录是否存在,不存在则创建
|
||
# if not os.path.exists(workdir + f'/{pid}/'):
|
||
# os.makedirs(workdir + f'/{pid}/')
|
||
image_path = os.path.join(workdir, f'{pid}_{order_id}', f'{pid}Tex1.jpg')
|
||
copy_save_path = os.path.join(workdir, f'{pid}_{order_id}', f'{pid}Tex1_old.jpg')
|
||
save_path = os.path.join(workdir, f'{pid}_{order_id}', f'{pid}Tex1.jpg') # 保存修改后图像
|
||
shutil.copy(image_path, copy_save_path) # 备份原图,复制操作
|
||
image = cv2.imread(image_path)
|
||
for img_angle in image_angle_list:
|
||
# save_face_path = os.path.join(workdir, save_face_prefix, f'{pid}_{img_angle}.jpg')
|
||
img_rotated = rotate_img_fill_bound(image, img_angle)
|
||
face_hog = get_face_hog(img_rotated)
|
||
if face_hog is None:
|
||
print('图片 {0} 旋转角度为{1}时,没有检测到人脸,跳过...'.format(pid, img_angle))
|
||
logging.info('图片 {0} 旋转角度为{1}时,没有检测到人脸,跳过...'.format(pid, img_angle))
|
||
else:
|
||
print('图片 {0} 旋转角度为{1}时,检测到人脸,处理中...'.format(pid, img_angle))
|
||
logging.info('图片 {0} 旋转角度为{1}时,检测到人脸,处理中...'.format(pid, img_angle))
|
||
face_img, x1, y1, x2, y2 = get_face_hog(img_rotated) # 注意:这里会存在错误检测的人脸!
|
||
face_h, face_w, _ = face_img.shape
|
||
if face_h >= 300 and face_w >= 300: # 去除face_img 尺寸较小的图片
|
||
judge = is_face_detected(face_img) # mediapipe人脸识别筛除非人脸部分
|
||
if judge:
|
||
# print('mediapipe人脸识别成功!')
|
||
if lock_nose(face_img) is None:
|
||
print('鼻孔不满足筛选条件!')
|
||
continue
|
||
# print('lock_nose检测到的鼻孔满足筛选条件!')
|
||
draw_nose_face, nose_list = lock_nose(face_img)
|
||
face_img_result = nose_color_fill(face_img, nose_list, pid)
|
||
if face_img_result is None:
|
||
print('旋转角度为{1}时,两个鼻孔可以检测到,但是鼻孔颜色深浅存在问题,处理失败...')
|
||
continue
|
||
# 将处理完成的人脸图片还原到原图中去,并将角度还原为初始状态
|
||
img_rotated[y1:y2, x1:x2] = face_img_result
|
||
result_img = rotate_img_fill_bound(img_rotated, -img_angle)
|
||
# 保存图片的质量是原图的 95%
|
||
# if not os.path.exists(os.path.join(workdir, save_face_prefix)):
|
||
# os.makedirs(os.path.join(workdir, save_face_prefix))
|
||
# cv2.imwrite(save_face_path, face_img_result, [cv2.IMWRITE_JPEG_QUALITY, 95])
|
||
# print('图片 {0} 旋转角度为{1}时,人脸已保存!'.format(pid, img_angle))
|
||
# logging.info('图片 {0} 旋转角度为{1}时,人脸已保存!'.format(pid, img_angle))
|
||
print('图片 {0} 旋转角度为{1}时,鼻孔处理成功!'.format(pid, img_angle))
|
||
logging.info('图片 {0} 旋转角度为{1}时,鼻孔处理成功!'.format(pid, img_angle))
|
||
image = result_img # 将旋转后的处理结果保存为新的图片,再次进行旋转处理
|
||
continue
|
||
else:
|
||
# mediapipe算法识别为非人脸
|
||
print('图片 {0} 旋转角度为{1}时,mediapipe算法判断为非人脸,跳过...'.format(pid, img_angle))
|
||
logging.info('图片 {0} 旋转角度为{1}时,mediapipe算法判断为非人脸,跳过...'.format(pid, img_angle))
|
||
nose_error = open(os.path.join(workdir, mediapipe_judge_fail), 'a')
|
||
nose_error.write(
|
||
f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())} {pid} 人脸二级筛选失败,跳过...\n')
|
||
continue
|
||
else:
|
||
print('图片 {0} 旋转角度为{1}时,检测到人脸尺寸小于300*300,跳过...'.format(pid, img_angle))
|
||
logging.info('图片 {0} 旋转角度为{1}时,检测到人脸尺寸小于300*300,跳过...'.format(pid, img_angle))
|
||
nose_error = open(os.path.join(workdir, small_face_error), 'a')
|
||
nose_error.write(
|
||
f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())} {pid} 检测到人脸尺寸小于300*300,跳过...\n')
|
||
continue
|
||
# 保存图片的质量是原图的 95%
|
||
if not os.path.exists(os.path.join(workdir, f'{pid}_{order_id}')):
|
||
os.makedirs(os.path.join(workdir, f'{pid}_{order_id}'))
|
||
cv2.imwrite(save_path, image, [cv2.IMWRITE_JPEG_QUALITY, 95])
|
||
end_time = time.time()
|
||
solve_time = start_time - end_time
|
||
print('图片:{0} 已处理完成并保存,处理时间:{1}!'.format(pid, solve_time))
|
||
logging.info('图片:{0} 已处理完成并保存,处理时间:{1}!'.format(pid, solve_time))
|
||
|
||
|
||
if __name__ == '__main__':
|
||
with open("config/nose.yaml", 'r') as f:
|
||
Config = yaml.load(f, Loader=yaml.FullLoader)
|
||
|
||
os_type = platform.system()
|
||
|
||
workdir = Config['Nose_Config']['Select_system'][f'{os_type}_path']['workdir']
|
||
pids_txt = Config['Nose_Config']['Select_system'][f'{os_type}_path']['pids_txt']
|
||
|
||
no_detect_nose_error = Config['Nose_Config']['Select_system'][f'{os_type}_path']['no_detect_nose_error']
|
||
small_face_error = Config['Nose_Config']['Select_system'][f'{os_type}_path']['small_face_error']
|
||
mediapipe_judge_fail = Config['Nose_Config']['Select_system'][f'{os_type}_path']['mediapipe_judge_fail']
|
||
run_logging = Config['Nose_Config']['Select_system'][f'{os_type}_path']['run_logging']
|
||
|
||
image_angle_list = Config['Nose_Config']['Personal_parameter']['image_angle_list'] # 图片旋转角度0、90、180、270
|
||
draw_nose_rectangle = Config['Nose_Config']['Personal_parameter']['draw_nose_rectangle'] # 是否需要画出鼻孔的矩形框
|
||
|
||
if len(sys.argv) == 2:
|
||
if sys.argv[1] == 'all':
|
||
# with open('datasets/pids_all.txt', 'r') as f:
|
||
with open(os.path.join(workdir, pids_txt), 'r') as f:
|
||
pids = f.read().split(',')
|
||
else:
|
||
pids = sys.argv[1].split(',')
|
||
main(pids)
|
||
else:
|
||
print('用法:python nose_processing.py <pids>')
|
||
sys.exit(0)
|