You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
443 lines
22 KiB
443 lines
22 KiB
''' |
|
找到贴图图片中的人脸,并对人脸的鼻孔部分进行肉色填充,去除黑色鼻孔。 |
|
''' |
|
|
|
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(workdirImgPath, f'{pid}_{order_id}', f'{pid}Tex1.jpg') |
|
copy_save_path = os.path.join(workdirImgPath,"copy_texture", f'{pid}_{order_id}', f'{pid}Tex1_old.jpg') |
|
|
|
#判断是否存在目录,不存在就创建 |
|
if not os.path.exists( os.path.join(workdirImgPath,'copy_texture', f'{pid}_{order_id}')): |
|
os.makedirs(os.path.join(workdirImgPath,'copy_texture', f'{pid}_{order_id}')) |
|
|
|
save_path = os.path.join(workdirImgPath, 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(workdirImgPath, f'{pid}_{order_id}')): |
|
os.makedirs(os.path.join(workdirImgPath, 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'] |
|
workdirImgPath = Config['Nose_Config']['Select_system'][f'{os_type}_path']['workdirImgPath'] |
|
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)
|
|
|