当前位置:首页 > 技术 > 正文内容

OpenCV、Dlib与MTCNN人脸检测算法性能对比

访客 技术 2026年8月28日 2
本文对比了三种主流人脸检测框架在证件照场景下的检测效果,测试数据包含银行提供的身份证复印件图像(含多张模糊人脸样本)。实验环境使用Python3.7 + CUDA 10.0,涉及模型权重文件及测试代码均来自开源项目。
![]()![]()

# 人脸检测 - Dlib优化版
import cv2
import dlib
import glob
import datetime

# 图像分类目录
PROCESSED_DIR = "output/processed/"
UNDETECTED_DIR = "output/undetected/"
ERROR_DIR = "output/error/"
MULTI_DIR = "output/multi_face/"
ORIGINAL_DIR = "input/"

# 初始化检测器
face_detector = dlib.get_frontal_face_detector()
landmark_predictor = dlib.shape_predictor("models/shape_predictor_68_face_landmarks.dat")

start_time = datetime.datetime.now()
image_count = 0
error_count = 0

for img_path in glob.glob(ORIGINAL_DIR + "*.jpg"):
    image = cv2.imread(img_path)
    gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    
    # 多尺度检测
    faces = face_detector(gray_image, 3)
    face_num = len(faces)
    filename = img_path.split("\\")[-1]
    
    if face_num > 1:
        print("多人脸检测:", filename)
        cv2.imwrite(MULTI_DIR + filename, image)
        continue
    
    if face_num == 0:
        error_count += 1
        print(f"未检测到人脸({error_count}):", filename)
        cv2.imwrite(UNDETECTED_DIR + filename, image)
        continue
    
    # 提取面部特征点
    face_shape = landmark_predictor(image, faces[0])
    if len(face_shape.parts()) < 68:
        print("异常检测结果:", filename)
        cv2.imwrite(ERROR_DIR + filename, image)
        continue
    
    # 绘制检测框与特征点
    for point in face_shape.parts():
        cv2.circle(image, (point.x, point.y), 1, (0, 255, 0), 2)
    
    x, y, w, h = faces[0].left(), faces[0].top(), faces[0].width(), faces[0].height()
    cv2.rectangle(image, (x, y), (x+w, y+h), (0, 255, 0), 2)
    cv2.imwrite(PROCESSED_DIR + filename, image)
    image_count += 1

print("检测耗时:", datetime.datetime.now() - start_time)
View Code
![]()![]()

# 人脸检测 - OpenCV增强版
import cv2
import glob
import datetime

# 初始化分类器
face_cascade = cv2.CascadeClassifier("models/haarcascade_frontalface_default.xml")
input_dir = "input/"
output_dir = "output/"

start_time = datetime.datetime.now()
undetected_count = 0

for img_path in glob.glob(input_dir + "*.jpg"):
    image = cv2.imread(img_path)
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    
    # 多级图像预处理
    _, binary1 = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_TRIANGLE)
    _, binary2 = cv2.threshold(gray, 100, 255, cv2.THRESH_OTSU)
    binary3 = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, 
                                   cv2.THRESH_BINARY, 25, 10)
    
    # 高斯降噪
    processed = cv2.GaussianBlur(binary3, (7,7), 0)
    
    # 多尺度检测
    faces = face_cascade.detectMultiScale(processed, scaleFactor=1.2, 
                                         minNeighbors=3, minSize=(32,32))
    
    filename = img_path.split("\\")[-1]
    face_num = len(faces)
    
    if face_num > 1:
        print("多人脸检测:", filename)
        cv2.imwrite(output_dir + "multi/" + filename, image)
        continue
    
    if face_num == 0:
        undetected_count += 1
        print(f"未检测到人脸({undetected_count}):", filename)
        cv2.imwrite(output_dir + "undetected/" + filename, image)
        continue
    
    # 绘制检测结果
    for (x, y, w, h) in faces:
        cv2.rectangle(image, (x, y), (x+w, y+h), (0, 255, 0), 2)
        cv2.circle(image, (x + w//4, y + h//4 + 30), min(w//8, h//8), (0, 255, 0))
        cv2.circle(image, (x + 3*w//4, y + h//4 + 30), min(w//8, h//8), (0, 255, 0))
        cv2.rectangle(image, (x + 3*w//8, y + 3*h//4), 
                     (x + 5*w//8, y + 7*h//8), (0, 255, 0))
    
    cv2.imwrite(output_dir + "detected/" + filename, image)

print("检测耗时:", datetime.datetime.now() - start_time)
View Code
![]()![]()

# 人脸检测 - MTCNN实现
import mxnet as mx
import cv2
import glob
import time
import datetime

# 初始化检测器
mtcnn_model = MtcnnDetector(model_folder="models/mxnet", ctx=mx.cpu(0), 
                           num_worker=4, accurate_landmark=False)
input_dir = "input/"
output_dir = "output/"

start_time = datetime.datetime.now()
undetected_count = 0

def process_images():
    for img_path in glob.glob(input_dir + "*.jpg"):
        image = cv2.imread(img_path)
        gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
        filename = img_path.split("\\")[-1]
        
        # 执行检测
        start = time.time()
        results = mtcnn_model.detect_face(image)
        elapsed = time.time() - start
        
        if results is None:
            undetected_count += 1
            print(f"未检测到人脸({undetected_count}):", filename)
            cv2.imwrite(output_dir + "undetected/" + filename, image)
            continue
        
        boxes, points = results
        face_num = len(boxes)
        
        if face_num > 1:
            print("多人脸检测:", filename)
            for box in boxes:
                cv2.rectangle(image, (int(box[0]), int(box[1])), 
                             (int(box[2]), int(box[3])), (0, 255, 0), 2)
            for p in points:
                for i in range(5):
                    cv2.circle(image, (p[i], p[i+5]), 1, (0, 255, 0), 2)
            cv2.imwrite(output_dir + "multi/" + filename, image)
            continue
        
        if face_num == 0:
            undetected_count += 1
            print(f"未检测到人脸({undetected_count}):", filename)
            cv2.imwrite(output_dir + "undetected/" + filename, image)
            continue
        
        # 绘制检测结果
        for box in boxes:
            cv2.rectangle(image, (int(box[0]), int(box[1])), 
                         (int(box[2]), int(box[3])), (0, 255, 0), 2)
        
        for p in points:
            for i in range(5):
                cv2.circle(image, (p[i], p[i+5]), 1, (0, 255, 0), 2)
        
        cv2.imwrite(output_dir + "detected/" + filename, image)
        print(f"检测耗时: {elapsed:.4f}s")

process_images()
print("总耗时:", datetime.datetime.now() - start_time)
View Code
![]()
标签: OpenCV
返回列表

上一篇:Linux 系统中的进程管理与状态演变

没有最新的文章了...

相关文章

Linux crontab 详解

1) crontab 是什么cron 是 Linux 的定时任务守护进程;crontab 是用来编辑/查看“按时间周期执行命令”的表(cron table)。常见两类:用户 crontab:每个用户一份(crontab -e 编辑)系统级 crontab / cron.d:可指定执行用户(/etc/crontab、/etc/cron.d/*)2) crontab 时间...

富文本里可以允许的 HTML 属性

一、所有标签默认允许的安全属性(极少)class        (可选)id           (通常建议禁用)title️ 注意:id 容易被滥用做锚点注入,很多系统直接禁用class 允许的话最好只允许固定前缀(如 editor-*)二、a 标签允许属性<a href="" t...

Mac 安装 Node.js 指南

方法一:通过官网安装包(最简单,适合初学者)如果你只是想快速安装并开始使用,这是最直接的方法。访问 Node.js 官网。页面会显示两个版本:LTS (Recommended For Most Users):长期支持版,最稳定。建议选这个。Current:最新特性版,包含最新功能但可能不够稳定。下载 .pkg 安装包并运行。按照安装向导点击“下一步”即可完成。方法二:使用 Homebrew 安装(...

Dom\HTML_NO_DEFAULT_NS 的副作用:自动加闭合标签

在使用Dom\HTMLDocument时,Dom\HTML_NO_DEFAULT_NS 将禁止在解析过程中设置元素的命名空间, 此设置是为了与DOMDocument向后兼容而存在的。当使用它时,已知的一个副作用就是:自动加闭合标签例如 </img> 为什么会这样?当你使用:Dom\HTML_NO_DEFAULT_NS文档会变成 无命名空间模式,此时内部更接近 XML...

Laravel 事件和监听器创建

在 Laravel 中,使用 Artisan 命令创建 Events(事件) 和 Listeners(监听器) 是非常高效的。你可以通过以下几种方式来实现:1. 手动创建单个 Event如果你只想创建一个事件类,可以使用 make:event 命令:Bashphp artisan make:event UserRegistered执行后,文件将生成在 app/Even...

自定义域名解析神器 dnsmasq

什么是 dnsmasq?dnsmasq 是一个轻量级、功能强大的网络服务工具,专为小型和中等规模网络设计。它是一个综合的网络基础设施解决方案[1]。dnsmasq 能做什么?功能说明应用场景DNS 转发与缓存将 DNS 查询转发到上游服务器(ISP、Google DNS 等),并在本地缓存结果加快 DNS 查询速度,减少外部 DNS 流量本地 DNS解析本地网络设备的主机名,无需编辑&n...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。