最近一段时间和实验室同学一起做了一个本科毕设,毕设的目的是做一个智能分类垃圾桶,摄像头拍一个物体,然后自动识别这个物体属于可回收垃圾、有害垃圾还是其他垃圾,接着控制舵机打开相对应的垃圾桶盖,其实还可以做厨余垃圾,但是因为缺少数据集的问题,为了减少工作量,我就没有加入新的厨余垃圾数据集(不想自己打那么多的标哈哈哈)。
下面描述一下项目的整体流程:首先在电脑上部署yolov5的环境,我使用的是Anaconda+Pycharm,yolov5的代码使用的是github上提供的标准代码,但是为了契合我们的项目,我在detect.py文件中加了一些自己的代码,整体的yolov5代码我会附在整篇文章的最后,方便大家使用。
yolov5环境部署好之后,运行detect.py文件,这时摄像头会打开,自动弹出一个窗口,如下所示:
此时按下回车键就会自动拍摄一个照片保存到本地,然后按ESC键之后就会继续向下执行,我使用的是绝对路径,所以如果你想部署在你本地的话,还需要修改一下保存照片的路径,在detect.py文件中修改,具体如下:
output_dir = 'D:\yolov5' i = 1 cap = cv2.VideoCapture(0) while 1: ret, frame = cap.read() cv2.imshow('cap', frame) flag = cv2.waitKey(1) if flag == 13: output_path = os.path.join(output_dir, "1.jpg") cv2.imwrite(output_path, frame) i += 1 if flag == 27: break
把 output_dir = 'D:\yolov5' 修改掉就好。
上一步完成之后,yolov5会识别刚才拍的照片中的物体,然后识别出的物体类型会存在class_label变量中,紧接着这个变量会通过socket传给树莓派,树莓派接收到这个变量之后会进行一些判断,判断打开哪一个舵机。舵机开完之后,下一步树莓派会将刚才接收到的物体类型连带垃圾桶上的温度、湿度传感器信息一起通过socket传给笔记本,笔记本这边做了一个前端界面,传过来的信息会存在数据库中,这样所有的信息都会汇总起来,这样就完成了一个简单的毕设工作。
下面具体讲一下每一步的细节,并且所有的文件、代码、成品图片都会一一展示出来。
首先是yolov5代码,yolov5如何部署,网上有很多的教程,大家可以去网上搜一下,其次是我在detect.py中加了socket传输代码,如果你部署的话,这个地方就需要修改一下IP地址,修改成你接受变量数据的设备IP,比如这边我要向树莓派传输变量,那么我就填写树莓派的IP地址,端口号填写9000应该问题就不打了,代码如下:
import socket sk = socket.socket() ip_port = ("192.168.1.108", 9000) sk.connect(ip_port) sk.send(class_label.encode())
在树莓派端也要部署接收的代码,代码如下:
def talk(conn):
while 1: # 循环通讯
try:
channel = conn.recv(1024).decode('utf-8')
if not channel:
break
print("进程<%s>来自客户端的消息:%s" % (os.getpid(), channel))
checkChenel(channel)
conn.send(channel.encode('utf-8'))
except:
break
conn.close()
def socket():
import socket
print("start socket")
server_sk = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_sk.bind(('192.168.1.108', 9000))
server_sk.listen(5)
while 1:
new_sk, addr = server_sk.accept()
p = Process(target=talk, args=(new_sk,))
p.start()
server_sk.close()
这样两端就可以通信起来,从而能够传输物体类别参数。还有一个重要的问题也要注意一下,在使用socket的时候,不能单线程,得要启动一个双线程,不然就会报错,这样就得在上面这段代码下面加上一个创建新线程的代码,代码如下:
# 创建一个线程
mthread = threading.Thread(target=socket)
# # 启动刚刚创建的线程
mthread .start()
# Set frequency to 50hz, good for servos.
pwm.set_pwm_freq(50)
print('Moving servo on channel x, press Ctrl-C to quit...')
#while True:
# channel=int(input('pleas input channel:'))
# Move servo on channel O between extremes.
这样就可以正常地进行参数传输。紧接着通过以下代码来控制舵机旋转对应的角度:
def checkChenel(channel):
channel = int(channel)
if channel == 1:
set_servo_angle(channel, -15)
time.sleep(5)
set_servo_angle(channel, 110)
time.sleep(0.5)
elif channel == 2 :
set_servo_angle(channel, 60)
time.sleep(5)
set_servo_angle(channel, 170)
time.sleep(0.5)
elif channel == 3 :
set_servo_angle(channel, 60)
time.sleep(5)
set_servo_angle(channel, 170)
time.sleep(0.5)
elif channel == 4 :
set_servo_angle(channel, 60)
time.sleep(5)
set_servo_angle(channel, 170)
time.sleep(0.5)
以上部分的具体展示如下:
1.yolov5识别具体的物体属于什么类别:
此时识别出的是种类二,也就是有害垃圾,这个是在yolov5配置文件中修改的,如下图所示:
在配置的时候,这些绝对地址都需要修改,如果有报错的话,基本上都是绝对地址没有修改好,耐心检查一下就OK。
2.树莓派端接收到类别信息,控制舵机打开垃圾桶盖:
3.树莓派外界了一个温湿度传感器,打开舵机之后,树莓派会将垃圾类别信息以及外接温湿度传感器的信息汇总好,通过socket传输给专门制作的前端后台中,存入数据库之后,然后前端界面中会显示出来此次垃圾分类的类别信息和温湿度信息。
完整演示视频在我的个人空间里面,可以进去查看
智能垃圾桶演示视频
所有的代码我都汇总好了,数据集也汇总好了,有需要的可以自取。
链接:https://pan.baidu.com/s/1x26GFAkIlbUnPvW2KJ2KZw?pwd=0412
提取码:0412