算开个头,不算特别实战
扫描电子显微镜,材料开发不可缺少的分析仪器。原理就不详述了。材料的形貌,具体长什么样的都可以看得很清楚。
材料表面的形貌很多情况下会和材料的物性产生直接关系,比如说可以从SEM看出粒子的直径分布,多孔材料的孔径等等。孔径这个就很直接了,孔径越小,材料的表面积越大,有可能相对的化学活性比如说气体的吸收能力会更大。
所以,有可能可以利用SEM作为材料的描述符X,建立模型来预测有关的物性?现在手边没有这样子的数据,但是觉得可能这方面的先行研究应该有一些吧。之前曾经有提到一块钱买中巴:机器学习在材料方向的应用(lightgbm+贝叶斯优化调参)zhuanlan.zhihu.com
可以用组成来预测物性。在这里,如果我们有组成,加上图像数据,应该可以得到更高的精度??可惜好像还没有系统性的数据
python有skimage这个包可以对材料进行一些预处理。对于材料的SEM也可以进行一些有意思的操作。哈佛大学有一个很简单的SEM的数据库,里面有四种材料的SEM图,但是好像没有标记,然后每种材料的样本也不大就四张图。可以在下面的地址下载https://dataverse.harvard.edu/dataset.xhtml?persistentId=doi:10.7910/DVN/HVBW0Q#__sid=js0dataverse.harvard.edu
首先对数据进行读取。这里我选择的是两张多孔粒子的图像
from skimage.io import imread
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
from pathlib import Path
import numpy as np
%matplotlib inline
plt.rcParams["figure.figsize"] = (8, 8)
plt.rcParams["figure.dpi"] = 150
plt.rcParams["font.size"] = 14
plt.rcParams['font.family'] = ['sans-serif']
plt.rcParams['font.sans-serif'] = ['DejaVu Sans']
plt.style.use('ggplot')
sns.set_style("whitegrid", {'axes.grid': False})
imgg=imread('...../archive/3dsem/Pollen1001.jpg')
fig = plt.plot(figsize=(3, 3))
plt.imshow(imgg)
多孔材料嘛。有密集恐惧症的同学对不住了。这里修改一下选项as_gray可以使得图片变成更加鲜明的样子。读取了两张图,其中一张长这样
imgg=imread('/Users/yweilin/Desktop/study/code/archive/3dsem/Pollen1001.jpg', as_gray=True)
imgg2=imread('/Users/yweilin/Desktop/study/code/archive/3dsem/Pollen1002.jpg', as_gray=True)
fig = plt.plot(figsize=(3, 3))
plt.imshow(imgg)
这个图下面有具体的拍照时间比例尺什么资料,我们可以把这一块锯掉。实际上读取这个数据之后,这是一个像素的矩阵,把对应坐标部分的数据去掉就可以了。
fig = plt.plot(figsize=(3, 3))
plt.imshow(imgg[:-100])
接下来我们可以对图片进行特征点提取
特征点是图像处理中,特征点指的是图像灰度值发生剧烈变化的点或者在图像边缘上曲率较大的点(即两个边缘的交点)。
百度百科里这样定义的。这里的特征点则可以反应出一些孔的有关信息。这个很重要因为之前也说了会对物性产生影响。
from skimage.feature import corner_harris, corner_peaks, ORB
descriptor_extractor = ORB(n_keypoints=1000)
def extract_points(in_img):
descriptor_extractor.detect_and_extract(in_img)
return {'keypoints': descriptor_extractor.keypoints,
'descriptors': descriptor_extractor.descriptors}
extracted_image=extract_points(imgg[:-100])
extracted_image2=extract_points(imgg2[:-100])
特征点可视化之后是这样的。注意一下这里的特征点图是90度翻转过的。
fig = plt.plot(figsize=(3, 3))
plt.plot(extracted_image['keypoints'][:, 0],
extracted_image['keypoints'][:, 1],
'.',)
# plt.plot(extracted_image2['keypoints'][:, 0],
# extracted_image2['keypoints'][:, 1],
# '.',)
这里imgg2是二号图像,与一号图像相比似乎别无两样。
对照一号图片的特征点可以看出似乎还是有一些不同之处的。
fig = plt.plot(figsize=(3, 3))
plt.plot(extracted_image['keypoints'][:, 0],
extracted_image['keypoints'][:, 1],
'.',)
plt.plot(extracted_image2['keypoints'][:, 0],
extracted_image2['keypoints'][:, 1],
'.',)
特征点和特征点之间出现了一定程度的偏移。将特征点投影到原图,可以进一步观察对应信息
from skimage.feature import match_descriptors, plot_matches
c_matches = match_descriptors(extracted_image['descriptors'],extracted_image2['descriptors'], cross_check=True)
fig = plt.plot(figsize=(3, 3))
plot_matches(plt,
imgg[:-100], imgg2[:-100],
extracted_image['keypoints'], extracted_image2['keypoints'],
c_matches)
可以观察到提取的特征点分布在孔的附近。具体看一下两张图的特征点之间的距离以及分布
dist_list=[]
for i, (c_idx, n_idx) in enumerate(c_matches):
x_vec = [extracted_image['keypoints'][c_idx, 0], extracted_image2['keypoints'][n_idx, 0]]
y_vec = [extracted_image['keypoints'][c_idx, 1], extracted_image2['keypoints'][n_idx, 1]]
dist = np.sqrt(np.square(np.diff(x_vec))+np.square(np.diff(y_vec)))[0]
dist_list.append(dist)
dist_list_df=pd.DataFrame(dist_list,columns=['distance'])
dist_list_df.hist(figsize=(5, 5))
这两张图之间的大部分图还是匹配的。接下来看一看距离在100以上的有点异常的特征点
outlier=[]
outlier_index=[]
for x in dist_list:
if x > 100:
outlier.append(x)
outlier_index.append(dist_list.index(x))
fig = plt.plot(figsize=(3, 3))
plt.plot(extracted_image['keypoints'][:, 0][outlier_index],
extracted_image['keypoints'][:, 1][outlier_index],
'.',)
plt.plot(extracted_image2['keypoints'][:, 0][outlier_index],
extracted_image2['keypoints'][:, 1][outlier_index],
'.',)
还是可接受的吧。可能因为亮度什么的或许有些不同?https://github.com/onecoinbuybus/chemoinformatics/blob/master/matinfo.ipynbgithub.com
参考了kaggle看到的文章https://www.kaggle.com/kmader/3dsem-a-dataset-for-3d-sem-surface-reconstructionwww.kaggle.com