基于Python的鱼眼摄像头人脸识别应用开发问题求助
适配鱼眼摄像头的人脸识别解决方案:从关键点检测失败到正常运行
Hey Logesh, 我看了你遇到的鱼眼摄像头适配问题——普通webcam下人脸识别正常,但切换到鱼眼镜头后连人脸关键点都检测不出来,这确实是鱼眼镜头的畸变特性导致的典型问题。咱们一步步拆解解决:
问题根源分析
鱼眼镜头会产生桶形畸变,画面边缘的人脸会被严重拉伸变形,而face_recognition和dlib的人脸检测模型是基于正常平面图像训练的,自然无法识别畸变后的人脸形态。另外我注意到你的代码里还有两个独立的摄像头循环,这会导致硬件资源冲突,也是关键点检测失败的潜在原因。
解决方案步骤
1. 先矫正鱼眼图像的畸变
首先需要通过OpenCV的鱼眼畸变矫正功能,把扭曲的画面还原成正常平面图像。你需要先获取摄像头的内参(K)和畸变系数(D),如果没有专业标定数据,可以先用近似参数,之后再用棋盘格标定优化。
畸变矫正函数与示例参数
import numpy as np import cv2 def undistort_fisheye(frame, K, D): # 初始化畸变矫正映射表 h, w = frame.shape[:2] map1, map2 = cv2.fisheye.initUndistortRectifyMap(K, D, np.eye(3), K, (w, h), cv2.CV_16SC2) # 应用矫正 undistorted_frame = cv2.remap(frame, map1, map2, interpolation=cv2.INTER_LINEAR, borderMode=cv2.BORDER_CONSTANT) return undistorted_frame # 示例参数(根据你的摄像头调整,建议用棋盘格标定获取准确值) K = np.array([[600, 0, 320], [0, 600, 240], [0, 0, 1]], dtype=np.float32) D = np.array([[0.1, 0.05, 0.01, 0.005, 0.0]], dtype=np.float32)
2. 修复代码中的两个关键错误
- 颜色格式转换错误:原代码中
rgb_small_frame = small_frame[:, :, ::1]是错的,OpenCV读取的是BGR格式,face_recognition需要RGB,应该改成::-1。 - 双摄像头循环冲突:原代码同时启动了两个摄像头捕获循环,会导致硬件资源抢占,必须合并成一个循环。
3. 优化人脸检测灵敏度
即使矫正了畸变,鱼眼镜头下的人脸可能还是有轻微变形,可以调高dlib检测器的upsample参数,提升对变形/小尺寸人脸的检测率:
# 原代码的detector调用改成: faces = detector(gray, 2) # 第二个参数为upsample次数,默认0,设为2会更敏感
修正后的完整代码
import face_recognition import cv2 import numpy as np import dlib # 鱼眼畸变矫正参数(根据你的摄像头调整,建议用棋盘格标定获取准确值) K = np.array([[600, 0, 320], [0, 600, 240], [0, 0, 1]], dtype=np.float32) D = np.array([[0.1, 0.05, 0.01, 0.005, 0.0]], dtype=np.float32) def undistort_fisheye(frame, K, D): h, w = frame.shape[:2] map1, map2 = cv2.fisheye.initUndistortRectifyMap(K, D, np.eye(3), K, (w, h), cv2.CV_16SC2) undistorted_frame = cv2.remap(frame, map1, map2, interpolation=cv2.INTER_LINEAR, borderMode=cv2.BORDER_CONSTANT) return undistorted_frame # 获取默认摄像头引用 video_capture = cv2.VideoCapture(0) # 设置摄像头分辨率(可选,根据你的鱼眼摄像头调整) video_capture.set(cv2.CAP_PROP_FRAME_WIDTH, 1280) video_capture.set(cv2.CAP_PROP_FRAME_HEIGHT, 720) # 加载样本图片并生成编码 obama_image = face_recognition.load_image_file("obama.jpg") obama_face_encoding = face_recognition.face_encodings(obama_image)[0] biden_image = face_recognition.load_image_file("biden.jpg") biden_face_encoding = face_recognition.face_encodings(biden_image)[0] Logesh_image = face_recognition.load_image_file("Upside Logesh.jpg") Logesh_face_encoding = face_recognition.face_encodings(Logesh_image)[0] known_face_encodings = [ obama_face_encoding, biden_face_encoding, Logesh_face_encoding ] known_face_names = [ "Barack Obama", "Joe Biden", "Logesh" ] # 初始化变量 face_locations = [] face_encodings = [] face_names = [] process_this_frame = True # 初始化dlib的检测器和关键点预测器 detector = dlib.get_frontal_face_detector() predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat") while True: ret, frame = video_capture.read() if not ret: break # 第一步:矫正鱼眼畸变 undistorted_frame = undistort_fisheye(frame, K, D) # 缩小帧以加快处理速度 small_frame = cv2.resize(undistorted_frame, (0, 0), fx=0.25, fy=0.25) # 正确转换为RGB格式 rgb_small_frame = small_frame[:, :, ::-1] # 每隔一帧处理一次以节省资源 if process_this_frame: face_locations = face_recognition.face_locations(rgb_small_frame) face_encodings = face_recognition.face_encodings(rgb_small_frame, face_locations) face_names = [] for face_encoding in face_encodings: matches = face_recognition.compare_faces(known_face_encodings, face_encoding) name = "Unknown" # 选择最匹配的人脸 face_distances = face_recognition.face_distance(known_face_encodings, face_encoding) best_match_index = np.argmin(face_distances) if matches[best_match_index]: name = known_face_names[best_match_index] face_names.append(name) process_this_frame = not process_this_frame # 绘制人脸识别结果 display_frame = undistorted_frame.copy() frame_center = display_frame.shape[1] // 2 for (top, right, bottom, left), name in zip(face_locations, face_names): # 缩放回原尺寸 top *= 4 right *= 4 bottom *= 4 left *= 4 # 绘制人脸框和名称 cv2.rectangle(display_frame, (left, top), (right, bottom), (0, 0, 255), 2) cv2.rectangle(display_frame, (left, bottom - 35), (right, bottom), (0, 0, 255), cv2.FILLED) font = cv2.FONT_HERSHEY_DUPLEX cv2.putText(display_frame, name, (left + 10, bottom - 6), font, 1.0, (255, 255, 255), 1) # 位置提示 if right < frame_center - 100: cv2.putText(display_frame, "You are in the right side", (left - 100, bottom - 300), font, 0.8, (255, 255, 255), 1) elif left > frame_center + 100: cv2.putText(display_frame, "You are in the left side", (left - 100, bottom - 300), font, 0.8, (255, 255, 255), 1) # 检测并绘制人脸关键点 gray = cv2.cvtColor(display_frame, cv2.COLOR_BGR2GRAY) faces = detector(gray, 2) # 提升检测灵敏度 for face in faces: landmarks = predictor(gray, face) for n in range(0, 68): x = landmarks.part(n).x y = landmarks.part(n).y cv2.circle(display_frame, (x, y), 3, (255, 0, 0), -1) # 显示结果 cv2.imshow('Fisheye Face Recognition', display_frame) # 按q退出 if cv2.waitKey(1) & 0xFF == ord('q'): break # 释放资源 video_capture.release() cv2.destroyAllWindows()
额外优化建议
如果近似畸变参数效果不好,建议用棋盘格标定法获取准确的K和D参数:打印一张棋盘格,用鱼眼摄像头从不同角度、距离拍摄20-30张图片,然后用OpenCV的cv2.fisheye.calibrate工具计算出专属的畸变参数,这样矫正效果会更精准。
内容的提问来源于stack exchange,提问作者Logesh M
相关产品推荐
相关产品推荐

