本文主要介绍如何使用python的TensorFlow2.0深度学习框架搭建一个:岩石样本的智能识别系统,如果有毕业设计或者课程设计需求的同学可以参考本文。本项目来自于第九届“泰迪杯”数据挖掘挑战赛的B题:岩石样本的智能识别。
博主也参考过语音识别系统相关模型的文章,但大多是理论大于方法。很多同学肯定对原理不需要过多了解,只需要搭建出一个可视化系统即可。
也正是因为我发现网上大多的帖子只是针对原理进行介绍,功能实现的相对很少。
如果您有以上想法,那就找对地方了!
不多废话,直接进入正题!
在油气勘探中,岩石样本识别是一项即基础又重要的环节;在矿产资源勘探中,尤其是
在固体金属矿产资源勘探中,岩石样本识别同样发挥着不可估量的作用;岩石样本的识别与
分类对于地质分析极为重要。目前岩石样本识别的方法主要有重磁、测井、地震、遥感、电
磁、地球化学、手标本及薄片分析方法等方法,而采用图像深度学习的方法建立岩石样本自 动识别分类模型是一条新的途径。
现有样本数据是采用工业相机在录井现场对岩屑和岩心样品进行拍照,分别在暗箱内拍 摄白光和荧光两种相片,如图 1 和图 2
所示。白光灯下拍摄的相片是用于提取颜色、纹理、 粒度等特征识别岩性,荧光灯下拍摄的相片是用于识别含油气性(石油在紫外线照射下具有
的发光特征,其中的绿色和黄色部分是含油的,见图 2)
本赛题期待参赛者能够通过图像处理技术和深度学习算法,设计出有效的模型识别出岩 石样本的岩性类别及含油气情况,实现岩石样本智能识别分类。
数据集 rock 中,“白光/荧光”标签为“1”的数据是相同白光环境下拍摄的岩石样本
图像数据,“白光/荧光”标签为“2”的数据是相同荧光环境下拍摄的岩石样本图像数据, 请利用数据集 rock 的数据完成以下问题。
1、构建岩石样本岩性智能识别模型。请设计合适的机器学习或深度学习算法,针对数 据集 rock 实现岩石样本岩性智能识别与分类。
2、计算岩石含油面积百分含量。石油在紫外线照射下具有发光特征,即荧光灯下拍摄 的相片中绿色或黄色部分是含油的,请设计合适的算法计算岩石的含油面积百分含量(绿色 和黄色部分的面积占总岩石面积的百分比)。
本赛题的数据总共由两部分组成。
(1) 数据集 rock:包含白光和荧光下拍摄的图像数据,图像名称为“X-Y.bmp”或 “X-Y.jpg”。
X 表示样本编号,编号相同表示为同一个岩石样本拍摄的图像,其中编号在 1~ 321之间的为“.bmp”格式的图像数据,编号在 322~350 之间的为“.jpg”格式的图像数 据(见图 3);
Y表示拍摄图像时的光照环境(1 表示白光,2 表示荧光)。
(2) 标签表 rock_label.csv:此表格的内容为数据集 rock中每个样本的岩性类别(见 图 4)。
本项目使用的是anaconda的jupyter notebook编译环境,如不清楚如何使用的同学可以参考csdn上其他博主的基础教程,这里就不进行赘述。
- TensorFlow-GPU,版本:2.0及以上
- sklearn
- pandas
- opencv-python
#数据预处理
#图片加载
# 读取图片+数据处理函数
def read_img(path,label_pd):
print("数据集地址:"+path)
imgs = []
labels = []
for root, dirs, files in os.walk(path):
for file in tqdm(files):
# print(path+'/'+file+'/'+folder)
# 读取的图片
# img = io.imread(os.path.join(root,file))
img = cv2.imread(os.path.join(root, file))
# skimage.transform.resize(image, output_shape)改变图片的尺寸
img = cv2.resize(img, (w, h))
# 将读取的图片数据加载到imgs[]列表中
imgs.append(img)
labels = list(label_pd['label'])
# 将读取的图片和labels信息,转化为numpy结构的ndarr(N维数组对象(矩阵))数据信息
return imgs,labels
# 调用读取图片的函数,得到图片和labels的数据集
data1, label1 = read_img(train_img_url,label_data)
可以看到图像数据是非常少的,如果以此作为分类效果肯定不行。因此我们对图像数据进行图像增强操作。主要是对图像进行:翻转、旋转、裁剪。代码如下:
# 将图像进行随机翻转,裁剪
def img_cut(imgs,label):
imgs_out = []
label_out = []
for i in tqdm(range(len(imgs))):
# 添加原图
imgs_out.append(imgs[i])
label_out.append(label[i])
# 随机翻转
for e in range(-1,2):
# 1:水平翻转,0:垂直翻转,-1:水平垂直翻转
f_img = cv2.flip(imgs[i], e)
# 添加翻转图像
imgs_out.append(f_img)
# 添加类标
label_out.append(label[i])
# 裁剪翻转后图片
# 生成裁剪随机数:70%-90%大小
rd_num = np.random.uniform(0.7, 0.9)
# 生成随机裁剪长宽
rd_w = int(w * rd_num)
rd_h = int(h * rd_num)
# 进行裁剪
crop_img = tf.image.random_crop(imgs[i],[rd_w,rd_h,c]).numpy()
# 重新调整大小
re_img = cv2.resize(crop_img, (w, h))
# 添加裁剪图像
imgs_out.append(re_img)
# 添加类标
label_out.append(label[i])
# 原图随机裁剪,执行3次
for f in range(3):
# 生成裁剪随机数:50%-80%大小
rd_num = np.random.uniform(0.5, 0.8)
# 生成随机裁剪长宽
rd_w = int(w * rd_num)
rd_h = int(h * rd_num)
# 进行裁剪
crop_img = tf.image.random_crop(imgs[i],[rd_w,rd_h,c]).numpy()
# 重新调整大小
re_img = cv2.resize(crop_img, (w, h))
# 添加裁剪图像
imgs_out.append(re_img)
# 添加类标
label_out.append(label[i])
return imgs_out,label_out
# 执行函数
data2,label2 = img_cut(data1,label1)
# 将图像数据转换为numpy数组
data_sample,label_sample = np.asarray(data2, np.float32), np.asarray(label2, np.int32)
完成图像增强处理后图片数据有700张,512*512的3通道数据,每个类别数据如下:
由于模型构建代码较多,这里就不一一进行展示,感兴趣的同学可以在文章下方找到完整代码下载地址。
#运行构建的模型图
ResNet_model = ResNet50(input_shape=(w,h,c),classes=label_counts)
#编译模型来配置学习过程
ResNet_model.compile(optimizer=keras.optimizers.Adam(learning_rate=learning_rate),
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
'''
第一轮训练100个epoch
'''
history_1 = ResNet_model.fit(data,label, epochs = num_epochs,batch_size = batch_size,validation_split=0.1)
#保存模型
ResNet_model.save('models_save/Resnet_model_0322_100.h5')
'''
第二轮训练100个epoch
'''
history_2 = ResNet_model.fit(data,label, epochs = num_epochs,batch_size = batch_size,validation_split=0.1)
#保存模型
ResNet_model.save('models_save/Resnet_model_0322_200.h5')
'''
第三轮训练100个epoch
'''
history_3 = ResNet_model.fit(data,label, epochs = num_epochs,batch_size = batch_size,validation_split=0.1)
#保存模型
ResNet_model.save('models_save/Resnet_model_0322_300.h5')
'''
第四轮训练100个epoch
'''
history_4 = ResNet_model.fit(data,label, epochs = num_epochs,batch_size = batch_size,validation_split=0.1)
#保存模型
ResNet_model.save('models_save/Resnet_model_0322_400.h5')
针对6个不同岩石种类进行分类,70%用作训练数据,30%用作测试数据,最终测试集的准确率能达到:94.3%,见下图:
由于项目代码量和数据集较大,感兴趣的同学可以直接下载代码,使用过程中如遇到任何问题可以在评论区进行评论,我都会一一解答。
代码下载: