如何将NumPy数组图像的人脸矩形区域保存到变量中?
问题:提取图像局部区域到变量不符合预期
尝试从尺寸为(640,480,3)的numpy.ndarray图像中提取矩形框标记的区域到face_region变量,cv2.rectangle()能正常绘制并显示矩形,但提取的区域无法正确保留目标局部、或出现报错。相关代码如下:
def extract_face_region(image, landmarks): landmark_coords = np.array([(landmarks.part(i).x, landmarks.part(i).y) for i in [2, 14, 40, 41, 46, 47, 50, 52]]) XLT = landmarks.part(14).x YLT = max(landmarks.part(40).y, landmarks.part(41).y, landmarks.part(46).y, landmarks.part(47).y) Wrect = landmarks.part(2).x - landmarks.part(14).x Hrect = min(landmarks.part(50).y, landmarks.part(52).y) - YLT if 0 <= XLT < image.shape[1] and 0 <= YLT < image.shape[0] and 0 <= XLT + Wrect <= image.shape[1] and 0 <= YLT + Hrect <= image.shape[0]: face_region = image[YLT:YLT+Hrect, XLT:XLT+Wrect, :] else: print("Region outside image limits.") cv2.rectangle(image, (int(XLT), int(YLT)), (int(XLT + Wrect), int(YLT + Hrect)), (255, 0, 0), 2) #cv2_imshow(image) cv2_imshow(face_region) return face_region
解决建议
1. 统一处理坐标为整数
人脸关键点坐标通常是浮点数,直接用于numpy切片会导致错误或异常结果,先把所有坐标转为整数:
XLT = int(landmarks.part(14).x) YLT = int(max(landmarks.part(40).y, landmarks.part(41).y, landmarks.part(46).y, landmarks.part(47).y)) XRT = int(landmarks.part(2).x) YRB = int(min(landmarks.part(50).y, landmarks.part(52).y))
2. 避免负尺寸的矩形
如果关键点顺序导致XRT < XLT或YRB < YLT,计算出的宽高会是负数,numpy切片会返回空数组。强制修正坐标顺序确保宽高为正:
# 确保左x小于右x,上y小于下y x1, x2 = min(XLT, XRT), max(XLT, XRT) y1, y2 = min(YLT, YRB), max(YLT, YRB) Wrect = x2 - x1 Hrect = y2 - y1
3. 初始化默认的face_region
当区域超出图像范围时,原代码中face_region未定义,直接调用cv2_imshow会抛出NameError。在else分支初始化空数组避免报错:
if 0 <= x1 < image.shape[1] and 0 <= y1 < image.shape[0] and 0 <= x2 <= image.shape[1] and 0 <= y2 <= image.shape[0]: face_region = image[y1:y2, x1:x2, :] else: print("Region outside image limits.") face_region = np.array([]) # 初始化空数组
4. 优化切片显示逻辑
添加判断,仅当face_region有效时才显示,避免空数组报错:
if face_region.size > 0: cv2_imshow(face_region)
修正后的完整代码
def extract_face_region(image, landmarks): # 提取关键点坐标并转为整数 XLT = int(landmarks.part(14).x) YLT = int(max(landmarks.part(40).y, landmarks.part(41).y, landmarks.part(46).y, landmarks.part(47).y)) XRT = int(landmarks.part(2).x) YRB = int(min(landmarks.part(50).y, landmarks.part(52).y)) # 修正坐标顺序,确保矩形宽高为正 x1, x2 = min(XLT, XRT), max(XLT, XRT) y1, y2 = min(YLT, YRB), max(YLT, YRB) # 提取目标区域 if 0 <= x1 < image.shape[1] and 0 <= y1 < image.shape[0] and 0 <= x2 <= image.shape[1] and 0 <= y2 <= image.shape[0]: face_region = image[y1:y2, x1:x2, :] else: print("Region outside image limits.") face_region = np.array([]) cv2.rectangle(image, (x1, y1), (x2, y2), (255, 0, 0), 2) if face_region.size > 0: cv2_imshow(face_region) return face_region
内容的提问来源于stack exchange,提问作者leonardo20
相关产品推荐
相关产品推荐

