目录
- 概述
- 1 实现过程
-
- 1.1 应用场景实现过程
- 1.2 仿真场景实现过程
- 2 代码实现
-
- 2.1 基于卷积神经网络图像识别模型搭建与训练模块
- 2.2 串口配置和图像识别模块
- 结束语
概述
基于卷积神经网络(CNN)实现水果识别。用仿真实现机械臂对水果的分拣。
1 实现过程
1.1 应用场景实现过程
1). 水果图像数据采集以及上传
2). 图像识别(经过卷积神经网络训练后得到的模型)
3). 图像识别后的结果通过串口发送数据给芯片
4). 芯片控制控制舵机使机械臂分拣水果
整体过程如下图:
1.2 仿真场景实现过程
实现功能: 软件模拟传送带上水果识别,接收上层传入控制命令,进行相应操作,界面上机械臂会动态进行识别水果推出。
实现过程如下:
1). 仿真软件会把水果图片路径通过串口发送到pc
2). pc依据串口收到图片路径信息,读取图片信息,进行识别
3). 然后pc通过串口发送命令进行机械臂操作
演示图片如下:
2 代码实现
只用了苹果和香蕉两种水果识别
2.1 基于卷积神经网络图像识别模型搭建与训练模块
import numpy as np
from keras.datasets import mnist
from keras.models import Sequential
from keras.layers import Dense
from keras.layers import Dropout
from keras.layers import Flatten
from keras.layers.convolutional import Conv2D
from keras.layers.convolutional import MaxPooling2D
from keras.utils import np_utils
from sklearn.model_selection import train_test_split
from keras import backend as K
import cv2
import os
os.environ["CUDA_VISIBLE_DEVICES"] = "0"
from glob import glob
img_h, img_w, n_channels = 100, 100, 3
classes = 2
train_batch_size = 32
test_batch_size = 32
train_path = './data/Training/'
test_path = './data/Test/'
train_epoch = 10
MODEL_PATH = 'final_model_apple.h5'
class Dataset:
def __init__(self, path_name):
self.train_images = None
self.train_labels = None
self.valid_images = None
self.valid_labels = None
self.test_images = None
self.test_labels = None
self.path_name = path_name
self.input_shape = None
def load_dataset(self):
all_paths = glob(self.path_name+"*")
images = []
labels = []
for i, img_name in enumerate(all_paths):
img = cv2.imread(img_name, 1)
img = cv2.resize(img, dsize=(img_w, img_h))
images.append(img)
labels.append(img_name[-9])
tmpFlag = np.random.random()
if tmpFlag > 0.5:
tmpFlag = np.random.random()
if tmpFlag > 0.5:
flip_horizontal = cv2.flip(img, 1)
images.append(flip_horizontal)
else:
flip_vertical = cv2.flip(img, 0)
images.append(flip_vertical)
labels.append(img_name[-9])
images = np.array(images)
return images, labels
def load(self, img_rows=img_h, img_cols=img_w,
img_channels=n_channels, nb_classes=classes):
images, labels = self.load_dataset()
train_images, valid_images, train_labels, valid_labels = train_test_split(images, labels, test_size=0.3)
_, test_images, _, test_labels = train_test_split(images, labels, test_size=0.5)
train_images = train_images.reshape(train_images.shape[0], img_rows, img_cols, img_channels)
valid_images = valid_images.reshape(valid_images.shape[0], img_rows, img_cols, img_channels)
test_images = test_images.reshape(test_images.shape[0], img_rows, img_cols, img_channels)
self.input_shape = (img_rows, img_cols, img_channels)
print(train_images.shape[0], 'train samples')
print(valid_images.shape[0], 'valid samples')
print(test_images.shape[0], 'test1 samples')
train_labels = np_utils.to_categorical(train_labels, nb_classes)
valid_labels = np_utils.to_categorical(valid_labels, nb_classes)
test_labels = np_utils.to_categorical(test_labels, nb_classes)
train_images = train_images.astype('float32')
valid_images = valid_images.astype('float32')
test_images = test_images.astype('float32')
train_images /= 255
valid_images /= 255
test_images /= 255
self.train_images = train_images
self.valid_images = valid_images
self.test_images = test_images
self.train_labels = train_labels
self.valid_labels = valid_labels
self.test_labels = test_labels
dataset = Dataset(train_path)
dataset.load()
def baseline_model(dataset):
model = Sequential()
model.add(Conv2D(32, (5, 5), input_shape=dataset.input_shape, activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.2))
model.add(Conv2D(64, kernel_size=(5, 5), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2), strides=(2, 2)))
model.add(Dropout(0.2))
model.add(Flatten())
model.add(Dense(128, activation='relu'))
model.add(Dense(classes, activation='softmax'))
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
return model
model = baseline_model(dataset)
model.fit(dataset.train_images,dataset.train_labels, validation_data=(dataset.valid_images, dataset.valid_labels), epochs=train_epoch, batch_size=train_batch_size, verbose=1)
model.summary()
scores = model.evaluate(dataset.test_images, dataset.test_labels, verbose=1)
print("Baseline Error: %.2f%%" % (100 - scores[1] * 100))
model.save('final_model_apple.h5')
2.2 串口配置和图像识别模块
import cv2
import numpy as np
from keras.models import load_model
import time
import os
import serial
os.environ["CUDA_VISIBLE_DEVICES"] = "0"
model = load_model('./final_model_apple.h5')
portx = "COM3"
bps = 115200
timex = 5
ser = serial.Serial(portx, bps, timeout=timex)
print("begin....")
while True:
file = ser.readline()
if not file.strip():
continue
file=file[:-1].decode()
print("recv:", file)
img = cv2.imread(file, cv2.IMREAD_COLOR)
print(img)
img1 = cv2.resize(img,(100,100),interpolation = cv2.INTER_AREA)
img = (img1.reshape(1,100,100,3)).astype("float32")/255
predict = model.predict(img)
print(predict)
predict=np.argmax(predict,axis=1)
if 0 == predict[0] :
cmd = bytes.fromhex('ff 01')
ser.write(cmd)
print("图片中的水果是苹果")
else:
print("图片中的水果是香蕉")
结束语
首先要感谢华清李老师对这次项目的指导,由于机械臂仿真软件是老师提供故没有上传
链接:https://pan.baidu.com/s/1OIeyeEOKmpMapnOsLtFqgQ
提取码:pnqu
后期在这个网站上下载更多数据来训练 :https://www.kaggle.com/moltean/fruits