在 Covid-19 疫情持续的情况下,人们出行需要在公共场合戴口罩。 在这里,我们分享一个计算机视觉模型,可以检测该人是否戴口罩。
数据集收集:
在数据集上建立模型,其中有 331 个训练图像和 17 个带有标签掩码的测试图像、以及没有掩码的侧视图像。
数据注释:
图像注释已使用 MakeSense.AI 完成。 这是一个开源网站,可帮助注释图像并根据我们的选择以任何格式下载。 这里的注解有两种方式:
1.在.xml格式中,我们有X-min,X-max,Y-min,Y-max坐标
2.txt 格式包含对象类别、对象坐标、图像宽度、图像高度
数据准备和建模:
由于在这里使用了 2 个不同的模型,因此数据准备以 2 种不同的方式完成。
1. 使用预训练的 SSD Resnet 进行 Tensorflow 对象检测:
必须从 xml 创建 .csv 文件。
importglob#thislibraryisneededtoreadXMLfilesforconvertingitintoCSVimportxml.etree.ElementTreeasETimportshutildefxml_to_csv(data):xml_list=[]forfilesindata:if'.xml'infiles:tree=ET.parse(files)root=tree.getroot()formemberinroot.findall('object'):#print(member)value=(root.find('filename').text,int(root.find('size').find('width').text),int(root.find('size').find('height').text),member.find('name').text,int(member.find('bndbox').find('xmin').text),int(member.find('bndbox').find('ymin').text),int(member.find('bndbox').find('xmax').text),int(member.find('bndbox').find('ymax').text))xml_list.append(value)column_name=['filename','width','height','class','xmin','ymin','xmax','ymax']xml_df=pd.DataFrame(xml_list,columns=column_name)returnxml_df
在此之后,我们需要分别创建训练和测试 tf 记录。
"""Usage:#Fromtensorflow/models/#Createtraindata:pythongenerate_tfrecord.py--csv_input=data/train_labels.csv--output_path=train.record#Createtestdata:pythongenerate_tfrecord.py--csv_input=data/test_labels.csv--output_path=test.record"""from__future__importdivisionfrom__future__importprint_functionfrom__future__importabsolute_importimportosimportioimportpandasaspdimporttensorflowastffromPILimportImageimportsyssys.path.append('../')fromobject_detection.utilsimportdataset_utilfromcollectionsimportnamedtuple,OrderedDict#flags=tf.app.flags#flags.DEFINE_string('csv_input','','/content/Object_Detection/test_labels.csv')#flags.DEFINE_string('output_path','','/content/Object_Detection/Annotations/test.record')#flags.DEFINE_string('image_dir','','/content/Object_Detection/Images/test')#FLAGS=flags.FLAGS#TO-DOreplacethiswithlabelmapdefclass_text_to_int(row_label):ifrow_label=='nomask':return1elifrow_label=='mask':return2defsplit(df,group):data=namedtuple('data',['filename','object'])gb=df.groupby(group)return[data(filename,gb.get_group(x))forfilename,xinzip(gb.groups.keys(),gb.groups)]defcreate_tf_example(group,path):withtf.io.gfile.GFile(os.path.join(path,'{}'.format(group.filename)),'rb')asfid:encoded_jpg=fid.read()encoded_jpg_io=io.BytesIO(encoded_jpg)image=Image.open(encoded_jpg_io)width,height=image.size#changeherebasedonyourimageextensionfilename=group.filename.encode('utf8')image_format=b'jpeg'xmins=[]xmaxs=[]ymins=[]ymaxs=[]classes_text=[]classes=[]forindex,rowingroup.object.iterrows():xmins.append(row['xmin']/width)xmaxs.append(row['xmax']/width)ymins.append(row['ymin']/height)ymaxs.append(row['ymax']/height)classes_text.append(row['class'].encode('utf8'))classes.append(class_text_to_int(row['class']))tf_example=tf.train.Example(features=tf.train.Features(feature={'image/height':dataset_util.int64_feature(height),'image/width':dataset_util.int64_feature(width),'image/filename':dataset_util.bytes_feature(filename),'image/source_id':dataset_util.bytes_feature(filename),'image/encoded':dataset_util.bytes_feature(encoded_jpg),'image/format':dataset_util.bytes_feature(image_format),'image/object/bbox/xmin':dataset_util.float_list_feature(xmins),'image/object/bbox/xmax':dataset_util.float_list_feature(xmaxs),'image/object/bbox/ymin':dataset_util.float_list_feature(ymins),'image/object/bbox/ymax':dataset_util.float_list_feature(ymaxs),'image/object/class/text':dataset_util.bytes_list_feature(classes_text),'image/object/class/label':dataset_util.int64_list_feature(classes),}))returntf_exampledefmain_train():writer=tf.io.TFRecordWriter('/content/FaceMaskDetection/Annotations/train.record')path=os.path.join('/content/FaceMaskDetection/Images/train')examples=pd.read_csv('/content/FaceMaskDetection/train.csv')grouped=split(examples,'filename')forgroupingrouped:tf_example=create_tf_example(group,path)writer.write(tf_example.SerializeToString())writer.close()output_path=os.path.join(os.getcwd(),'/content/FaceMaskDetection/Annotations/train.record')print('SuccessfullycreatedtheTFRecords:{}'.format(output_path))
我们已经对模型进行了 10000 步的训练。 对于最后几个步骤,这里是损失的样子:
从上面我们可以看到总损失太多了,所以我们不期望这个模型能正常工作。对于模型的推断,我们提供了以下要点。
category_index=label_map_util.create_category_index_from_labelmap(files['LABELMAP'])IMAGE_PATH=os.path.join('/content/FaceMaskDetection/Images/train/N47.jpeg')img=cv2.imread(IMAGE_PATH)image_np=np.array(img)input_tensor=tf.convert_to_tensor(np.expand_dims(image_np,0),dtype=tf.float32)detections=detect_fn(input_tensor)num_detections=int(detections.pop('num_detections'))detections={key:value[0,:num_detections].numpy()forkey,valueindetections.items()}detections['num_detections']=num_detections#detection_classesshouldbeints.detections['detection_classes']=detections['detection_classes'].astype(np.int64)label_id_offset=1image_np_with_detections=image_np.copy()viz_utils.visualize_boxes_and_labels_on_image_array(image_np_with_detections,detections['detection_boxes'],detections['detection_classes']+label_id_offset,detections['detection_scores'],category_index,use_normalized_coordinates=True,max_boxes_to_draw=1,min_score_thresh=0.1,agnostic_mode=False)newsize=(300,300,3)plt.figure(figsize=(15,10))#image_np_with_detections=image_np_with_detections.resize(newsize)plt.imshow(cv2.cvtColor(image_np_with_detections,cv2.COLOR_BGR2RGB))plt.show()
让我们检查一下模型的执行效果。
从上面可以清楚地看到这个模型表现得不够好。要么需要训练更多的步骤,要么需要使用更好的模型,但是相对来说,损失并没有减少太多,可能已经达到了饱和点。我们需要使用更好的模型。
2. YoloV5s:
在这里,我们将使用 .txt 文件注释来训练模型。yolo v5 有不同的版本。我们最初使用 Yolo v5s 版本来检查模型的性能。
importyamlwithopen("data.yaml",'r')asstream:num_classes=str(yaml.safe_load(stream)['nc'])fromIPython.core.magicimportregister_line_cell_magic@register_line_cell_magicdefwritetemplate(line,cell):withopen(line,'w')asf:f.write(cell.format(**globals()))%%writetemplate/content/yolov5/models/custom_yolov5s.yaml#parametersnc:2#numberofclasses#CHANGEDHEREdepth_multiple:0.33#modeldepthmultiplewidth_multiple:0.50#layerchannelmultiple#anchorsanchors:-[10,13,16,30,33,23]#P3/8-[30,61,62,45,59,119]#P4/16-[116,90,156,198,373,326]#P5/32#YOLOv5backbonebackbone:#[from,number,module,args][[-1,1,Focus,[64,3]],#0-P1/2[-1,1,Conv,[128,3,2]],#1-P2/4[-1,3,BottleneckCSP,[128]],[-1,1,Conv,[256,3,2]],#3-P3/8[-1,9,BottleneckCSP,[256]],[-1,1,Conv,[512,3,2]],#5-P4/16[-1,9,BottleneckCSP,[512]],[-1,1,Conv,[1024,3,2]],#7-P5/32[-1,1,SPP,[1024,[5,9,13]]],[-1,3,BottleneckCSP,[1024,False]],#9]#YOLOv5headhead:[[-1,1,Conv,[512,1,1]],[-1,1,nn.Upsample,[None,2,'nearest']],[[-1,6],1,Concat,[1]],#catbackboneP4[-1,3,BottleneckCSP,[512,False]],#13[-1,1,Conv,[256,1,1]],[-1,1,nn.Upsample,[None,2,'nearest']],[[-1,4],1,Concat,[1]],#catbackboneP3[-1,3,BottleneckCSP,[256,False]],#17(P3/8-small)[-1,1,Conv,[256,3,2]],[[-1,14],1,Concat,[1]],#catheadP4[-1,3,BottleneckCSP,[512,False]],#20(P4/16-medium)[-1,1,Conv,[512,3,2]],[[-1,10],1,Concat,[1]],#catheadP5[-1,3,BottleneckCSP,[1024,False]],#23(P5/32-large)[[17,20,23],1,Detect,[nc,anchors]],#Detect(P3,P4,P5)]
在训练模型之前,请确保文件结构如下所示:
确保图像的情况下,标签文件名应该完全相同,否则会引发错误。现在我们将以 80 的批量大小训练我们的模型 200 个时期。 对于最后几个时期,这就是我们损失的样子。
让我们检查一下我们的模型的执行效果:
可以看到这个模型表现良好。让我们看看具体是怎样的:
从上面我们可以观察到,模型根本没有过拟合。
计算机视觉技术的示例:
TSINGSEE青犀视频基于多年视频领域的技术经验积累,在人工智能技术+视频领域,也不断研发,将AI检测、智能识别技术融合到各个视频应用场景中,如:安防监控、视频中的人脸检测、人流量统计、危险行为(攀高、摔倒、推搡等)检测识别等。典型的示例如EasyCVR视频融合云服务,具有AI人脸识别、车牌识别、语音对讲、云台控制、声光告警、监控视频分析与数据汇总的能力。