这是之前网上举办的口罩佩戴公开赛的数据集,我周末正好有时间就想着拿来做一个口罩佩戴识别系统,跟我前面的一篇博文相互照应。链接在下面,感兴趣可以看下:
这里做的不是目标检测,而是图像识别任务。
效果如下:

网上公开赛的数据集下载解压缩后如下:

sample_submit.csv是提交样例格式,这里可以直接删掉。
进入train目录,如下:

可见:大赛给定的数据集一共是划分了三个类别,从上到下分别表示:未正确佩戴口罩、佩戴口罩、未佩戴口罩。
我自己开发不打算分成三个类别,这里将未正确佩戴口罩划归到佩戴口罩类别下,当然了这个本身无所谓的,我只是个人做法而已。
首先解析数据集:
- def parseData2H5():
- '''
- 加载本地数据集创建H5数据集
- '''
- X_train, y_train =[], []
- X_test, y_test =[], []
- picDir='data/train/'
- for one_label in os.listdir(picDir):
- for one_pic in os.listdir(picDir+one_label+'/'):
- if one_pic.endswith("jpg") or one_pic.endswith("png") or one_pic.endswith("jpeg"):
- try:
- one_path = picDir+one_label+'/' + one_pic
- print("one_path: ", one_path)
- #图片
- one_img = cv2.imread(one_path)
- one_img = cv2.resize(one_img,(100,100))
- one_img = one_img.transpose((2,0,1))
- #标签
- one_pic_classes = one_label
- one_y = getY(one_pic_classes)
- #整合
- X_train.append(one_img)
- y_train.append(one_y)
- except Exception as e:
- print("train Exception: ", e)
- X_train = np.array(X_train)
- picDir='data/test/'
- for one_label in os.listdir(picDir):
- for one_pic in os.listdir(picDir+one_label+'/'):
- if one_pic.endswith("jpg") or one_pic.endswith("png") or one_pic.endswith("jpeg"):
- try:
- one_path = picDir+one_label+'/' + one_pic
- print("one_path: ", one_path)
- #图片
- one_img = cv2.imread(one_path)
- one_img = cv2.resize(one_img,(100,100))
- one_img = one_img.transpose((2,0,1))
- #标签
- one_pic_classes = one_label
- one_y = getY(one_pic_classes)
- #整合
- X_test.append(one_img)
- y_test.append(one_y)
- except Exception as e:
- print("test Exception: ", e)
- X_test = np.array(X_test)
- f = h5py.File("dataset.h5")
- f['X_train'] = X_train
- f['X_test'] = X_test
- f['y_train'] = y_train
- f['y_test'] = y_test
- print("y_train_0: ", y_train[0])
- print("y_test_0: ", y_test[0])
- f.close()
之后构建模型:
- def initModel(h=224, w=224, way=3):
- """
- 构建模型
- """
- model = Sequential()
- input_shape = (h, w, way)
- model.add(Conv2D(64, (3, 3), input_shape=input_shape))
- model.add(Activation("relu"))
- model.add(Dropout(0.3))
- model.add(Conv2D(64, (3, 3)))
- model.add(Activation("relu"))
- model.add(MaxPooling2D(pool_size=(2, 2)))
- model.add(Flatten())
- model.add(Dense(1024))
- model.add(Activation("relu"))
- model.add(Dropout(0.3))
- model.add(Dense(numbers))
- model.add(Activation("sigmoid"))
- lrate = 0.01
- decay = lrate / 100
- sgd = SGD(lr=lrate, momentum=0.9, decay=decay, nesterov=False)
- model.compile(loss="binary_crossentropy", optimizer=sgd, metrics=["accuracy"])
- print(model.summary())
- return model
训练模型就是正常的流程了,这里就不在介绍了,在我之前的文章里面有很多图像识别的项目,这里就不再赘述细节了。训练过程可视化如下:

这里开发了批量测试函数用于测试整体的识别精度:
- def batchTest(dataDir="data/test/"):
- '''
- 测试集测试
- '''
- count_dict={}
- for one_label in os.listdir(dataDir):
- print("one_label: ", one_label)
- count_dict[one_label]={}
- count_dict[one_label]["right"]=0
- count_dict[one_label]["wrong"]=0
- oneDir=dataDir+one_label+"/"
- for one_pic in os.listdir(oneDir):
- one_path=oneDir+one_pic
- one_pred,one_proba=singleTest(image_path=one_path)
- if one_pred==one_label:
- count_dict[one_label]["right"]+=1
- else:
- count_dict[one_label]["wrong"]+=1
- print("count_dict: ", count_dict)
- with open("count_dict.json","w") as f:
- f.write(json.dumps(count_dict))
- acc_dict={}
- for one_label in count_dict:
- one_right,one_wrong=count_dict[one_label]["right"],count_dict[one_label]["wrong"]
- one_acc=one_right/(one_right+one_wrong)
- print("one_label: ", one_label)
- print("one_acc: ", one_acc)
- acc_dict[one_label]=one_acc
- print("acc_dict: ", acc_dict)
感兴趣可以直接使用,也可以基于自己的个性化应用进行改造。