接上文,本次我们将使用入门级的CNN卷积神经网络来完成价格识别。1分析已经获取到原始图像,然后对图像进行处理,然后进行裁剪。作为机器学习的原材料。因为图片是PNG格式,所以一般是4通道(RGB+透明度)。一般处理流程:1获取原图:4通道(RGB+透明度)2转换为灰度图:单通道,像素值0-255灰度转换公式:L=R299/1000+G587/1000+B*114/10003灰度图二值化:其实就是将图像的像素值转换为0或1(二值化转换时需要根据图像当前数据适当调整[0if_<200else1])如果数据比较复杂,还会涉及去边框、边缘检测、歪斜校正、裁剪、降噪(腐蚀、膨胀)等。这次的数据比较简单,转成二进制后可以直接使用数据。2识别2.1切割图像切割关键代码:lines=[-281.16,-249.92,-218.68,-187.44,-156.2,-124.96,-93.72,-62.48,-31.24,-0.0]lines_step=22lines_map={'-281.16':336,'-249.92':299,'-218.68':261,'-187.44':223,'-156.2':187,'-124.96':149,'-93.72':112,'-62.48':74,'-31.24':38,'-0.0':1,}idx=1defprocess_img(imgpath:str):globalidx#原图img=Image.open(imgpath)width,height=img.sizeimg2=copy.deepcopy(img)img_arr=np.array(img)print(img_arr.shape)#转换为灰度#转换算法:L=R*299/1000+G*587/1000+B*114/1000≈361img_gray=img.convert('L')img_gray_arr=np.array(img_gray)print(img_gray_arr.shape)fordatainimg_gray_arr:pass#print(''.join(['{:03}'.format(_)for_indata]))#print(''.join(['{:03}'.format(_)if_!=0else'...'for_indata]))#二值化img_bin=img_gray.point([0if_<128else1for_inrange(256)],'1')img_bin_arr=np.array(img_bin)print(img_bin_arr.shape)fordatainimg_bin_arr:pass#print(''.join(['1'if_else'0'for_indata]))#print(''.join(['X'if_else'.'for_indata]))#图像处理img_draw=ImageDraw.Draw(img2)forlineinlines:new_line=lines_map.get(str(line))p1=(new_line,1)p2=(new_line+22,height-1)#图片圆形选择img_draw.rectangle((p1,p2),outline='red')#图片裁剪img_crop=img_bin.crop((new_line,0,new_line+22,height))img_crop.save(os.path.join('imgs_crop','{:03}.png'.format(idx)))idx+=1plt.imshow(img2)plt.show()裁剪图片:然后对图片进行手动分类,将图片放置在以编号命名的文件夹中,完成手动标注。2.2识别训练主要使用Python3Keras+TensorFlow完成。模型代码示例:defgen_model():"""建立模型:return:model"""_model=Sequential([#卷积层#36是输出维度,也就是卷积核的个数#kernel_size是大小卷积核Conv2D(36,kernel_size=3,padding='same',activation='relu',input_shape=(36,22,1)),#最大池化层MaxPooling2D(pool_size=(2,2)),#Dropoutincludes在训练过程中每次更新时将输入单元的比例随机设置为0,有助于防止过拟合。Dropout(0.25),#卷积层Conv2D(64,kernel_size=3,padding='same',activation='relu',input_shape=(36,36,1)),#最大池化层MaxPooling2D(pool_size=(2,2)),#Dropout(0.25),#压平输入,将多维数据变成一维数据Flatten(),#全连接层Dense(512,activation='relu'),Dropout(0.5),Dense(10,activation='softmax'),])return_model训练代码示例:deftrain():model=gen_model()model.summary()#modelcompilation#optimizer优化器模型#loss损失函数名,objectivefunction#metrics包含指标在训练和测试期间评估模型的网络性能model.compile(optimizer='adam',#keras.optimizers.Adadelta()loss='sparse_categorical_crossentropy',metrics=['accuracy'])x_train,y_train=load_data()x_train=x_train.reshape(-1,36,22,1)x_test,y_test=load_test_data()x_test=x_test.reshape(-1,36,22,1)#模型加载训练集callbacks=tensorboardmonitoring#做训练评估#x_train输入数据#y_train标量sign#batch_size梯度下降时,训练时会计算一次每batch包含的样本数,从而使目标函数一步步优化。#epochsInteger,训练的轮数,每个epoch都会对训练集进行一轮。#verboselog显示,0表示输出不在标准输出流中的日志信息,1表示输出进度条记录,2表示每个epoch输出一行记录#validation_data验证数据集history=model.fit(x_train,y_train,batch_size=32,epochs=20,verbose=1,validation_data=(x_test,y_test),)#epochs数据集中所有样本都运行一次的次数,多少组batch_size用于训练和调整权重score=model.evaluate(x_test,y_test,verbose=0)print('Testloss:',score[0])print('Testaccuracy:',score[1])#绘制训练集的准确率值和训练期间的测试集('Epoch')plt.legend(['Train','Test'],loc='upperleft')plt.show()#绘制训练时训练集和测试集的损失值plt.plot(history.history['loss'])plt.plot(history.history['val_loss'])plt.title('Modelloss')plt.ylabel('Loss')plt.xlabel('Epoch')plt.legend(['Train','Test'],loc='upperleft')plt.show()model.save('model/ziru.h5')训练数据生成代码示例:要点:train_lable和train_data。lable是对应的数据标签,即要识别的值。data是对应数据的具体数据值。defgen_train_data(parent_path:str):train_data=[]train_label=[]foridxinrange(10):cur_path=os.path.join(parent_path,str(idx))fordirpath,dirnames,文件名inos.walk(cur_path):对于文件名中的文件名:iffilename.endswith('png'):imgpath=os.path.join(cur_path,filename)label=imgpath.split('/')[1]data=np.array(Image.open(imgpath))train_label.append(int(label))train_data.append(data)returnnp.array(train_data),np.array(train_label)训练过程如下:由于图片比较简单,简单训练基本上可以达到100%的识别。Epoch1/207/7[==============================]-1秒68毫秒/步-损失:2.0173-精度:0.3350-val_loss:1.3893-val_accuracy:0.7950Epoch2/207/7[==============================]-0s43ms/step-损失:1.1314-精度:0.6900-val_loss:0.5309-val_accuracy:1.0000Epoch3/207/7[==============================]-0s36ms/步-损失:0.5474-精度:0.8100-val_loss:0.1853-val_accuracy:1.0000Epoch4/207/7[==============================]-0s36ms/step-loss:0.2606-accuracy:0.9250-val_loss:0.0842-val_accuracy:1.0000Epoch5/207/7[==============================]-0s34ms/step-loss:0.2730-accuracy:0.9250-val_loss:0.1025-val_accuracy:0.9700Epoch6/207/7[==============================]-0s37毫秒/步-损失:0.1857-准确度:0.9300-val_loss:0.0365-val_accuracy:1.0000Epoch7/207/7[==============================]-0s35ms/步-损失:0.0952-精度:0.9800-val_loss:0.0165-val_accuracy:1.0000Epoch8/207/7[==============================]-0s35ms/step-损失:0.0560-精度:0.9900-val_loss:0.0076-val_accuracy:1.0000Epoch9/207/7[==============================]-0s35ms/step-损失:0.0125-精度:1.0000-val_loss:0.0066-val_accuracy:1.0000Epoch10/207/7[==============================]-0s36ms/步-损失:0.0173-精度:1.0000-val_loss:0.0024-val_accuracy:1.0000Epoch11/207/7[==============================]-0s34ms/step-loss:0.0086-accuracy:1.0000-val_loss:0.0014-val_accuracy:1.0000Epoch12/207/7[==============================]-0s37ms/step-loss:0.0061-accuracy:1.0000-val_loss:8.3420e-04-val_accuracy:1.0000Epoch13/207/7[==============================]-0秒33毫秒/步-损失:0.0051-精度:1.0000-val_loss:4.9917e-04-val_accuracy:1.0000Epoch14/207/7[==============================]-0s35毫秒/步-损失:0.0020-精度:1.0000-val_loss:3.4299e-04-val_a精度:1.0000Epoch15/207/7[=================================]-0s35ms/step-损失:0.0037-准确度:1.0000-val_loss:2.3839e-04-val_accuracy:1.0000Epoch16/207/7[===============================]-0s34ms/step-loss:0.0028-accuracy:1.0000-val_loss:2.0110e-04-val_accuracy:1.0000Epoch17/207/7[===============================]-0s36ms/step-loss:0.0012-accuracy:1.0000-val_loss:1.8016e-04-val_accuracy:1.0000Epoch18/207/7[=================================]-0s35毫秒/步-损失:0.0015-准确度:1.0000-val_loss:1.5284e-04-val_accuracy:1.0000Epoch19/207/7[=================================]-0s38ms/步-损失:8.4545e-04-精度:1.0000-val_loss:1.3383e-04-val_accuracy:1.0000Epoch20/207/7[===============================]-0s36ms/step-loss:7.2767e-04-accuracy:1.0000-val_loss:1.2135e-04-val_accuracy:1.0000Testloss:0.00012135423457948491Testaccuracy:1.0Validationloss和accuracychartloading:2.3recogniti在模型上,输入数据,得到识别结果结果示例代码:def__recognize_img(img_data):model=load_model('model/ziru.h5')img_arr=np.array(img_data)img_arr=img_arr.reshape((-1,36,22,1))result=model.predict(img_arr)predict_val=__parse_result(result)返回predict_valdef__parse_result(result):result=result[0]max_val=max(result)foriinrange(10):ifmax_val==result[i]:returni3package整个识别过程完成后,剩下的就是封装服务对外暴露了。为了方便,提供了一个接口服务:测试接口==>https://lemon.lpe234.xyz/common/ziru/4总结本文中CNN的使用基本是入门级的。其实数字识别也可以通过关键像素来识别。比如1张和3张图片的像素肯定是有区别的,找出这个区别就基本可以识别了。
