自学内容网 自学内容网

对AVEC2014视频进行Dlib或MTCNN人脸裁剪

预处理:人脸裁剪对齐保存的操作

Dlib

dlib windows包在资源里
其他代码可查看注释帮助理解

import os
import random
import cv2
import dlib
from imutils.face_utils import FaceAligner, rect_to_bb
from tqdm import tqdm  # 引入tqdm库

# 配置路径
dataset_path = 'datasets/AVEC2014'  # 原始数据集路径
output_path = 'datasets/avec14'  # 输出路径
crop_size = 256  # 人脸裁剪后的大小


# 获取人脸对齐器
def get_face(fa, image):
    detector = dlib.get_frontal_face_detector()  # 获取人脸检测器
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)  # 将图像转换为灰度图
    thresh = gray.shape[0] // 4  # 设置阈值
    rects = detector(gray, 2)  # 检测人脸
    face_aligned = None  # 初始化返回的人脸图像
    for rect in rects:
        (x, y, w, h) = rect_to_bb(rect)  # 获取人脸的坐标
        if w > thresh:  # 如果人脸宽度大于阈值,则认为是有效人脸
            face_aligned = fa.align(image, gray, rect)  # 对齐人脸
            break  # 只处理第一张人脸
    return face_aligned


# 处理视频
def process_video(video_path, save_dir, fa):
    cap = cv2.VideoCapture(video_path)  # 打开视频文件
    total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))  # 获取总帧数
    if total_frames < 64:  # 如果视频帧数少于64,跳过该视频
        print(f"Warning: Video '{video_path}' has less than 64 frames. Skipping.")
        cap.release()  # 释放视频文件
        return

    start_frame = random.randint(0, total_frames - 64)  # 随机选择起始帧
    frames = []
    for i in range(start_frame, start_frame + 64):  # 提取连续的64帧
        cap.set(cv2.CAP_PROP_POS_FRAMES, i)  # 设置当前读取的帧数
        ret, frame = cap.read()  # 读取该帧
        if ret:
            frames.append(frame)  # 保存读取到的帧

    cap.release()  # 释放视频文件

    for i, frame in enumerate(tqdm(frames, desc=f"Processing frames from {os.path.basename(video_path)}")):  # 加入进度条
        face_aligned = get_face(fa, frame)  # 对齐每一帧中的人脸
        if face_aligned is not None:
            img_name = f"{i + 1:05d}.jpg"  # 给每一帧命名
            save_path = os.path.join(save_dir, img_name)  # 保存路径
            cv2.imwrite(save_path, face_aligned)  # 保存图像
        else:
            print(f"Face not found in frame {i + 1}")  # 如果没有检测到人脸


# 主函数:处理数据集中的所有视频
def align_dlib():
    predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat")  # 加载预测器
    fa = FaceAligner(predictor, desiredFaceWidth=crop_size)  # 初始化人脸对齐器

    # 遍历主目录(Training、Development、Testing)
    main_dirs = ['Training', 'Development', 'Testing']
    for main_dir in main_dirs:
        main_dir_path = os.path.join(dataset_path, main_dir)
        if not os.path.isdir(main_dir_path):
            print(f"Skipping non-directory: {main_dir_path}")
            continue

        # 遍历每个子目录(Northwind、Freeform 等)
        sub_dirs = os.listdir(main_dir_path)
        for sub_dir in sub_dirs:
            sub_dir_path = os.path.join(main_dir_path, sub_dir)
            if not os.path.isdir(sub_dir_path):
                print(f"Skipping non-directory: {sub_dir_path}")
                continue

            # 遍历视频文件夹中的每个视频文件
            video_files = os.listdir(sub_dir_path)
            for video_file in video_files:
                video_path = os.path.join(sub_dir_path, video_file)

                if not os.path.isfile(video_path):
                    continue

                # 获取视频名称(去掉文件扩展名)
                video_name = os.path.splitext(video_file)[0]

                # 构建保存路径: datasets/avec14/Training/Northwind/236_1_Northwind_video
                save_path = os.path.join(output_path, main_dir, sub_dir, video_name)
                os.makedirs(save_path, exist_ok=True)  # 创建保存文件夹

                print(f"Processing video: {video_path}")
                process_video(video_path, save_path, fa)  # 处理该视频


if __name__ == "__main__":
    align_dlib()  # 调用主函数进行处理

MTCNN

import os
import pandas as pd
import cv2
from tqdm import tqdm
from mtcnn import MTCNN


def get_files(path):
    file_info = os.walk(path)
    file_list = []
    for r, d, f in file_info:
        file_list += f
    return file_list


def get_dirs(path):
    file_info = os.walk(path)
    dirs = []
    for d, r, f in file_info:
        dirs.append(d)
    return dirs[1:]


def generate_label_file():
    print('get label....')
    base_url = './AVEC2014/label/DepressionLabels/'
    file_list = get_files(base_url)
    labels = []
    loader = tqdm(file_list)
    for file in loader:
        label = pd.read_csv(base_url + file, header=None)
        labels.append([file[:file.find('_Depression.csv')], label[0][0]])
        loader.set_description('file:{}'.format(file))
    pd.DataFrame(labels, columns=['file', 'label']).to_csv('./processed/label.csv', index=False)
    return labels


def generate_img(path, v_type, img_path):
    videos = get_files(path)
    loader = tqdm(videos)
    for video in loader:
        name = video[:5]
        save_path = img_path + v_type + '/' + name
        os.makedirs(save_path, exist_ok=True)
        cap = cv2.VideoCapture(path + video)
        n_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
        gap = int(n_frames / 100)
        for i in range(n_frames):
            success, frame = cap.read()
            if success and i % gap == 0:
                cv2.imwrite(save_path + '/{}.jpg'.format(int(i / gap)), frame, [int(cv2.IMWRITE_JPEG_QUALITY), 100])
                loader.set_description("data:{} type:{} video:{} frame:{}".format(path.split('/')[2], v_type, name, i))
        cap.release()


def get_img():
    print('get video frames....')
    train_f = './AVEC2014/train/Freeform/'
    train_n = './AVEC2014/train/Northwind/'
    test_f = './AVEC2014/test/Freeform/'
    test_n = './AVEC2014/test/Northwind/'
    validate_f = './AVEC2014/dev/Freeform/'
    validate_n = './AVEC2014/dev/Northwind/'
    dirs = [train_f, train_n, test_f, test_n, validate_f, validate_n]
    types = ['Freeform', 'Northwind', 'Freeform', 'Northwind', 'Freeform', 'Northwind']
    img_path = ['./img/train/', './img/train/', './img/test/', './img/test/', './img/validate/', './img/validate/']
    os.makedirs('./img/train', exist_ok=True)
    os.makedirs('./img/test', exist_ok=True)
    os.makedirs('./img/validate', exist_ok=True)
    for i in range(6):
        generate_img(dirs[i], types[i], img_path[i])


def get_face():
    print('get frame faces....')
    detector = MTCNN()

    '''
    save_path = ['./processed/train/Freeform/', './processed/train/Northwind/', './processed/test/Freeform/',
                 './processed/test/Northwind/', './processed/validate/Freeform/', './processed/validate/Northwind/']
    paths = ['./img/train/Freeform/', './img/train/Northwind/', './img/test/Freeform/', './img/test/Northwind/',
             './img/validate/Freeform/', './img/validate/Northwind/']

    save_path = ['./processed/validate/Freeform/', './processed/validate/Northwind/']
    paths = ['./img/validate/Freeform/', './img/validate/Northwind/']
    '''
    save_path = [ './processed/validate/Northwind/']
    paths = ['./img/validate/Northwind/']
    for index, path in enumerate(paths):
        dirs = get_dirs(path)
        loader = tqdm(dirs)
        for d in loader:
            os.makedirs(save_path[index] + d.split('/')[-1], exist_ok=True)
            files = get_files(d)
            for file in files:
                img_path = d + '/' + file
                s_path = save_path[index] + d.split('/')[-1] + '/' + file
                img = cv2.cvtColor(cv2.imread(img_path), cv2.COLOR_BGR2RGB)
                info = detector.detect_faces(img)
                if (len(info) > 0):
                    x, y, width, height = info[0]['box']
                    confidence = info[0]['confidence']
                    b, g, r = cv2.split(img)
                    img = cv2.merge([r, g, b])
                    img = img[y:y + height, x:x + width, :]
                    cv2.imwrite(s_path, img, [int(cv2.IMWRITE_JPEG_QUALITY), 100])
                    loader.set_description('confidence:{:4f} img:{}'.format(confidence, img_path))


if __name__ == '__main__':
  
    os.makedirs('./img', exist_ok=True)
    os.makedirs('./processed', exist_ok=True)
    os.makedirs('./processed/train', exist_ok=True)
    os.makedirs('./processed/test', exist_ok=True)
    os.makedirs('./processed/validate', exist_ok=True)
    label = generate_label_file()
    get_img()

    get_face()


原文地址:https://blog.csdn.net/weixin_44194001/article/details/143891731

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!