Opencv中!face_cascade.load( face_cascade_name )报错,xml文件无法加载

本文介绍了解决在OpenCV中使用`face_cascade.load`时遇到的错误加载问题,重点提示了路径检查、XML版本对应、以及从debug模式切换到release模式的必要性,包括项目属性配置。
部署运行你感兴趣的模型镜像

face_cascade.load

在opencv中加载xml文件的代码片段如下

// 代码片段
 cv::String face_cascade_name = "D:/opencv2.49/opencv/sources/data/haarcascades/haarcascade_eye_tree_eyeglasses.xml";

 if (!face_cascade.load(face_cascade_name))
  { printf("--(!)Error loading face cascade, please change face_cascade_name in source code.\n"); return -1; };


在VS2022中编译时,总是加载失败,显示Error loading face cascade。大家可以从以下几方面进行排查:

1.路径是否正确。要注意两级之间的连接使用/或\,并且注意路径中要不含中文
2.xml文件的版本是否正确,opencv版本和vs是否适配
3.要用release版本运行,不能用debug!!(我也不知道为什么,但我debug了两周都报错,换成release就可以了
要注意换成release后,相应的项目属性需要重新配置,特别是附加依赖项,要换成没有d的版本

祝大家调试顺利

您可能感兴趣的与本文相关的镜像

ACE-Step

ACE-Step

音乐合成
ACE-Step

ACE-Step是由中国团队阶跃星辰(StepFun)与ACE Studio联手打造的开源音乐生成模型。 它拥有3.5B参数量,支持快速高质量生成、强可控性和易于拓展的特点。 最厉害的是,它可以生成多种语言的歌曲,包括但不限于中文、英文、日文等19种语言

void detectAndDisplay(Mat frame); /** Global variables */ CascadeClassifier face_cascade; CascadeClassifier eyes_cascade; /** @function main */ int main(int argc, const char** argv) { CommandLineParser parser(argc, argv, "{help h||}" "{face_cascade|data/haarcascades/haarcascade_frontalface_alt.xml|Path to face cascade.}" "{eyes_cascade|data/haarcascades/haarcascade_eye_tree_eyeglasses.xml|Path to eyes cascade.}" "{camera|0|Camera device number.}"); parser.about("\nThis program demonstrates using the cv::CascadeClassifier class to detect objects (Face + eyes) in a video stream.\n" "You can use Haar or LBP features.\n\n"); parser.printMessage(); String face_cascade_name = samples::findFile(parser.get<String>("face_cascade")); String eyes_cascade_name = samples::findFile(parser.get<String>("eyes_cascade")); //-- 1. Load the cascades if (!face_cascade.load(face_cascade_name)) { cout << "--(!)Error loading face cascade\n"; return -1; }; if (!eyes_cascade.load(eyes_cascade_name)) { cout << "--(!)Error loading eyes cascade\n"; return -1; }; int camera_device = parser.get<int>("camera"); VideoCapture capture; //-- 2. Read the video stream capture.open(camera_device); if (!capture.isOpened()) { cout << "--(!)Error opening video capture\n"; return -1; } Mat frame; while (capture.read(frame)) { if (frame.empty()) { cout << "--(!) No captured frame -- Break!\n"; break; } //-- 3. Apply the classifier to the frame detectAndDisplay(frame); if (waitKey(10) == 27) { break; // escape } } return 0; }
06-01
import sys import cv2 import os import numpy as np import uuid from PIL import Image, ImageDraw, ImageFont from datetime import datetime from PyQt5 import QtCore, QtGui, QtWidgets from PyQt5.QtCore import Qt from face_11 import Ui_mainWindow # 假设UI文件生成的模块名为face_11 class FaceSignInSystem(QtWidgets.QMainWindow, Ui_mainWindow): def __init__(self): super().__init__() self.setupUi(self) self.current_face_id = "" self.photo_count = 0 self.a = 0 self.b = 0 self.signed_names = set() # 用于存储已签到的姓名 self.sign_records = [] # 存储完整签到记录(含时间) self.last_signed_time = {} # 记录每个人最后签到时间,避免重复签到 self.sign_cooldown = 5 # 签到冷却时间(秒) # 新增:多角度识别配置 self.angle_thresholds = { "frontal": 5000, # 正面阈值 "left": 9500, # 左侧面阈值 "right": 9500, # 右侧面阈值 "up": 8500, # 抬头阈值 "down": 8500 # 低头阈值 } # 初始化标签显示 self.label_3.setWordWrap(True) self.label_3.setStyleSheet("color: green; font-size: 12pt;") self.label_4.setStyleSheet("color: red; font-size: 12pt;") self.label_3.setText("签到信息") self.label_4.setText("缺勤信息") # 隐藏初始不可用的按钮 self.camera_btn.hide() self.ovecam_btn.hide() self.oversign_btn.hide() self.user_edit.setObjectName("user_edit") self.user_edit.setPlaceholderText("请输入姓名") # 创建班级表 def name(self, face_id): try: with open('info.csv', 'r+') as f: myInfo = f.readlines() namelist = [line.split(',')[0].strip() for line in myInfo] if face_id not in namelist: f.writelines(f'\n{face_id},已录入') except Exception as e: print(f"创建班级表时出错: {e}") # 生成图片文件(修改:添加角度信息) def gen_face_name(self, str_face_id, angle="frontal"): return f"{str_face_id}_{angle}_{str(uuid.uuid4())}.jpg" # 绘制中文字符 def ChineseText(self, img, text, position, textColor=(255, 0, 0), textsize=30): try: font_paths = ["simsun.ttc", "simhei.ttf", "Arial.ttf"] font = None for font_path in font_paths: try: font = ImageFont.truetype(font_path, textsize, encoding='utf-8') break except: continue if font is None: font = ImageFont.load_default() if isinstance(img, np.ndarray): img = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB)) draw = ImageDraw.Draw(img) draw.text(position, text, textColor, font=font) return cv2.cvtColor(np.asarray(img), cv2.COLOR_RGB2BGR) except Exception as e: print(f"绘制文字失败: {e}") return img # 保存签到信息 def saveInfo(self, face_id): try: now = datetime.now() if face_id in self.last_signed_time: time_diff = (now - self.last_signed_time[face_id]).total_seconds() if time_diff < self.sign_cooldown: return False # 冷却中,不执行签到 if face_id not in self.signed_names: now_str = now.strftime("%Y-%m-%d %H:%M:%S") self.signed_names.add(face_id) self.last_signed_time[face_id] = now new_record = f"{face_id} 于 {now_str} 签到" self.sign_records.append(new_record) display_records = self.sign_records[-20:] self.label_3.setText("\n".join(display_records)) return True return False except Exception as e: print(f"保存签到信息时出错: {e}") self.label_3.setText("签到失败,请重试") return False # 生成缺勤名单 def absenteeism(self): try: total = set() with open('info.csv', 'r') as f: total = {line.split(',')[0].strip() for line in f if line.strip() and not line.startswith('name')} absentee_list = total - self.signed_names if absentee_list: self.label_4.setText(f"缺勤人员:{', '.join(absentee_list)}") with open('absenteeism.csv', 'w') as f: for name in absentee_list: f.write(f'{name},未签到\n') else: self.label_4.setText("无缺勤人员") except Exception as e: print(f"建立缺勤名单时出错: {e}") self.label_4.setText("生成缺勤名单失败") # 加载模型 def load_model(self, file_scp): face_ids = [] face_models = [] angle_models = {} # 新增:按角度存储模型 try: with open(file_scp, 'r', encoding='utf-8') as f: lines = f.read().splitlines() for line in lines: parts = line.strip().split() if len(parts) >= 2: face_id = parts[0] model_path = parts[1] if not os.path.exists(model_path): print(f"模型文件不存在: {model_path},尝试重新生成模型") self.generate_face_model(face_id) if not os.path.exists(model_path): print(f"重新生成模型失败: {model_path}") continue try: model_data = np.load(model_path) face_ids.append(face_id) face_models.append(model_data) # 提取角度信息 angle = "frontal" # 默认正面 if "_left_" in model_path: angle = "left" elif "_right_" in model_path: angle = "right" elif "_up_" in model_path: angle = "up" elif "_down_" in model_path: angle = "down" if face_id not in angle_models: angle_models[face_id] = {} angle_models[face_id][angle] = model_data print(f"成功加载模型: {model_path} ({angle})") except Exception as e: print(f"加载模型 {model_path} 失败: {e}") return face_ids, face_models, angle_models except Exception as e: print(f"加载模型索引文件失败: {e}") return [], [], {} # 新增:检测人脸角度 def detect_face_angle(self, face_roi): # 简化版角度检测,实际应用中可以使用更复杂的姿态估计算法 eyes = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_eye.xml').detectMultiScale(face_roi) if len(eyes) >= 2: # 计算双眼之间的角度 eye1, eye2 = sorted(eyes, key=lambda e: e[0])[:2] eye1_center = (eye1[0] + eye1[2] // 2, eye1[1] + eye1[3] // 2) eye2_center = (eye2[0] + eye2[2] // 2, eye2[1] + eye2[3] // 2) dx = eye2_center[0] - eye1_center[0] dy = eye2_center[1] - eye1_center[1] angle = np.degrees(np.arctan2(dy, dx)) return angle return 0 # 人脸识别(修改:添加角度感知) def face_recognize(self, face_roi, face_models, face_ids, angle_models=None, face_angle=0): target_size = (100, 100) face_roi = cv2.resize(face_roi, target_size) face_vector = face_roi.flatten() min_distance = float('inf') best_match_index = -1 # 确定当前人脸角度分类 angle_category = "frontal" if face_angle < -30: angle_category = "left" elif face_angle > 30: angle_category = "right" # 优先使用特定角度的模型 if angle_models: for i, face_id in enumerate(face_ids): if face_id in angle_models and angle_category in angle_models[face_id]: model = angle_models[face_id][angle_category] model_vectors = model.reshape(model.shape[0], -1) distances = np.sqrt(np.sum((model_vectors - face_vector) ** 2, axis=1)) avg_distance = np.mean(distances) # 根据角度调整阈值 threshold = self.angle_thresholds.get(angle_category, 7000) if avg_distance < min_distance and avg_distance < threshold: min_distance = avg_distance best_match_index = i # 回退到通用模型 if best_match_index == -1: for i, model in enumerate(face_models): model_vectors = model.reshape(model.shape[0], -1) distances = np.sqrt(np.sum((model_vectors - face_vector) ** 2, axis=1)) avg_distance = np.mean(distances) if avg_distance < min_distance: min_distance = avg_distance best_match_index = i if best_match_index != -1 and min_distance < self.angle_thresholds.get(angle_category, 7000): return face_ids[best_match_index], min_distance else: return "unknown", min_distance # 获取最大人脸区域 def get_max_face_opencv(self, face_rects): if len(face_rects) == 0: return 0, None max_area = 0 max_rect = None for (x, y, w, h) in face_rects: area = w * h if area > max_area: max_area = area max_rect = (x, y, w, h) return max_area, max_rect # 生成人脸模型(修改:支持多角度模型) def generate_face_model(self, face_id): face_dir = os.path.join('faces', face_id) os.makedirs(face_dir, exist_ok=True) # 按角度分类图片 angle_images = { "frontal": [], "left": [], "right": [], "up": [], "down": [] } for img_name in os.listdir(face_dir): if img_name.endswith('.jpg'): img_path = os.path.join(face_dir, img_name) with open(img_path, 'rb') as f: img_data = np.frombuffer(f.read(), np.uint8) img = cv2.imdecode(img_data, cv2.IMREAD_GRAYSCALE) if img is not None: img = cv2.resize(img, (100, 100)) # 确定图片角度分类 angle = "frontal" if "_left_" in img_name: angle = "left" elif "_right_" in img_name: angle = "right" elif "_up_" in img_name: angle = "up" elif "_down_" in img_name: angle = "down" angle_images[angle].append(img) # 为每个角度生成模型 model_paths = [] for angle, images in angle_images.items(): if images: model_path = os.path.join(face_dir, f"{face_id}_{angle}.npy") try: model_data = np.array(images) np.save(model_path, model_data) print(f"模型已保存至:{model_path} ({angle})") model_paths.append(model_path) except Exception as e: print(f"保存{angle}模型失败: {e}") # 更新模型索引文件 try: with open('model.scp', 'a', encoding='utf-8') as f: for path in model_paths: angle = "frontal" if "_left_" in path: angle = "left" elif "_right_" in path: angle = "right" elif "_up_" in path: angle = "up" elif "_down_" in path: angle = "down" f.write(f"{face_id} {path} {angle}\n") except Exception as e: print(f"更新模型索引文件失败: {e}") return model_paths # 信息录入功能(修改:强制多角度采集) def do_info(self): self.info_btn.hide() self.sign_btn.hide() self.oversign_btn.hide() self.camera_btn.show() self.ovecam_btn.show() face_id = self.user_edit.text().strip() if not face_id: print("请输入有效的姓名") return self.current_face_id = face_id self.a = 0 # 多角度采集 required_angles = ["frontal", "left", "right", "up", "down"] angle_descriptions = { "frontal": "正面", "left": "左侧面", "right": "右侧面", "up": "抬头", "down": "低头" } try: os.makedirs('faces', exist_ok=True) face_dir = os.path.join('faces', face_id) os.makedirs(face_dir, exist_ok=True) face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml') if face_cascade.empty(): print("无法加载人脸检测器") return cap = cv2.VideoCapture(0) if not cap.isOpened(): print("无法打开摄像头") return angle_index = 0 current_angle = required_angles[angle_index] angle_count = {angle: 0 for angle in required_angles} total_count = 0 print(f"开始采集 {face_id} 的人脸数据") while True: ret, frame = cap.read() if not ret: break gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) face_rects = face_cascade.detectMultiScale( gray, scaleFactor=1.1, minNeighbors=5, minSize=(100, 100) ) max_area, max_rect = self.get_max_face_opencv(face_rects) # 显示当前采集状态 status_text = f"请面对摄像头 {angle_descriptions[current_angle]},已采集: {angle_count[current_angle]}/3" frame = self.ChineseText(frame, status_text, (10, 30), (0, 255, 0), 24) if max_area > 10: x, y, w, h = max_rect cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 0, 255), 2) cv2.imshow("FACE", frame) if self.a == 1: self.a = 0 if max_area > 10 and angle_count[current_angle] < 3: x, y, w, h = max_rect roi = frame[y:y + h, x:x + w] save_path = os.path.join(face_dir, self.gen_face_name(face_id, current_angle)) cv2.imencode('.jpg', roi)[1].tofile(save_path) angle_count[current_angle] += 1 total_count += 1 print(f"已保存{angle_descriptions[current_angle]}人脸图片: {save_path}") # 切换到下一个角度 if angle_count[current_angle] >= 3 and angle_index < len(required_angles) - 1: angle_index += 1 current_angle = required_angles[angle_index] elif self.a == 3: self.a = 0 break if cv2.waitKey(1) == 27: break cap.release() cv2.destroyAllWindows() if total_count > 0: print(f"成功采集 {total_count} 张 {face_id} 的人脸图片") self.generate_face_model(face_id) self.name(face_id) else: print("未采集到任何人脸图片") except Exception as e: print(f"发生错误: {e}") if 'cap' in locals() and cap.isOpened(): cap.release() cv2.destroyAllWindows() # 开始拍照 def do_camera(self): if not self.current_face_id: print("请先输入姓名") return self.a = 1 # 结束录入 def do_ovecam(self): self.info_btn.show() self.sign_btn.show() self.oversign_btn.hide() self.camera_btn.hide() self.ovecam_btn.hide() self.a = 3 # 开始签到(修改:添加角度感知) def do_sign(self): self.info_btn.hide() self.sign_btn.hide() self.oversign_btn.show() # 加载模型(获取角度模型) face_ids, face_models, angle_models = self.load_model("model.scp") if not face_models: print("没有可用的人脸模型,请先录入人脸数据") self.do_oversign() return face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml') if face_cascade.empty(): print("无法加载人脸检测器") self.do_oversign() return cap = cv2.VideoCapture(0) # 重置签到记录 self.last_signed_time = {} while True: success, img = cap.read() if not success: break gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) face_rects = face_cascade.detectMultiScale( gray, scaleFactor=1.1, minNeighbors=5, minSize=(100, 100) ) # 只处理最大的人脸 max_area, max_rect = self.get_max_face_opencv(face_rects) if max_area > 10000: # 设置最小人脸面积阈值 x, y, w, h = max_rect cv2.rectangle(img, (x, y), (x + w, y + h), (0, 0, 255), 2) face_roi = gray[y:y + h, x:x + w] # 检测人脸角度 face_angle = self.detect_face_angle(face_roi) # 进行人脸识别(带角度信息) face_id, confidence = self.face_recognize(face_roi, face_models, face_ids, angle_models, face_angle) # 根据识别结果显示不同信息 if face_id != "unknown" and confidence < self.angle_thresholds.get("frontal", 7000): # 显示角度信息 #angle_text = f"角度: {int(face_angle)}°" #img = self.ChineseText(img, angle_text, (x, y - 60), (0, 165, 255)) signed = self.saveInfo(face_id) st = "签到成功" if signed else "已签到" text = f"{face_id}{st}" color = (0, 0, 255) if signed else (0, 165, 255) else: text = "未注册" color = (0, 0, 255) # 显示识别信息 img = self.ChineseText(img, text, (x, y - 30), color) cv2.imshow("FACE", img) cv2.resizeWindow("FACE",640, 480) key = cv2.waitKey(1) if key == 27 or key == ord('q') or self.b == 1: self.b = 0 break self.absenteeism() cap.release() cv2.destroyAllWindows() # 结束签到 def do_oversign(self): self.info_btn.show() self.sign_btn.show() self.oversign_btn.hide() self.b = 1 self.absenteeism() if __name__ == "__main__": app = QtWidgets.QApplication(sys.argv) window = FaceSignInSystem() window.show() sys.exit(app.exec_())==完整的主代码 ArcFace 进行特征提取与匹配
最新发布
06-12
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值