口罩佩戴检测(一):数据的获取与预处理

技术凯 2021-01-08 01:26:48 8857

  本篇文章开始,将为大家介绍口罩佩戴检测的实现方法,识别算法使用SVM算法,编程语言使用matlab。以下是本系列文章的目录安排。

一、问题的提出

  2020年2月份中国开始爆发了新冠疫情,所有公共场合都要求所有人员必须佩戴口罩。但是在人群众多的场合,随时监督人群中每个人的口罩佩戴情况,无疑对在场工作人员的工作负荷是一个很大的挑战。所以我们想通过自己在模式识别课程上所学的知识,来建立一个解决这个问题的基本框架—通过建立分类器来识别人群中每个人是否佩戴口罩,甚至是否正确佩戴口罩。

二、数据获取和预处理

  在武汉大学数据共享网站上分别下载了10000张佩戴口罩和10000张没有佩戴口罩的照片作为训练集,在各类样本中随机选取2000张佩戴口罩的人像照片和没有佩戴口罩的人像作为测试集。然后将这20000张照片转换成灰度图像,然后将照片的灰度值作为矩阵中元素的值,通过灰度图像得到100*100的矩阵,然后再转换为10000维的列向量。作为样本向量。
  数据获取和预处理的实现:

2.1导入数据

1、将收集到的数据集由图片格式转换成matlab可处理的数据格式。(程序已封装成函数datas_import())

% 此函数实现的功能是将图像文件批量转换成数组并导入matlab可以处理的.mat文件
function datasImport
    clear
    % 分别导入10000张戴口罩和不戴口罩的图像数据
    datas_import('masked_clean',10000,'face_dataset',10000,0.9)
end

函数的第一个参数是正样本(戴口罩)图片的路径
第二个参数是导入正样本的数量
第三个参数是负样本(不戴口罩)图片的路径
第四个参数是导入负样本的数量
第五个样本是划分样本训练数据和测试数据的划分比率
  本次实例中,将导入正负类样本各10000张进行算法的学习与测试,学习数据和测试数据划分比率为0.9,即最终一共有18000张训练样本,2000张测试样本。
2、datas_import()函数的具体定义

% 数据集生成器,positive_path是正样本(戴口罩)图片路径
% negative_path是负样本(不戴口罩)图片路径
% ratio是训练集测试集划分比率,若ratio=0.9,则90%的训练集,10%的测试集
% positive_num和negative_num决定导入多少图像文件
function datas_import(positive_path,positive_num,negative_path,negative_num,ratio)
    fprintf('开始导入未戴口罩的数据\n');
    negative_datas=imageDatas_import(negative_path,negative_num);
    negative_num=size(negative_datas,1);%确定负类样本数量
    test_index=randperm(negative_num,round(negative_num*(1-ratio)));
    % 确定负类测试样本
    test_negative=negative_datas(test_index,:,:);
    % 确定负类训练样本
    train_negative=negative_datas;
    train_negative(test_index,:,:)=[];
    save('dataset.mat','test_negative','train_negative','negative_datas');
    fprintf('开始导入戴口罩的数据\n');
    positive_datas=imageDatas_import(positive_path,positive_num);
    positive_num=size(positive_datas,1);%确定负类样本数量
    test_index=randperm(positive_num,round(positive_num*0.1));
    % 确定正类测试样本
    test_positive=positive_datas(test_index,:,:);
    % 确定正类训练样本
    train_positive=positive_datas;
    train_positive(test_index,:,:)=[];
    save('dataset.mat','test_positive','train_positive','positive_datas','-append');
end

第一步:首先导入一定数量的负样本(已封装成函数imageDatas_import())
第二步:使用randperm(n,x)函数从n个样本中随机抽取x各样本,这x各样本作为负类测试集
第三步:将a-x个样本作为负类的训练集。
第四步:将训练集和测试集保存至dataset.mat文件中,供程序的下一步操作
正类样本的导入同以上四个步骤。
3、imageDatas_import()函数具体定义

% 导入图象数据,转换成灰度图,并统一尺寸
function images=imageDatas_import(file_path,import_num)
    import_index=1;
    is_import_finished=0;
    file_list=dir(file_path);
    file_num=length(file_list);
    if file_num==0
        fprintf('文件夹为空\n');
    else
        fprintf('找到%d个文件\n',file_num);
        for i=1:file_num%list中的前两个数据分别代表
            % 如果需要的文件数量已经导够,则停止导入
            if is_import_finished==1
                fprintf('%d个图像文件已经导入完成\n',import_index);
                break;
            end
            file_name=file_list(i).name;
            % 跳过"."和".."路径,从该目录下的文件开始搜索
            if strcmp(file_name,'.')==1 || strcmp(file_name,'..')==1
                continue;
            end
            image_list=dir(fullfile(file_path,file_name,'*.jpg'));%列出path路径下所有后缀为.jpg的文件
            image_num=length(image_list);%获取图片数量
            if image_num==0
                fprintf('在第%d个文件夹中未找到任何图像\n',i-2);
            else
                fprintf('在第%d个文件夹中已找到%d张图像\n',i-2,image_num);
                for j=1:image_num
                    image_name=image_list(j).name;%获取每一张图片名称
                    image=imread(fullfile(file_path,file_name,image_name));
                    image=imresize(image,[100,100]);%统一图片尺寸
                    image=rgb2gray(image);%转为灰度图
                    images(import_index,:,:)=image;
                    if import_index==import_num%如果图片导够了
                        is_import_finished=1;
                        break;
                    end
                    import_index=import_index+1;
                end
            end
        end
    end
end

  该函数作用是从指定路径中导入指定数量的图片,并将图片尺寸统一为100X100的大小,然后转换为灰度图的数据矩阵,最终转换成matlab可以处理的数据矩阵。
  综上所述,数据集由图片转换成100*100维的数据矩阵(即10000维的数据样本),并保存到dataset.mat文件中。
数据导入部分完整代码:

% 此函数实现的功能是将图像文件批量转换成数组并导入matlab可以处理的.mat文件
function datasImport
    clear
    % 分别导入10000张戴口罩和不戴口罩的图像数据
    datas_import('masked_clean',10000,'face_dataset',10000,0.9)
end
% 数据集生成器,positive_path是正样本(戴口罩)图片路径
% negative_path是负样本(不戴口罩)图片路径
% ratio是训练集测试集划分比率,若ratio=0.9,则90%的训练集,10%的测试集
% positive_num和negative_num决定导入多少图像文件
function datas_import(positive_path,positive_num,negative_path,negative_num,ratio)
    fprintf('开始导入未戴口罩的数据\n');
    negative_datas=imageDatas_import(negative_path,negative_num);
    negative_num=size(negative_datas,1);%确定负类样本数量
    test_index=randperm(negative_num,round(negative_num*(1-ratio)));
    % 确定负类测试样本
    test_negative=negative_datas(test_index,:,:);
    % 确定负类训练样本
    train_negative=negative_datas;
    train_negative(test_index,:,:)=[];
    save('dataset.mat','test_negative','train_negative','negative_datas');
    fprintf('开始导入戴口罩的数据\n');
    positive_datas=imageDatas_import(positive_path,positive_num);
    positive_num=size(positive_datas,1);%确定负类样本数量
    test_index=randperm(positive_num,round(positive_num*0.1));
    % 确定正类测试样本
    test_positive=positive_datas(test_index,:,:);
    % 确定正类训练样本
    train_positive=positive_datas;
    train_positive(test_index,:,:)=[];
    save('dataset.mat','test_positive','train_positive','positive_datas','-append');
end
% 导入图象数据,转换成灰度图,并统一尺寸
function images=imageDatas_import(file_path,import_num)
    import_index=1;
    is_import_finished=0;
    file_list=dir(file_path);
    file_num=length(file_list);
    if file_num==0
        fprintf('文件夹为空\n');
    else
        fprintf('找到%d个文件\n',file_num);
        for i=1:file_num%list中的前两个数据分别代表
            % 如果需要的文件数量已经导够,则停止导入
            if is_import_finished==1
                fprintf('%d个图像文件已经导入完成\n',import_index);
                break;
            end
            file_name=file_list(i).name;
            % 跳过"."和".."路径,从该目录下的文件开始搜索
            if strcmp(file_name,'.')==1 || strcmp(file_name,'..')==1
                continue;
            end
            image_list=dir(fullfile(file_path,file_name,'*.jpg'));%列出path路径下所有后缀为.jpg的文件
            image_num=length(image_list);%获取图片数量
            if image_num==0
                fprintf('在第%d个文件夹中未找到任何图像\n',i-2);
            else
                fprintf('在第%d个文件夹中已找到%d张图像\n',i-2,image_num);
                for j=1:image_num
                    image_name=image_list(j).name;%获取每一张图片名称
                    image=imread(fullfile(file_path,file_name,image_name));
                    image=imresize(image,[100,100]);%统一图片尺寸
                    image=rgb2gray(image);%转为灰度图
                    images(import_index,:,:)=image;
                    if import_index==import_num%如果图片导够了
                        is_import_finished=1;
                        break;
                    end
                    import_index=import_index+1;
                end
            end
        end
    end
end
2.2数据处理

  仅仅将图像转换为数据矩阵是不够的,还需要进一步对数据进行处理,以作为我们分类器的输入。
1、制作测试数据,将100100的样本转换为100001的样本。因为我们的分类器输入要求数据是dim1的形式。一共有2000个测试样本,最终测试样本数据大小为100002000

clear
load('dataset.mat')
test_num_n=size(test_negative,1);% 测试数据数量 负样本
test_num_p=size(test_positive,1);% 测试数据数量,正样本
train_num_n=size(train_negative,1);% 训练数据数量,负样本
train_num_p=size(train_positive,1);% 训练数据数量,正样本
dim=size(test_negative,2)*size(test_negative,3);
% 制作测试数据
test1=reshape(test_negative,test_num_n,dim);
test2=reshape(test_positive,test_num_p,dim);
Testing=[test1;test2];
Testing=Testing';

2、制作测试数据标签,负类(不戴口罩)为0,正类为1。

% 制作测试数据标签
Testing_label1=zeros(1,test_num_n);
Testing_label2=ones(1,test_num_p);
Testing_label=[Testing_label1,Testing_label2];

3、训练数据及标签的制作同以上2个步骤

% 训练数据
train1=reshape(train_negative,train_num_n,dim);
train2=reshape(train_positive,train_num_p,dim);
Training=[train1;train2];
Training=Training';
% 制作训练数据标签
Training_label1=zeros(1,train_num_n);
Training_label2=ones(1,train_num_p);
Training_label=[Training_label1,Training_label2];

4、将数据类型转换成适合分类器处理的double型并保存。

% 类型转换并保存处理后的数据
Training=double(Training);
Training_label=double(Training_label);
Testing=double(Testing);
Testing_label=double(Testing_label);
save('dataset_processed.mat','Training','Training_label','Testing','Testing_label');

数据处理部分完整代码如下:

clear
load('dataset.mat')
test_num_n=size(test_negative,1);% 测试数据数量 负样本
test_num_p=size(test_positive,1);% 测试数据数量,正样本
train_num_n=size(train_negative,1);% 训练数据数量,负样本
train_num_p=size(train_positive,1);% 训练数据数量,正样本
dim=size(test_negative,2)*size(test_negative,3);
% 制作测试数据
test1=reshape(test_negative,test_num_n,dim);
test2=reshape(test_positive,test_num_p,dim);
Testing=[test1;test2];
Testing=Testing';
% 制作测试数据标签
Testing_label1=zeros(1,test_num_n);
Testing_label2=ones(1,test_num_p);
Testing_label=[Testing_label1,Testing_label2];
% 训练数据
train1=reshape(train_negative,train_num_n,dim);
train2=reshape(train_positive,train_num_p,dim);
Training=[train1;train2];
Training=Training';
% 制作训练数据标签
Training_label1=zeros(1,train_num_n);
Training_label2=ones(1,train_num_p);
Training_label=[Training_label1,Training_label2];
% 类型转换并保存处理后的数据
Training=double(Training);
Training_label=double(Training_label);
Testing=double(Testing);
Testing_label=double(Testing_label);
save('dataset_processed.mat','Training','Training_label','Testing','Testing_label');

  综上,数据经二次处理后,统一转换成dim*n的格式,并附有标签。在经过类型转换后保存至dataset_processed.mat文件中。

声明:本文内容由易百纳平台入驻作者撰写,文章观点仅代表作者本人,不代表易百纳立场。如有内容侵权或者其他问题,请联系本站进行删除。
红包 84 8 评论 打赏
评论
0个
内容存在敏感词
手气红包
    易百纳技术社区暂无数据
相关专栏
置顶时间设置
结束时间
删除原因
  • 广告/SPAM
  • 恶意灌水
  • 违规内容
  • 文不对题
  • 重复发帖
打赏作者
易百纳技术社区
技术凯
您的支持将鼓励我继续创作!
打赏金额:
¥1易百纳技术社区
¥5易百纳技术社区
¥10易百纳技术社区
¥50易百纳技术社区
¥100易百纳技术社区
支付方式:
微信支付
支付宝支付
易百纳技术社区微信支付
易百纳技术社区
打赏成功!

感谢您的打赏,如若您也想被打赏,可前往 发表专栏 哦~

举报反馈

举报类型

  • 内容涉黄/赌/毒
  • 内容侵权/抄袭
  • 政治相关
  • 涉嫌广告
  • 侮辱谩骂
  • 其他

详细说明

审核成功

发布时间设置
发布时间:
是否关联周任务-专栏模块

审核失败

失败原因
备注
拼手气红包 红包规则
祝福语
恭喜发财,大吉大利!
红包金额
红包最小金额不能低于5元
红包数量
红包数量范围10~50个
余额支付
当前余额:
可前往问答、专栏板块获取收益 去获取
取 消 确 定

小包子的红包

恭喜发财,大吉大利

已领取20/40,共1.6元 红包规则

    易百纳技术社区