实验5 AI实验箱应用之贝叶斯
一、实验目的
1. 用实验箱的摄像头拍摄方块上数字的图片,在图像处理的基础上,应用贝叶斯方法识别图像中的数字并进行分类。
二、实验内容和步骤
1. 应用实验箱机械手臂上的摄像头拍摄图像;
2. Opencv处理图像;
3. 用贝叶斯方法识别处理后图像中的数字;
4. 驱动机械臂移动识别出的数字方块。
三、实验结果和分析
1. 对给出程序的主要模块添加注释,并运行完成实验步骤
程序主要模块的注释
(1)bayes_classify_movethings\img_rec\bayes_classfier.py
import numpy as np # 导入numpy库,用于数学运算 import cv2 # 导入opencv库,用于图像处理 # 图像二值化函数 def imgBinaryzation(imgs): global cv_img # 定义全局变量cv_img for i in range(len(imgs)): # 遍历图像数组 cv_img = imgs[i].astype(np.uint8) # 将图像转换为uint8类型 cv2.threshold(cv_img, 50, 1, cv2.THRESH_BINARY_INV, cv_img) # 应用阈值操作进行图像二值化 imgs[i] = cv_img # 更新原图像数组 print(cv_img.reshape(28, 28)) # 打印变换后的图像 return imgs # 返回二值化后的图像数组 # 训练贝叶斯分类器函数 def train(imgs, labels, classNum, featureNum, valueZone): priPro = np.zeros(classNum) # 初始化先验概率数组 condPro = np.zeros((classNum, featureNum, valueZone)) # 初始化条件概率数组 # 计算先验概率和条件概率 for i in range(len(labels)): # 遍历所有标签 img = imgs[i] # 获取对应的图像 label = labels[i][0] # 获取图像对应的标签 priPro[label] += 1 # 更新先验概率
for j in range(featureNum): # 遍历所有特征 condPro[label][j][img[j]] += 1 # 更新条件概率 # 对条件概率进行平滑处理 for i in range(classNum): # 遍历所有类别 for j in range(featureNum): # 遍历所有特征 total = 0 # 初始化特定特征的总计数 for k in range(valueZone): # 遍历所有可能的特征值 total += condPro[i][j][k] # 累加特定类别和特征下的特征值计数 for k in range(valueZone): # 再次遍历所有可能的特征值 # 计算平滑后的条件概率 pro_k = (float(condPro[i][j][k]) / float(total)) * 100000 + 1 condPro[i][j][k] = pro_k # 更新条件概率数组 return priPro, condPro # 返回先验概率和条件概率 # 计算特定图像和标签的概率 def cal_pro(img, label, priPro, condPro): pro = int(priPro[label]) # 获取先验概率 print("len(img): ", len(img)) for i in range(len(img)): # 遍历图像的每个特征 pro *= int(condPro[label][i][img[i]]) # 计算最终概率 return pro # 返回概率 # 分类器准确率计算函数 def classfier_acc(imgs, priPro, condPro, classNum): pred = [] # 初始化预测结果列表 for img in imgs: # 遍历所有图像 predLabel = -1 # 初始化预测标签 maxPro = -1 # 初始化最大概率 for i in range(classNum): # 遍历所有类别 pro = cal_pro(img, i, priPro, condPro) # 计算概率 if maxPro < pro: # 如果找到更大的概率 maxPro = pro # 更新最大概率 predLabel = i # 更新预测标签 pred.append(predLabel) # 将预测标签加入结果列表 print("pred: ", pred) return pred # 返回预测结果 # 单个图像分类函数 def classfier(img, priPro, condPro, classNum): pred = [] # 初始化预测结果列表 predLabel = -1 # 初始化预测标签 maxPro = -1 # 初始化最大概率 for i in range(classNum): # 遍历所有类别 pro = cal_pro(img, i, priPro, condPro) # 计算概率 if maxPro < pro: # 如果找到更大的概率 maxPro = pro # 更新最大概率 predLabel = i # 更新预测标签 pred.append(predLabel) # 将预测标签加入结果列表 print("pred: ", pred) return pred # 返回预测结果 # 准确率计算函数 def accuracyRate(pred, labels): count = 0 # 初始化计数器 for i in range(len(pred)): # 遍历所有预测结果 if pred[i] == int(labels[i][0]): # 如果预测结果与实际标签相同 count += 1 # 增加计数器 acRate = float(count) / float(len(pred)) # 计算准确率 return acRate # 返回准确率 |
(2)bayes_classify_movethings\main.py
import threading import cv2 from img_rec import img_rec from robotic_arm.my_serial import MySerial # 单片机功能选择 SINGLE_CHIP_FUNCTION_DATA = "3001070155a1ff" # 控制机械臂位置 CONTROL_ROBOTIC_ARM_POSITION_DATA = "3001070155a11131" # 控制机械臂抓取 CONTROL_ROBOTIC_ARM_GRAB_DATA = "3002070155a131" vs = cv2.VideoCapture(0) image_processing = img_rec.ImageProcessing() # 创建串口对象 my_serial = MySerial('/dev/ttyS4', baudrate=115200, timeout=1) # 创建串口接收远程 t_serial = threading.Thread(target=my_serial.receive_msg) t_serial.start() current_state = 0 # 当前状态 next_state = 0 # 下一个状态 is_grab = True # 判断是否抓取(初始是false),进行搬运需要改为true source_location = 0 # 最终搬运的源位置 # my_serial.send_msg(SINGLE_CHIP_FUNCTION_DATA + "31") while True: current_state = next_state if current_state == 0: my_serial.send_msg(CONTROL_ROBOTIC_ARM_POSITION_DATA) print("控制机械臂移动。") next_state = 1 elif current_state == 1: if my_serial.recv_msg[12:16] == "2131": print("机械臂已到达仓库1。") next_state = 2 my_serial.recv_msg = "" elif current_state == 2: print("开始拍摄照片。") for i in range(30): ret, frame = vs.read() cv2.imwrite("./pic.jpg", frame) # cv2.imshow("frame", frame) # cv2.waitKey(0) print("拍摄照片完成,照片保存在当前目录下的pic.jpg,开始识别。") image_thresh, cargo_location = image_processing.image_position(frame) cargo_location_sort = image_processing.image_sort(cargo_location) rec_result = image_processing.image_recognize(cargo_location, cargo_location_sort, frame) print("识别结束,结果为{}".format(rec_result)) if is_grab and rec_result != {}: # sorted 可以对所有可迭代的对象进行排序操作。 # sorted(iterable, key=None, reverse=False) # iterable -- 可迭代对象。 # key -- 主要是用来进行比较的元素,只有一个参数,具体的函数的参数就是取自于可迭代对象中,指定可迭代对象中的一个元素来进行排序。 # reverse -- 排序规则,reverse = True 降序 , reverse = False 升序(默认)。 # 返回值 -- 返回重新排序的列表。 list_sort = sorted(rec_result.items(), key=lambda kv: (kv[1], kv[0]), reverse=False) print("排序结束,结果为{}".format(list_sort)) source_location = list_sort[0][0] + 1 next_state = 3 else: break elif current_state == 3: my_serial.send_msg(CONTROL_ROBOTIC_ARM_GRAB_DATA + "1{}21".format(source_location)) next_state = 4 elif current_state == 4: if my_serial.recv_msg[12:16] == "4131": print("机械臂已搬运完毕。") break break else: break my_serial.THREAD_CONTROL = False |
2. 描述整个执行过程
实验步骤操作内容
(1)应用实验箱机械手臂上的摄像头拍摄图像
执行该操作时,程序会把摄像头拍摄的图像存入根目录下,并命名为pic.jpg图像。pic.jpg图像示例如下图所示:
(2)Opencv处理图像
执行该操作时,程序会利用pic.jpg图像进行图像定位(将黄色色块从整个图像中取出)、图像排序(将数字图像的位置进行排序)。
(3)用贝叶斯方法识别处理后图像中的数字
执行该操作时,程序会利用pic.jpg图像进行图像识别(对各个位置处的数 字进行分类)。分类结果会在实验箱终端进行显示,如下图所示:
(4)驱动机械臂移动识别出的数字方块
执行该操作时,程序会将识别出的4个数字分类结果进行排序,并搬运其中的最值数字方块。机械臂移动过程如下图所示:
3. 测试不同数字块,得出本次实验中数字识别的准确率
(1)每个数字的测试
待测数字方块 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
程序识别结果 | 1 | 2 | 3 | 9 | 3 | 9 | 1 | 3 | 9 |
上表中,蓝色部分为识别准确的数字,橘色部分为识别错误的数字。
因此,本次实验中数字识别的大致准确率为:4 / 9 = 44.4%
(2)一组方块的测试
测试序号 | 4个方块的内容 | 预测的4个结果 | 预测准确率 |
1 | 4513 | 9313 | 50% |
2 | 4913 | 9913 | 75% |
3 | 6193 | 6193 | 100% |
4 | 6513 | 5313 | 50% |
5 | 7513 | 1313 | 50% |
6 | 8513 | 3313 | 50% |
7 | 9913 | 4913 | 75% |
我们在实验的过程中均录制了视频,但是由于视频文件过大,无法全部发送到平台,因此此处只给出测试7的视频结果。
4. 分析准确率不高的原因,给出提高准确率的可能方法
准确率低的原因
(1)光线因素
我们在测试实验箱自带的识别应用软件中发现,在二值化图形的情况下,有些数字方块由于光线太强直接显示为白色,有些数字方块由于光线太弱直接显示为黑色。切换到RGB图形的情况时,发现光线也存在类似的情况,大致对应二值化图形情况下的内容。多次实验后,我们发现光线的强弱的确会影响识别的准确率。
(2)测试集因素
Bayes识别存在识别错误的情况可能由以下因素导致的:数字6和数字9存在中心对称的情况;数字4和数字9的拓扑结构类似,均包含一个封闭图案和半封闭图案;数字5和数字3的拓扑结构类似;数字7和数字1的拓扑结构类似;数字8的一半可以作为数字3。
(3)特征的独立性假设难以达到
朴素贝叶斯分类器基于特征之间相互独立的假设。然而,在图像数据中,像素之间通常是高度相关的。例如,在数字图像中,相邻像素往往有相关性,这违背了朴素贝叶斯的独立性假设。
(4)训练集因素
首先,如果训练数据不足或缺乏多样性,例如数字样式的差异,模型可能无法泛化到新样本。其次,在训练数据中某些数字出现得更频繁,导致模型对这些数字的识别效果更好,即存在类别不平衡。
提高准确率的可能方法
(1)均匀打光,保证每个数字方块处于同一个光照强度下。
(2)增加更多样化的训练数据,或者使用数据增强技术(如旋转、缩放、平移图像)来增加样本的多样性。
(3)使用类别平衡技术,如过采样少数类或欠采样多数类,以确保每个类别都有相似的表示。
(4)优化平滑参数,通过交叉验证来找到更优的平滑系数。
(5)改进特征提取和预处理步骤。使用更复杂的图像处理技术,如直方图均衡化、边缘检测或降维技术(如PCA),有助于提取更有意义的特征。
五、附录
1:操作系统互相连接的实验步骤
2:实验箱可使用的应用
(1)打开桌面上的“综合测试”,体验仓库货物识别及搬运功能。
(2)打开桌面上的“图像识别”,体验动物、水果、蔬菜等类别的识别。
3:WIFI连接注意事项
WIFI连接FSAIarm(屏幕右上角)。如果已经显示连接上,但仍然转圈,则点击disconnect,再重新连接自己的热点。M3配置wifi的灯一直闪烁,直到配置成功(灯处于长亮)。