如何用Python通过摄像头拍摄护照尺寸证件照
问题描述
我现有一段用Python调用摄像头拍摄图像的代码,但拍出来的图像宽高尺寸太大。能不能把画面调整成护照照片的尺寸,只拍摄头部到肩部的区域?有没有办法实现这个需求?我想要的画面效果和最终成品类似护照照,现有代码如下:
import cv2 key = cv2.waitKey(1) webcam = cv2.VideoCapture(0) while True: try: check, frame = webcam.read() print(check) # prints true as long as the webcam is running print(frame) # prints matrix values of each framecd cv2.imshow("Capturing", frame) key = cv2.waitKey(1) if key == ord('s'): cv2.imwrite(filename='saved_img.jpg', img=frame) webcam.release() img_new = cv2.imread('saved_img.jpg', cv2.IMREAD_UNCHANGED) img_new = cv2.imshow("Captured Image", img_new) # SHOWS THE IMAGE AFTER CAPTURING cv2.waitKey(1650) cv2.destroyAllWindows() print("captured images saved") break elif key == ord('q'): print("Turning off camera.") webcam.release() print("Camera off.") print("Program ended.") cv2.destroyAllWindows() break except(KeyboardInterrupt): print("Turning off camera.") webcam.release() print("Camera off.") print("Program ended.") cv2.destroyAllWindows() break
解决方案
完全可以实现,核心思路是在预览和拍摄时锁定/裁剪头肩区域,下面给两种实用方案:
方案1:固定区域裁剪(快速上手)
护照照片标准比例一般是3:4(比如300×400像素),可以在摄像头画面上画一个绿色参考框,提示用户对准,拍摄时直接裁剪框内区域:
修改后的代码:
import cv2 # 定义护照照目标像素尺寸(可按需调整) PASSPORT_W = 300 PASSPORT_H = 400 webcam = cv2.VideoCapture(0) # 获取摄像头原始分辨率 cam_w = int(webcam.get(cv2.CAP_PROP_FRAME_WIDTH)) cam_h = int(webcam.get(cv2.CAP_PROP_FRAME_HEIGHT)) # 计算居中的裁剪区域坐标 x_start = (cam_w - PASSPORT_W) // 2 y_start = (cam_h - PASSPORT_H) // 2 x_end = x_start + PASSPORT_W y_end = y_start + PASSPORT_H while True: check, frame = webcam.read() if not check: break # 在预览画面画绿色参考框 cv2.rectangle(frame, (x_start, y_start), (x_end, y_end), (0, 255, 0), 2) cv2.imshow("对准绿色框拍摄", frame) key = cv2.waitKey(1) if key == ord('s'): # 裁剪框内区域 cropped_img = frame[y_start:y_end, x_start:x_end] cv2.imwrite('passport_photo.jpg', cropped_img) webcam.release() # 展示成品 cv2.imshow("拍摄完成", cropped_img) cv2.waitKey(2000) cv2.destroyAllWindows() print("护照照片已保存") break elif key == ord('q'): print("关闭摄像头") webcam.release() cv2.destroyAllWindows() break webcam.release() cv2.destroyAllWindows()
方案2:人脸检测自动裁剪(精准适配)
如果想自动定位头肩区域,用OpenCV自带的人脸检测模型就能实现,检测到人脸后扩展区域到头肩范围:
修改后的代码:
import cv2 # 加载OpenCV自带的人脸检测模型 face_detector = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml') # 护照照目标比例3:4 TARGET_RATIO = 3/4 webcam = cv2.VideoCapture(0) while True: check, frame = webcam.read() if not check: break gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) faces = face_detector.detectMultiScale(gray, 1.1, 4) # 检测到人脸时计算头肩区域并画框 for (x, y, w, h) in faces: # 扩展人脸区域:向上加30%高度(头顶),向下加20%高度(肩部) top = max(0, int(y - h*0.3)) bottom = min(frame.shape[0], int(y + h + h*0.2)) # 根据比例计算宽度并居中 desired_w = int((bottom - top) * TARGET_RATIO) left = max(0, int(x + w//2 - desired_w//2)) right = min(frame.shape[1], left + desired_w) cv2.rectangle(frame, (left, top), (right, bottom), (0, 255, 0), 2) cv2.imshow("对准人脸拍摄", frame) key = cv2.waitKey(1) if key == ord('s'): if len(faces) > 0: # 裁剪头肩区域并调整到标准尺寸 cropped_img = frame[top:bottom, left:right] cropped_img = cv2.resize(cropped_img, (300, 400)) cv2.imwrite('auto_passport_photo.jpg', cropped_img) print("自动裁剪的护照照片已保存") else: print("未检测到人脸,请调整位置") webcam.release() cv2.destroyAllWindows() break elif key == ord('q'): print("关闭摄像头") webcam.release() cv2.destroyAllWindows() break webcam.release() cv2.destroyAllWindows()
补充说明
- 固定裁剪方案适合快速实现,需要用户自己对准框内区域
- 人脸检测方案更智能,能自动适配不同用户的头肩位置,准确率取决于人脸检测的环境(光线、角度等)
- 可以根据实际护照照片的尺寸要求,修改代码里的像素数值
内容的提问来源于stack exchange,提问作者O JOE
相关产品推荐
相关产品推荐

