CenterFace人脸检测程序中的一个不为人知的bug
程序是用opencv的dnn模块加载CenterFace的onnx文件做人脸检测的,程序源码在github地址是 https://github.com/hpc203/CenterFace-opencv-dnn-problem
文件夹里有2幅图片,运行 python problem.py,其中problem.py的源码如下
import cv2 from centerface import CenterFace if __name__ == '__main__': frame = cv2.imread('1.jpg') h, w = frame.shape[:2] landmarks = True centerface = CenterFace(landmarks=landmarks) if landmarks: dets, lms = centerface(frame, h, w, threshold=0.35) else: dets = centerface(frame, threshold=0.35) for det in dets: boxes, score = det[:4], det[4] cv2.rectangle(frame, (int(boxes[0]), int(boxes[1])), (int(boxes[2]), int(boxes[3])), (2, 255, 0), 1) if landmarks: for lm in lms: for i in range(0, 5): cv2.circle(frame, (int(lm[i * 2]), int(lm[i * 2 + 1])), 2, (0, 0, 255), -1) cv2.namedWindow('out', cv2.WINDOW_NORMAL) cv2.imshow('out', frame) # cv2.waitKey(0) landmarks = True centerface = CenterFace(landmarks=landmarks) for i in range(2): frame = cv2.imread(str(i)+'.jpg') h, w = frame.shape[:2] # landmarks = True # centerface = CenterFace(landmarks=landmarks) if landmarks: dets, lms = centerface(frame, h, w, threshold=0.35) else: dets = centerface(frame, threshold=0.35) for det in dets: boxes, score = det[:4], det[4] cv2.rectangle(frame, (int(boxes[0]), int(boxes[1])), (int(boxes[2]), int(boxes[3])), (2, 255, 0), 1) if landmarks: for lm in lms: for i in range(0, 5): cv2.circle(frame, (int(lm[i * 2]), int(lm[i * 2 + 1])), 2, (0, 0, 255), -1) # cv2.namedWindow('problem', cv2.WINDOW_NORMAL) # cv2.imshow('problem', frame) # cv2.waitKey(0) cv2.namedWindow('problem', cv2.WINDOW_NORMAL) cv2.imshow('problem', frame) cv2.waitKey(0) cv2.destroyAllWindows()
程序先会读取第2张图片,进入centerface做人脸检测,接下来是for循环读取第1张图片做人脸检测,然后读取第2张图片做人脸检测,最后可视化窗口展示第2张图片的人脸检测结果。结果如下
可以看到同一幅图片,只对单张图片做人脸检测和for循环里做人脸检测之后的结果是不一样的。我尝试过把 for循环之前的centerface = CenterFace(landmarks=landmarks)这句话改写在for循环内,也就是说在for循环遍历每张图片的时候,都会重新初始化网络。改成这样之后,人脸检测结果就是一样的了。按理来说,模型初始化只需要做一次,在for循环之前做模型的初始化的,可这样做的结果就不对了,这是什么原因呢?