import cv2 import os import shutil Img_dir = '../cacheUserImg' Copy_dir = '../cacheUserImgCopy' cv2.namedWindow("show", 0) # 获取人脸识别训练数据 # face_cascade = cv2.CascadeClassifier('./haarcascade_frontalface_default.xml') face_cascade = cv2.CascadeClassifier('./haarcascade_frontalface_alt.xml') def show(img, ms=0, reduce=3): """ 显示 """ cv2.imshow('show', img) h, w = img.shape[:2] cv2.resizeWindow("show", w//reduce, h//reduce) cv2.waitKey(ms) def rotate_img_bad(img, angle): """ 旋转 """ # 原图的高、宽 以及通道数 h, w = img.shape[:2] M = cv2.getRotationMatrix2D((w / 2, h / 2), angle, 1.0) rotated_img = cv2.warpAffine(img, M, (w, h)) # show(rotated_img) cv2.imwrite(f'./test_{angle}.png', rotated_img) return rotated_img def rotate_img(image, angle): # grab the dimensions of the image and then determine the # center (h, w) = image.shape[:2] (cX, cY) = (w // 2, h // 2) # grab the rotation matrix (applying the negative of the # angle to rotate clockwise), then grab the sine and cosine # (i.e., the rotation components of the matrix) M = cv2.getRotationMatrix2D((cX, cY), -angle, 1.0) # print(M, type(M)) cos = abs(M[0, 0]) sin = abs(M[0, 1]) # print(f"cos {cos}, sin {sin}.\t h,w:{h},{w}\tangle:{angle} \t point:{cX},{cY}") # compute the new bounding dimensions of the image nW = int((h * sin) + (w * cos)) nH = int((h * cos) + (w * sin)) # adjust the rotation matrix to take into account translation M[0, 2] += (nW / 2) - cX M[1, 2] += (nH / 2) - cY # perform the actual rotation and return the image rotated_img = cv2.warpAffine(image, M, (nW, nH)) # cv2.imwrite(f'./test_{angle}.png', rotated_img) return rotated_img def check_face(img_gray, cascade): """ 检测人脸 """ # 探测图片中的人脸 faces = face_cascade.detectMultiScale( img_gray, scaleFactor=1.1, # 每次缩减比例 minNeighbors=5, # 检测多次 flags=cv2.CASCADE_SCALE_IMAGE, minSize=(100, 100) ) print("检测到人脸区域:{}".format(faces)) return faces def mark_face(img, faces): """ 标记人脸 """ print("mark face") iy, ix = img.shape[:2] for x, y, w, h in faces: # cv2.rectangle(img, (x, y), (x+w, y+h), (0, 255, 0), 2) show(img, 100) # 裁剪图片 print(ix, iy, x, y, w, h) length2 = min(ix, iy) length = int(w*2.5) length = min(length2, length) print(f"length: {length2} {length}") ow = length-w ow1 = ow//2 oh = length-h oh1 = oh//2 y1, y2 = y-oh1, y+h+oh1 x1, x2 = x-ow1, x+w+ow1 # 检测图片溢出 print(y1, y2, x1, x2) if y1 < 0: print('裁剪:1 顶部溢出') y1 = 0 y2 = length if y2 > iy: print('裁剪:2 底部溢出') y2 = iy y1 = iy-length if x1 < 0: print('裁剪:3 左侧溢出') x1 = 0 x2 = length if x2 > ix: print('裁剪:4 右侧溢出') x2 = ix x1 = ix-length img2 = img[y1:y2, x1:x2] show(img2, 200) return img2 def run(img_name): # 读取图片,灰度转换 img_bgr = cv2.imread(os.path.join(Img_dir, img_name)) img_gray = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2GRAY) # 旋转图片 find = False for angle in range(0, 360, 90): show(rotate_img(img_bgr, angle), 100) print(f"angle: {angle}") if angle > 0: img_bgr_r = rotate_img(img_bgr, angle) img_gray_r = rotate_img(img_gray, angle) else: img_bgr_r = img_bgr img_gray_r = img_gray faces = check_face(img_gray_r, face_cascade) if not isinstance(faces, tuple): print("find face") img_final = mark_face(img_bgr_r, faces) find = True break # show(img_bgr_r, 1000) print('end') if not find: print("未找到人脸,使用原图") img_final = img_bgr cv2.imwrite(os.path.join(Img_dir, img_name), img_final) if __name__ == '__main__': file_list = os.listdir(Img_dir) for i in range(len(file_list)): file_name = file_list[i] print("处理图片{0}/{1}: {2}".format(i+1, len(file_list), file_name)) if not os.path.exists(os.path.join(Copy_dir, file_name)): shutil.copy(f'{Img_dir}/{file_name}', f'{Copy_dir}/{file_name}') try: run(file_name) except Exception as _: pass cv2.destroyAllWindows()