如何显示并高亮Haar-Cascade检测到的人脸特征
Haar级联检测特征高亮与展示方法
你现有代码已经完成了检测框的基础绘制,可通过两类方案实现特征高亮展示:
方案1:强化检测结果的视觉高亮
适合业务场景下突出检测到的人脸、人眼目标,在现有描边基础上增加半透明填充、标签标注即可,不会遮挡原始画面内容:
- 半透明填充:通过图层混合实现检测区域的淡色高亮
- 标签标注:在检测框旁标记目标类型,辨识度更高
- 可选:添加检测框中心点标记,方便坐标定位
核心修改代码片段:
# 人脸绘制部分修改 for (x,y,w,h) in faces: # 新建叠加层做半透明效果 overlay = frame.copy() # 绘制实心填充矩形 cv2.rectangle(overlay, (x,y), (x + w, y + h), (255,0,0), -1) # 按权重混合图层,0.3为填充透明度,可自行调整 cv2.addWeighted(overlay, 0.3, frame, 0.7, 0, frame) # 绘制描边与标签 cv2.rectangle(frame, (x,y), (x + w, y + h), (255,0,0), 2) cv2.putText(frame, "Face", (x, y-10), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (255,0,0), 2) roi_gray = gray[y:y + h, x:x + w] roi_color = frame[y:y + h, x:x + w] eyes = eye_cascade.detectMultiScale(roi_gray, 1.1, 18) # 人眼绘制部分修改 for (ex, ey, ew, eh) in eyes: eye_overlay = roi_color.copy() cv2.rectangle(eye_overlay, (ex, ey), (ex + ew, ey + eh), (0,255,0), -1) cv2.addWeighted(eye_overlay, 0.3, roi_color, 0.7, 0, roi_color) cv2.rectangle(roi_color, (ex, ey), (ex + ew, ey + eh), (0, 255, 0), 2) cv2.putText(roi_color, "Eye", (ex, ey-5), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0,255,0), 1)
另外记得在循环结束、释放摄像头后加cv2.destroyAllWindows(),避免窗口残留卡死。
方案2:可视化Haar分类器本身的匹配特征
如果你需要展示Haar算法实际用于匹配判断的底层特征(即明暗块、边缘类特征模板),可以通过CascadeClassifier的getFeatures()接口读取训练好的分类器内存储的所有特征,按检测窗口的缩放比例映射到实际检测到的人脸区域上绘制即可。
需要注意:默认的人脸Haar分类器检测基准窗口为24*24像素,所有特征坐标都是基于这个基准窗口存储的,绘制时需要按当前检测到的人脸宽高做等比缩放,才能对应到实际画面的正确位置。
修改后的完整可运行代码如下:
import cv2 # 加载级联分类器 face_cascade = cv2.CascadeClassifier("models/haarcascade_frontalface_default.xml") eye_cascade = cv2.CascadeClassifier("models/haarcascade_eye.xml") cap = cv2.VideoCapture(0, cv2.CAP_DSHOW) # 读取人脸分类器的所有Haar特征(可选,用于底层特征可视化) face_features = face_cascade.getFeatures() face_window_size = face_cascade.getOriginalWindowSize() while True: ret, frame = cap.read() if not ret: break gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) faces = face_cascade.detectMultiScale(gray,1.3,5) for (x,y,w,h) in faces: # 半透明高亮 overlay = frame.copy() cv2.rectangle(overlay, (x,y), (x + w, y + h), (255,0,0), -1) cv2.addWeighted(overlay, 0.3, frame, 0.7, 0, frame) cv2.rectangle(frame, (x,y), (x + w, y + h), (255,0,0), 2) cv2.putText(frame, "Face", (x, y-10), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (255,0,0), 2) roi_gray = gray[y:y + h, x:x + w] roi_color = frame[y:y + h, x:x + w] # --- 可选:绘制Haar底层特征,不需要可以注释掉 --- # 计算缩放比例 scale_x = w / face_window_size[0] scale_y = h / face_window_size[1] # 取前20个强特征绘制,避免画面太乱 for feat in face_features[:20]: for rect in feat: # 特征矩形坐标映射到实际ROI rx = int(x + rect.x * scale_x) ry = int(y + rect.y * scale_y) rw = int(rect.width * scale_x) rh = int(rect.height * scale_y) # 权重为正画白色,为负画黑色,对应Haar特征的明暗块 color = (255,255,255) if rect.weight > 0 else (0,0,0) cv2.rectangle(frame, (rx, ry), (rx+rw, ry+rh), color, 1) # --- 底层特征绘制结束 --- eyes = eye_cascade.detectMultiScale(roi_gray, 1.1, 18) for (ex, ey, ew, eh) in eyes: eye_overlay = roi_color.copy() cv2.rectangle(eye_overlay, (ex, ey), (ex + ew, ey + eh), (0,255,0), -1) cv2.addWeighted(eye_overlay, 0.3, roi_color, 0.7, 0, roi_color) cv2.rectangle(roi_color, (ex, ey), (ex + ew, ey + eh), (0, 255, 0), 2) cv2.putText(roi_color, "Eye", (ex, ey-5), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0,255,0), 1) cv2.imshow("Webcam Stream", frame) key = cv2.waitKey(1) & 0xff if key == 27: break cap.release() cv2.destroyAllWindows()
如果不需要看底层Haar特征,直接把对应绘制的代码段注释掉即可,半透明高亮的效果已经能满足绝大多数场景的高亮需求。
内容的提问来源于stack exchange,提问作者john minty
相关产品推荐
相关产品推荐

