我使用了Python的OpenCV库进行所有与相机相关的操作,所以这里的label指的是图像属于哪个类,根据标签,图像保存在适当的目录中。ct和maxCt是用来保存图像的起始索引和最终索引,剩下的是标准的OpenCV代码,用于获取网络摄像头源并将图像保存到目录中。需要注意的一点是,我所有的图片维数都是300 x 300的。运行此目录树后,我的目录树如下所示。
C:.
├───paper
│ paper0.jpg
│ paper1.jpg
│ paper2.jpg
│
├───rock
│ rock0.jpg
│ rock1.jpg
│ rock2.jpg
│
└───scissor
scissor0.jpg
scissor1.jpg
scissor2.jpg
如果你引用的是Github存储库(https://github.com/HOD101s/RockPaperScissor-AI-) ,则getData.py会为你完成这项工作!预处理我们的数据我们需要使用图像,而计算机可以识别数字,因此,我们将所有图像转换为它们各自的矢量表示,另外,我们的标签尚待生成,由于已建立的标签不能是文本,因此我使用shape_to_label字典为每个类手动构建了“独热编码”表示。
DATA_PATH = sys.argv[1] # Path to folder containing data
shape_to_label = {'rock':np.array([1.,0.,0.,0.]),'paper':np.array([0.,1.,0.,0.]),'scissor':np.array([0.,0.,1.,0.]),'ok':np.array([0.,0.,0.,1.])}
arr_to_shape = {np.argmax(shape_to_label[x]):x for x in shape_to_label.keys()}
imgData = list()
labels = list()
for dr in os.listdir(DATA_PATH):
if dr not in ['rock','paper','scissor']:
continue
print(dr)
lb = shape_to_label[dr]
i = 0
for pic in os.listdir(os.path.join(DATA_PATH,dr)):
path = os.path.join(DATA_PATH,dr+'/'+pic)
img = cv2.imread(path)
imgData.append([img,lb])
imgData.append([cv2.flip(img, 1),lb]) #horizontally flipped image
imgData.append([cv2.resize(img[50:250,50:250],(300,300)),lb]) # zoom : crop in and resize
i+=3
print(i)
np.random.shuffle(imgData)
imgData,labels = zip(*imgData)
imgData = np.array(imgData)
labels = np.array(labels)
当我们根据类将图像保存在目录中时,目录名用作标签,该标签使用shape_to_label字典转换为独热表示。在我们遍历系统中的文件以访问图像之后,cv2.imread()函数返回图像的矢量表示。我们通过翻转图像并放大图像来进行一些手动的数据增强,这增加了我们的数据集大小,而无需拍摄新照片,数据增强是生成数据集的关键部分。最后,图像和标签存储在单独的numpy数组中。cv2.imread()函数https://www.geeksforgeeks.org/python-opencv-cv2-imread-method/更多关于数据增强的信息。https://towardsdatascience.com/data-augmentation-for-deep-learning-4fe21d1a4eb9通过迁移学习建立我们的模型:在处理图像数据时,有许多经过预训练的模型可供使用,这些模型已经在具有数千个标签的数据集上进行了训练,由于这些模型通过其应用程序api的Tensorflow和Keras分布,我们可以使用这些模型,这使得在我们的应用程序中包含这些预先训练的模型看起来很容易!
总之,迁移学习采用的是经过预训练的模型,并且不包含进行最终预测的最终层,能够区分这种情况下图像中的特征,并将这些信息传递给我们自己的Dense神经网络。为什么不训练你自己的模型呢?完全取决于你!然而,使用迁移学习可以在很多时候使你的进步更快,从某种意义上说,你避免了重复造轮子。