使用Python+OpenCV+Tensorflow+Flask实现检测X光中的新冠病毒
原始胸部X光图像(A),逆时针旋转45度后图像(B),顺时针旋转45度后图像,水平和垂直平移20%后图像(D),放大10%后图像(E)。使用TS/Keras图像预处理库(ImageDataGenerator),可以更改多个图像参数,例如:trainAug = ImageDataGenerator( rotation_range=15, width_shift_range=0.2, height_shift_range=0.2, rescale=1./255, shear_range=0.2, zoom_range=0.2, horizontal_flip=True, fill_mode='nearest')一开始,仅应用图像最大旋转15度来评估结果。trainAug = ImageDataGenerator(rotation_range=ROTATION_DEG, fill_mode="nearest")此时,我们已经定义了模型和数据,并准备好进行编译和训练。模型构建与训练编译允许我们给模型添加额外的特性,比如loss函数、优化器和度量。对于网络训练,我们使用损失函数来计算网络预测值与训练数据实际值之间的差异,伴随着优化器算法(如Adam)对网络中的权重进行更改,这些超参数有助于网络训练的收敛,使损失值尽可能接近于零。我们还指定了优化器(lr)的学习率,在这种情况下,lr被定义为1e-3。如果在训练过程中注意到“跳跃”的增加,即模型不能收敛,则应降低学习率,以达到最小值。opt = Adam(lr=INIT_LR, decay=INIT_LR / EPOCHS)model.compile(loss="binary_crossentropy", optimizer=opt, metrics=["accuracy"])让我们来训练模型:H = model.fit( trainAug.flow(trainX, trainY, batch_size=BS), steps_per_epoch=len(trainX) // BS, validation_data=(testX, testY), validation_steps=len(testX) // BS, epochs=EPOCHS)
结果看起来已经相当有趣了,验证数据的精度达到了92%!绘制精度图表:
评估训练模型:
看看混淆矩阵:[[27 0] [ 4 23]]acc: 0.9259sensitivity: 1.0000specificity: 0.8519从用最初选择的超参数训练的模型中,我们得到:100%的sensitivity(敏感度),也就是说,对于COVID-19阳性(即真正例)的患者,我们可以100%准确地将其识别为“COVID-19阳性”。85%的specificity(特异性)意味着在没有COVID-19(即真反例)的患者中,我们只能85%准确地将其识别为“COVID-19阴性”。结果并不令人满意,因为15%没有Covid的患者会被误诊。我们先对模型进行微调,更改一些超参数:因此,我们有:INIT_LR = 0.0001 # 曾经是 1e-3 EPOCHS = 20 # 曾经是 10 BS = 16 # 曾经是 8 NODES_DENSE0 = 128 # 曾经是 64DROPOUT = 0.5 MAXPOOL_SIZE = (2, 2) # 曾经是 (4, 4)ROTATION_DEG = 15 SPLIT = 0.2结果
precision recall f1-score support covid 0.93 1.00 0.96 27 normal 1.00 0.93 0.96 27 accuracy 0.96 54 macro avg 0.97 0.96 0.96 54weighted avg 0.97 0.96 0.96 54以及混淆矩阵:[[27 0] [ 2 25]]acc: 0.9630sensitivity: 1.0000specificity: 0.9259结果好多了!现在具有93%的特异性,这意味着在没有COVID-19(即真反例)的患者中,在93%到100%的范围内我们可以准确地将他们识别为“COVID-19阴性”。目前看来,这个结果很有希望。让我们保存这个模型,在那些没有经过训练的图像上测试(Covid-19的8个图像和从输入数据集中随机选择的20个图像)。model.save("../model/covid_normal_model.h5")在真实图像中测试模型(验证)首先,让我们检索模型并显示最终的体系结构,以检查一切是否正常:new_model = load_model('../model/covid_normal_model.h5')# 展示模型架构new_model.summary()
这个模型看起来不错,是VGG16的16层结构。请注意,可训练参数为590210,这是最后两层的总和,它们被添加到参数为14.7M的预训练模型中。让我们验证测试数据集中加载的模型:[INFO] evaluating network... precision recall f1-score support covid 0.93 1.00 0.96 27 normal 1.00 0.93 0.96 27 accuracy 0.96 54 macro avg 0.97 0.96 0.96 54weighted avg 0.97 0.96 0.96 54很好,我们得到了与之前相同的结果,这意味着训练的模型被正确地保存和加载。现在让我们用之前保存的8个Covid图像验证模型,为此,我们创建了另外一个函数,它是为单个图像测试开发的def test_rx_image_for_Covid19(imagePath): img = cv2.imread(imagePath) img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) img = cv2.resize(img, (224, 224)) img = np.expand_dims(img, axis=0) img = np.array(img) / 255.0 pred = new_model.predict(img) pred_neg = round(pred[0][1]*100) pred_pos = round(pred[0][0]*100) print(' X-Ray Covid-19 Detection using AI - MJRovai') print(' [WARNING] - Only for didactic purposes') if np.argmax(pred, axis=1)[0] == 1: plt.title('Prediction: [NEGATIVE] with prob: {}% No Covid-19'.format( pred_neg), fontsize=12) else: plt.title('Prediction: [POSITIVE] with prob: {}% Pneumonia by Covid-19 Detected'.format( pred_pos), fontsize=12) img_out = plt.imread(imagePath) plt.imshow(img_out) plt.savefig('../Image_Prediction/Image_Prediction.png') return pred_pos在Notebook上,此函数将显示以下结果:
通过更改其余7个图像的imagePath值,我们获得以下结果:所有图像均呈阳性,确认100%灵敏度。
现在让我们测试20个单独的图像,以验证标记为NORMAL的有效性。Notebook上的第一个应该是:
一个接一个的测试可以确认预测,但是由于我们有更多的图像,让我们使用另一个函数来测试一组图像,一次完成:test_rx_image_for_Covid19_batch (img_lst) 。批处理测试图像让我们创建包含在验证文件夹中的图像列表:validation_path = '../dataset_validation'normal_val_images = list(paths.list_images( f"{validation_path}/normal_validation"))non_covid_pneumonia_validation_images = list(paths.list_images( f"{validation_path}/non_covid_pneumonia_validation"))covid_val_images = list(paths.list_images( f"{validation_path}/covid_validation"))test_rx_image_for_Covid19_batch (img_lst) 函数如下:def test_rx_image_for_Covid19_batch(img_lst): neg_cnt = 0 pos_cnt = 0 predictions_score = [] for img in img_lst: pred, neg_cnt, pos_cnt = test_rx_image_for_Covid19_2(img, neg_cnt, pos_cnt) predictions_score.append(pred) print ('{} positive detected in a total of {} images'.format(pos_cnt, (pos_cnt+neg_cnt))) return predictions_score, neg_cnt, pos_cnt将该函数应用于我们先前分离的20幅图像:img_lst = normal_val_imagesnormal_predictions_score, normal_neg_cnt, normal_pos_cnt = test_rx_image_for_Covid19_batch(img_lst)normal_predictions_score我们观察到,所有20人被诊断为阴性,得分如下(记住,接近“1”代表“阳性”):0.25851375, 0.025379542, 0.005824779, 0.0047603976, 0.042225637, 0.025087152, 0.035508618, 0.009078974, 0.014746706, 0.06489486, 0.003134642, 0.004970203, 0.15801577, 0.006775451, 0.0032735346, 0.007105667, 0.001369465, 0.005155371, 0.029973848, 0.014993184只有2例图像的评估(1-准确度)低于90%(0.26和0.16)。请记住,输入数据集/input/20_Chest_Xray/有两个文件夹,/train和/test,只有/train中的一部分图像用于训练,并且模型从未看到测试图像:input - |_ 10_Covid_Imagens _ | |_ metadata.csv | |_ images [used train model 1] |_ 20_Chest_Xray - |_ test _ |_ NORMAL |_ PNEUMONIA |_ train _ |_ NORMAL [used train model 1] |_ PNEUMONIA然后,我们可以利用这个文件夹测试所有图像。首先,我们创建了图像列表:validation_path = '../input/20_Chest_Xray/test'normal_test_val_images = list(paths.list_images(f"{validation_path}/NORMAL"))print("Normal Xray Images: ", len(normal_test_val_images))pneumo_test_val_images = list(paths.list_images(f"{validation_path}/PNEUMONIA"))print("Pneumo Xray Images: ", len(pneumo_test_val_images))我们观察了234张诊断为正常的“未公开”图片(还有390张不是由Covid-19引起的肺炎)。应用批处理函数,我们观察到24幅图像出现假阳性(约10%)。让我们看看模型输出值是如何分布的,记住函数返回的值计算如下:pred = new_model.predict(image)pred_pos = round(pred[0][0] * 100)我们观察到,预测精度的平均值为0.15,并且非常集中于接近于零的值(中值仅为0.043),有趣的是,大多数误报率接近0.5,少数异常值高于0.6。
除了改进模型外,研究产生假阳性的图像也是很有意义的。测试不是由Covid引起的肺炎图像由于输入数据集也有肺炎患者的X光图像,但不是由Covid引起的,所以让我们应用模型1(Covid/Normal)来查看结果是什么:
结果非常糟糕,在390张图片中,185张有假阳性,而观察结果的分布,发现有一个峰值接近80%,也就是说,这是非常错误的!回顾这一结果在技术上并不令人惊讶,因为该模型没有经过普通肺炎患者图像的训练。不管怎样,这是一个大问题,因为我认为专家可以用肉眼区分病人是否患有肺炎,然而也许更难区分这种肺炎是由Covid-19(SARS-CoV-2)、任何其他病毒,甚至是细菌引起的。将Covid-19引起的肺炎患者与其他类型的病毒或细菌区分开来的模型是更有用,为此,另一个模型将被训练,现在我们有感染Covid-19的病人和感染肺炎但不是由Covid-19病毒引起的病人的图像。第3部分-模型2-Covid/普通肺炎数据准备从我的GitHub下载Notebook放入subdirectory /notebooks目录:https://github.com/Mjrovai/covid19Xray/blob/master/10_X-Ray_Covid_development/notebooks/20_Xray_Pneumo_Covid19_Model_2_Training_Tests.ipynb。导入使用的库并运行。模型2中使用的Covid图像数据集与模型1中使用的相同,只是现在它存储在不同的文件夹中。dataset_path = '../20_dataset'肺炎图像将从文件夹/input/20_Chest_Xray/train/PNEUMONIA/下载并存储在/20_dataset/pneumo/中。使用的函数与之前相同:input_dataset_path = '../input/20_Chest_Xray/train/PNEUMONIA'output_dataset_path = '../20_dataset/pneumo'img_num_select = len(xray_cv_train) # 样本数量与Covid数据相同这样,我们调用可视化支持函数,检查得到的结果:pneumo_images = list(paths.list_images(f"{dataset_path}/pneumo"))covid_images = list(paths.list_images(f"{dataset_path}/covid"))plots_from_files(covid_images, rows=10, maintitle="Covid-19 X-ray images")
plots_from_files(pneumo_images, rows=10, maintitle="Pneumony X-ray images"
最新活动更多
-
11月28日立即报名>>> 2024工程师系列—工业电子技术在线会议
-
12月19日立即报名>> 【线下会议】OFweek 2024(第九届)物联网产业大会
-
即日-12.26火热报名中>> OFweek2024中国智造CIO在线峰会
-
即日-2025.8.1立即下载>> 《2024智能制造产业高端化、智能化、绿色化发展蓝皮书》
-
精彩回顾立即查看>> 2024 智能家居出海论坛
-
精彩回顾立即查看>> 【在线会议】多物理场仿真助跑新能源汽车
推荐专题
发表评论
请输入评论内容...
请输入评论/评论长度6~500个字
暂无评论
暂无评论