[AI人工智能]基于行空板的机器学习物体分类项目(水果识别)
本帖最后由 IvanDMido 于 2022-11-25 18:42 编辑基于行空板的物体分类项目(水果识别)
前言
应两位小伙伴要求,将原“智能快递柜机器人”项目中的物体分类功能摘出,作一分享。
项目目标
用人工智能中的物体分类技术,对三种不同的水果(苹果、香蕉、西瓜)进行识别分类。
https://www.bilibili.com/video/BV1TY411d7t9/
项目器材
行空板,USB摄像头
项目流程1、采集拍取要识别的三类水果的图片集2、利用已有的一个基础物体分类模型,结合采集的图片数据集,训练一个包含这三类图片的新模型3、借助生成的模型,预测某一类水果
项目实践
STEP0硬件连接
将USB摄像头连上行空板。
STEP1摄像头采集图像
一、功能描述
在这个任务中,将采集苹果、香蕉、西瓜、以及白色背景四种类型的图像,并存储到当前路径下“dataset_object_classification”目录中的“01Apple”、“02Banana”、“03Watermelon”、“04Others”四个子目录内,这些目录自动生成。
二、编写程序'''拍照,采集图像作为数据集;
运行程序,终端输入1,表示采集"01Apple"数据集,待摄像头的画面启动后,按住按键a进行持续拍照,终端出现“image saved”字样,表示100张图片已采集完成”
之后重复上述操作,可采集02、03、04类数据集'''
import cv2 # 导入cv库
import os
os.system('mkdir -p dataset_object_classification/01Apple')# 创建文件夹以保存采集的图像
os.system('mkdir -p dataset_object_classification/02Banana')# 创建文件夹以保存采集的图像
os.system('mkdir -p dataset_object_classification/03Watermelon')# 创建文件夹以保存采集的图像
os.system('mkdir -p dataset_object_classification/04Others')# 创建文件夹以保存采集的图像
number = input("请输入数据集文件夹编号:")
if number == "1":
location = 'dataset_object_classification/01Apple/'
elif number == "2":
location = 'dataset_object_classification/02Banana/'
elif number == "3":
location = 'dataset_object_classification/03Watermelon/'
elif number == "4":
location = 'dataset_object_classification/04Others/'
print(location)
def get_photo(): # 定义拍照函数(上传参数--图片保存地址)
cap = cv2.VideoCapture(0) # 创建一个 VideoCapture 对象, 构建视频抓捕器, 0表示需要启动的摄像头
cap.set(cv2.CAP_PROP_BUFFERSIZE, 1) # Set the camera buffer to 1, to decrease the latency. # 设置1帧的缓冲,减少延迟避免卡顿
cv2.namedWindow('window',cv2.WND_PROP_FULLSCREEN) # Set the windows to be full screen. # 构建一个窗口,名称为window,属性为可以全屏
cv2.setWindowProperty('window', cv2.WND_PROP_FULLSCREEN, cv2.WINDOW_FULLSCREEN) # Set the windows to be full screen. # 设置窗口全屏
count = 0
while (cap.isOpened()): # 循环读取每一帧
ret, frame = cap.read() # 从摄像头读取图片 , ret存储布尔值,frame存储图像
#frame = cv2.flip(frame, 1, dst=None) # 镜像
cv2.imshow("window", frame) # 窗口显示,显示名为 window
# 保持画面的持续。
key = cv2.waitKey(1) # 每帧数据延时1ms,延时不能为 0,否则读取的结果会是静态帧
if key & 0xFF == ord('b'): # 按b键退出
break
elif key & 0xFF == ord('a'): # 通过a键保存图片,并退出。
if count < 100:# 100张图片,可自行修改数量
global location
cv2.imwrite(location+ str(count) + ".jpg", frame) # 将图像保存为图片
count = count + 1
# print(count)
else:
print("image saved")
cap.release()# 释放摄像头
cv2.destroyAllWindows()# 关闭所有窗口
get_photo()# 调用拍照函数,同时传入要保存的图片名称
三、运行程序A:运行程序,在终端输入1(表示将采集的图像存储到“01Apple”目录),随后将摄像头对准苹果的图片,待画面启动后,按住按键a进行持续拍照,终端出现“image saved”字样后,100张图片即采集完成”,再按下按键b退出摄像头画面。这里,我们采集苹果的图片集。操作过程视频:https://www.bilibili.com/video/BV11g411p74v/
B:之后用同样的方式,分别在终端输入2,3,4在“02Banana”、“03Watermelon”、“04Others”目录中拍摄并存储香蕉、西瓜、以及白色背景(用白色背景模拟其他物体)三种图片集。结果视频:https://www.bilibili.com/video/BV1FG4y1o7Bh/
STEP2用神经网络训练物体模型
一、功能描述将采集的四组图片数据集用神经网络训练出物体模型。
二、编写程序'''训练模型,将采集的图片数据集用神经网络训练出物体模型;
运行程序,待计算机自动训练,时间约1-5分钟不等,完成后,终端会显示“模型保存完成!”字样,并在当前文件目录下会自动生成“object_classification_model.h5”模型文件。'''
# 导入tensorflow深度学习框架
import tensorflow as tf
# 导入keras深度学习库
from tensorflow import keras
# 导入数据处理库
import numpy as np
# 数据预处理
# 将图片处理成预训练模型可以输入的格式
# 定义数据集路径
train_dir = 'dataset_object_classification'
# ImageDataGenerator为Keras的图像生成器,用于预处理图像数据
# mobilenet_v2.preprocess_input为mobilenet_v2的输入图像处理方法,用于将图像处理成适合mobilenet_v2模型的格式
datagen = keras.preprocessing.image.ImageDataGenerator(preprocessing_function=keras.applications.mobilenet_v2.preprocess_input)
# 图像生成器的flow_from_directory方法,负责生成批量数据,供模型训练
train_batches = datagen.flow_from_directory(
directory=train_dir, # directory:目标文件夹路径,在目标文件夹中,包含多个子文件夹,每个子文件夹都是一类,包含一类图像数据
shuffle=True, # shuffle:是否打乱数据,设置为True,表示打乱每个子文件夹的数据处理顺序,否则按照子文件夹中图片名称的字母顺序处理数据
target_size=(96,96), # target_size:目标尺寸,所有图像将被重置为目标尺寸
batch_size=10) #batch_size:数据批次大小,表示一批数据中包含的数据量,预处理时,会按批次处理数据
# train_batches返回的参数包括输入数据和标签数据
# 冻结预训练模型
# 基础模型用的是mobilenet_v2,输入图像尺寸为 224*224
base_model = keras.models.load_model("mobilenet_v2_96.h5",compile=False)# 导入预训练模型
base_model.trainable = False # 冻结预训练模型
# 这里的模型不含输出层,只有输入层和隐藏层
# 冻结后,权重等参数不再改变
# 冻结后的模型相当于只含输入层的特征提取器
# 创建神经网络
# 实例化一个神经网络模型
model = keras.Sequential(name="object_classification_model")
# 创建输入层
model.add(base_model) # 定义输入层为预训练模型,输入尺寸即为 224*224
# 创建隐藏层
model.add(keras.layers.Dense(100, activation='relu')) # 创建一层隐藏层,包括100个神经元
# 创建输出层
model.add(keras.layers.Dense(4, activation='softmax'))# 定义输出层为4分类(种类数量)
# # 查看模型结构
# print("模型结构:")
# model.summary()
# 训练模型
# 设置参数
model.compile(
optimizer=keras.optimizers.Adam(0.0001),
loss='categorical_crossentropy',
metrics=['accuracy']
)
# 训练模型
print("开始训练:")
model.fit(train_batches, epochs=5)# 设置5轮训练
print("训练完成!")
# 保存模型
model.save("object_classification_model.h5")
print("模型保存完成!")
三、运行程序Tips:如果出现没有库的一些报错,如tensorflow等,可通过pip install的方式自行安装。
A:运行程序,等待行空板自动训练模型(时间约1-5分钟不等,图片越多时间越久)。训练过程视频https://www.bilibili.com/video/BV1yD4y1e745/
B:训练完成后,会在终端显示“模型保存完成”,并在程序路径下生成对应的模型文件。
STEP3用神经网络预测单张图片一、功能描述用“dataset_object_classification/03Watermelon/2.jpg”图片进行预测,检验模型准确率。
二、编写程序'''用“dataset_object_classification/03Watermelon/2.jpg”图片进行预测,检验模型准确率;
运行程序,待计算机自动导入模型进行预测,随后会在终端显示该图片在四个类别下的不同分类概率,以及取概率最高的类别作为最终结果
PS:本程序非必须'''
# 导入tensorflow深度学习框架
import tensorflow as tf
# 导入keras深度学习库
from tensorflow import keras
# 导入数据处理库
import numpy as np
# 导入物体分类模型
print("导入模型中...")
model_name = "object_classification_model.h5"
model = tf.keras.models.load_model(model_name)
print("{}模型导入完成".format(model_name))
# 输出预测结果
img = keras.preprocessing.image.load_img("dataset_object_classification/01Apple/2.jpg", target_size=(96, 96))
img2 = keras.preprocessing.image.load_img("dataset_object_classification/02Banana/2.jpg", target_size=(96, 96))
img3 =keras.preprocessing.image.load_img("dataset_object_classification/03Watermelon/2.jpg", target_size=(96, 96))
img4 =keras.preprocessing.image.load_img("dataset_object_classification/04Others/2.jpg", target_size=(96, 96))
# 图像预处理
img_array = keras.preprocessing.image.img_to_array(img3) # 将图像数据转换为数组 #用img3进行预测,可自行修改
img_array = keras.applications.mobilenet_v2.preprocess_input(img_array)# 将数组处理成适合mobilenet_v2的输入格式
img_array = tf.expand_dims(img_array, 0) # 在图像数组前面增加一维,即将 (224,224,3) 的图像矩阵变成 (1,224,224,3)
# 定义分类结果的名称,按照数据集中的文件夹顺序,神经网络的输出依次为01-04
class_names = ["01Apple","02Banana","03Watermelon","04Others"]
# 预测
print("预测结果为:")
predictions = model.predict(img_array)# 预测图像(整体概率)
print(predictions)
result = class_names# 预测结果(概率最高者)
print(result)
三、运行程序
A:运行程序,等待行空板加载模型并进行预测预测过程视频https://www.bilibili.com/video/BV1tD4y1e7qg/
结果图示
STEP4用神经网络预测视频流
一、功能描述
实时显示图像的预测结果。
二、编写程序
'''在Pyboard屏幕上显示视频流画面并实时预测结果'''
# 导入tensorflow深度学习框架
import tensorflow as tf
# 导入keras深度学习库
from tensorflow import keras
# 导入OpenCV计算机视觉库
import cv2
# 导入数据处理库
import numpy as np
# 导入物体分类模型
print("导入模型中...")
model_name = "object_classification_model.h5"
model = tf.keras.models.load_model(model_name)
print("{}模型导入完成".format(model_name))
# 图像预处理
def preprocess_img(frame):
img = tf.image.resize(frame, (96, 96)) # 重置尺寸
img_array = keras.preprocessing.image.img_to_array(img)# 将图像转为数组
img_array = tf.expand_dims(img_array, 0) # 将图像数组增加一维,匹配模型输入
img_array = img_array/255. # 归一化
return img_array # 返回预处理后的图像数据
# 绘制分类结果
def add_data(frame,predictions):
res = frame # 获取一帧图像
box_startpoint = (30,10) # 定义坐标
class_names = ["01Apple","02Banana","03Watermelon","04Others"] # 定义分类结果
# # 在屏幕左上方,绘制各个分类结果的置信度直方图
# for idx,pred in enumerate(predictions.numpy()):
# # 绘制文字
# res = cv2.putText(res,
# str(class_names),
# (box_startpoint-20, box_startpoint+idx*40+10), #+20
# cv2.FONT_HERSHEY_SIMPLEX, 0.5,
# (0, 0, 255),
# 2,
# cv2.LINE_4)
# # 绘制直方图
# res = cv2.rectangle(res,
# (box_startpoint+70,box_startpoint+idx*40),
# (int(box_startpoint+100*np.around(predictions.numpy(),2))+70,box_startpoint+idx*40+15),
# (0,0,255),
# -1)
# 绘制直方图
res = cv2.rectangle(res,
(0,0),
(160,35),
(255,255,255),
-1)
# 在屏幕下方,绘制预测结果"predicted result :"+
res = cv2.putText(res,str(class_names),
(0,25), # coor
cv2.FONT_HERSHEY_SIMPLEX, 1,
(255, 0, 0),
2,
cv2.LINE_4)
res = str(class_names)
return res
# 初始化屏幕
window_name = 'frame'
cv2.namedWindow(window_name, cv2.WND_PROP_FULLSCREEN)
cv2.setWindowProperty(window_name, cv2.WND_PROP_FULLSCREEN, cv2.WINDOW_FULLSCREEN)
# whole_frame = np.zeros((480,800,3), dtype="uint8")
# 初始化摄像头
while True:
cap = cv2.VideoCapture(0) # 获取摄像头图像
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 240)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 320)
cap.set(cv2.CAP_PROP_BUFFERSIZE, 1)# 设置内部缓冲存储器中的帧数量
if cap is not None: # 如果没有连接摄像头,就等待
break
while True:
# 逐帧捕获摄像头的图像
ret, frame = cap.read() # ret为True或False,表示有没有读到图像,frame表示当前截取一帧的图像
img_array = preprocess_img(frame) # 对一帧图像做预处理
predictions = model.predict(img_array) # 模型预测(整体概率)
predictions = tf.nn.softmax(predictions)# 输出预测结果
new_frame = add_data(frame,predictions) # 对每一帧图像绘制分类结果
# frame=cv2ImgAddText(frame,new_frame, (10, 30),(0, 255, 0), 30)
print(new_frame)
# 显示图像
cv2.imshow('frame',frame)
# 按下熊猫键盘“A”键,退出程序
if cv2.waitKey(1) & 0xFF == ord('b'):
break
#清空显示
cap.release()
cv2.destroyAllWindows()
三、运行程序
过程视频
https://www.bilibili.com/video/BV14M411k7Kr/
小结
由于时间有限,对于程序的解释较为简单,但关于物体分类的总体操作思路不变,即“采集图像--训练模型--预测图像”,这也是很多人工智能项目普遍的操作流程。最后,希望本文能给你带来一些收获和启发,如果对相关的技术感兴趣,也欢迎作进一步研究并将你的成果开源出来。(PS:最后的最后,也感谢一下在原“智能快递柜机器人”项目中一起研讨并提供help的小伙伴。)
{:6_213:}{:6_213:}{:6_213:} 来学习一下!看看跟二哈有什么大区别 666 想问一下楼主,K10可以做这个项目吗?
页:
[1]