发 帖  
原厂入驻New
首轮预售——FPGA软件无线电开发(全阶教程+开发板+实例源码)仅限23套!!!

[经验] 【PYNQ-Z2试用体验】基于PYNQ的神经网络自动驾驶小车-搭建神经网络

2019-3-9 22:10:07  692 PYNQ-Z2 神经网络 自动驾驶
分享
0
在之前的帖子中,我们完成了神经网络自动驾驶小车的硬件搭建与底盘控制。当小车通过WIFi无线连接到网络后,已经可以对其进行远程操控,成为一辆无线遥控小车,但是这还不够,本讲我们将为它搭建神经网络控制器,赋予它自己的思想。
本篇我们将从0开始搭建并训练一个神经网络,用它来控制小车的运动。
要训练神经网络,我们首先需要的就是训练神经网络所需的数据集。对于本作品,我们收集训练数据的思路如下:使用电脑远程控制,手动控制小车在跑道上运动,此时小车摄像头采集到的道路图像数据将发送至电脑,电脑将当前道路图像数据与当前的操控方向打包存储起来,制作成一个数据集。
为了实现这个功能,我们需要在PYNQ-Z2开发板上安装视频流服务器,使车载摄像头采集到的图像数据实时传输至电脑端。在本作品中,我使用的是一个成熟的开源软件:mjpg-streamer,从网上下载源码并编译安装后,只需运行服务器的启动脚本“start.sh”,就可以启动流服务器。
这时,在同一网段下的其他电脑,可以通过链接“pynq:8080/?action=stream”获取数据流,上位机接收数据流,并使用OpenCV重新解码为图像,进行后续处理。
上位机接收视频流的代码如下:


  1. import re
  2. from urllib.request import urlopen
  3. import cv2
  4. import numpy as np
  5. # mjpg-streamer URL
  6. url = 'http://192.168.1.103:8080/?action=stream'
  7. stream = urlopen(url)
  8.    
  9. # Read the boundary message and discard
  10. stream.readline()

  11. sz = 0
  12. rdbuffer = None

  13. clen_re = re.compile(b'Content-Length: (\d+)\\r\\n')

  14. # Read each frame
  15. # TODO: This is hardcoded to mjpg-streamer's behavior
  16. while True:
  17.       
  18.     stream.readline()                    # content type
  19.    
  20.     try:                                 # content length
  21.         m = clen_re.match(stream.readline())
  22.         clen = int(m.group(1))
  23.     except:
  24.         break
  25.    
  26.     stream.readline()                    # timestamp
  27.     stream.readline()                    # empty line
  28.    
  29.     # Reallocate buffer if necessary
  30.     if clen > sz:
  31.         sz = clen*2
  32.         rdbuffer = bytearray(sz)
  33.         rDVIew = memoryview(rdbuffer)
  34.    
  35.     # Read frame into the preallocated buffer
  36.     stream.readinto(rdview[:clen])
  37.    
  38.     stream.readline() # endline
  39.     stream.readline() # boundary
  40.         
  41.     # This line will need to be different when using OpenCV 2.x
  42.     img = cv2.imdecode(np.frombuffer(rdbuffer, count=clen, dtype=np.byte), flags=cv2.IMREAD_COLOR)
  43.     # Show Image
  44.     cv2.imshow('Image', img)
  45.     c = cv2.waitKey(1)
  46.     if c & 0xFF == ord('q'):
  47.         exit(0)
复制代码

下一步,我们还需要编写远程控制小车运动的代码,作为一个可以远程控制小车的上位机控制端。在本讲中我们使用串口对底盘进行控制,向底盘发送“F”、“B”、“L”、“R”等字符,将控制底盘做出前进、后退、左转、右转等动作。PYNQ-Z2开发板上运行ser2net程序,其作用是通过无线网络接收字符串,并使用串口将信息转发至底盘控制器。
远程控制底盘运动代码如下:

  1. import pygame
  2. from pygame.locals import *
  3. import socket
  4. import time


  5. MOTION_STOP = b'S'
  6. MOTION_FORWARD  = b'F'
  7. MOTION_REVERSE  = b'B'
  8. MOTION_LEFT     = b'L'
  9. MOTION_RIGHT    = b'R'
  10. MOTION_REVERSE_LEFT  = b'H'
  11. MOTION_REVERSE_RIGHT = b'J'
  12. MOTION_FORWARD_LEFT  = b'G'
  13. MOTION_FORWARD_RIGHT = b'I'

  14. SPEED_LEFT_FAST  = b'5'
  15. SPEED_RIGHT_FAST  = b'5'
  16. SPEED_LEFT_SLOW = b'1'
  17. SPEED_RIGHT_SLOW = b'1'

  18. class RCTest(object):

  19.     def __init__(self):
  20.         pygame.init()
  21.         window_size = Rect(0,0,100,100)#设置窗口的大小
  22.         screen = pygame.display.set_mode(window_size.size)#设置窗口模式
  23.         # initialize TCP connection
  24.         self.address = ('192.168.1.103', 8484)
  25.         self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  26.         self.s.connect(self.address)
  27.         # begin control
  28.         self.send_inst = True
  29.         self.steer()

  30.     def steer(self):

  31.         while self.send_inst:
  32.             time.sleep(0.1)
  33.             for event in pygame.event.get():
  34.                 if event.type == KEYDOWN:
  35.                     key_input = pygame.key.get_pressed()

  36.                     # complex orders
  37.                     if key_input[pygame.K_UP] and key_input[pygame.K_RIGHT]:
  38.                         print("Forward Right")
  39.                         self.s.send(MOTION_FORWARD_RIGHT)

  40.                     elif key_input[pygame.K_UP] and key_input[pygame.K_LEFT]:
  41.                         print("Forward Left")
  42.                         self.s.send(MOTION_FORWARD_LEFT)

  43.                     elif key_input[pygame.K_DOWN] and key_input[pygame.K_RIGHT]:
  44.                         print("Reverse Right")
  45.                         self.s.send(MOTION_REVERSE_RIGHT)

  46.                     elif key_input[pygame.K_DOWN] and key_input[pygame.K_LEFT]:
  47.                         print("Reverse Left")
  48.                         self.s.send(MOTION_REVERSE_LEFT)

  49.                     # simple orders
  50.                     elif key_input[pygame.K_UP]:
  51.                         print("Forward")
  52.                         self.s.send(MOTION_FORWARD)

  53.                     elif key_input[pygame.K_DOWN]:
  54.                         print("Reverse")
  55.                         self.s.send(MOTION_REVERSE)

  56.                     elif key_input[pygame.K_RIGHT]:
  57.                         print("Right")
  58.                         self.s.send(MOTION_RIGHT)

  59.                     elif key_input[pygame.K_LEFT]:
  60.                         print("Left")
  61.                         self.s.send(MOTION_LEFT)

  62.                     elif event.key == pygame.K_SPACE:
  63.                         print('Stop')
  64.                         self.s.send(MOTION_STOP)
  65.                         time.sleep(0.01)

  66.                     # exit
  67.                     elif key_input[pygame.K_x] or key_input[pygame.K_q]:
  68.                         print('Exit')
  69.                         self.send_inst = False
  70.                         self.s.send(SPEED_LEFT_FAST)
  71.                         time.sleep(0.01)
  72.                         self.s.send(SPEED_RIGHT_FAST)
  73.                         time.sleep(0.01)
  74.                         self.s.send(MOTION_STOP)
  75.                         time.sleep(0.01)
  76.                         self.s.close()
  77.                         break

  78.                 # No KEY Pressing
  79.                 elif event.type == pygame.KEYUP:
  80.                     self.s.send(SPEED_LEFT_FAST)
  81.                     time.sleep(0.01)
  82.                     self.s.send(SPEED_RIGHT_FAST)
  83.                     time.sleep(0.01)
  84.                     self.s.send(MOTION_STOP)
  85.                     time.sleep(0.01)

  86. if __name__ == '__main__':
  87.     RCTest()
复制代码

最后,我们将以上两个程序融合,并加入制作数据集的代码,数据集采集程序就编写完成了。数据集采集使用PythonNumpy库完成,将采集得到的数据集保存为“.npz”格式的数据集文件。
需要注意的是,在这里我们为了减少神经网络规模与计算量,将原640*480的彩色图像转化为320*240的灰度图像,随后设置感兴趣区域,只收集最重要的下半部分的320*120区域,以进一步缩小规模,由于道路图像元素相对简单,虽然图像信息经过大量压缩,但是用来作为指导简单路面上神经网络驾驶信息还是足够的。
数据采集源代码如下:

  1. import numpy as np
  2. import cv2
  3. import pygame
  4. from pygame.locals import *
  5. import socket
  6. import time
  7. import os
  8. from urllib.request import urlopen
  9. import re

  10. MOTION_STOP = b'S'
  11. MOTION_FORWARD  = b'F'
  12. MOTION_REVERSE  = b'B'
  13. MOTION_LEFT     = b'L'
  14. MOTION_RIGHT    = b'R'
  15. MOTION_REVERSE_LEFT  = b'H'
  16. MOTION_REVERSE_RIGHT = b'J'
  17. MOTION_FORWARD_LEFT  = b'G'
  18. MOTION_FORWARD_RIGHT = b'I'

  19. SPEED_LEFT_FAST  = b'5'
  20. SPEED_RIGHT_FAST  = b'5'
  21. SPEED_LEFT_SLOW = b'1'
  22. SPEED_RIGHT_SLOW = b'1'

  23. class CollectTrainingData(object):
  24.    
  25.     def __init__(self):

  26.         self.send_inst = True

  27.         # create labels
  28.         self.k = np.zeros((4, 4), 'float')
  29.         for i in range(4):
  30.             self.k[i, i] = 1

  31.         self.temp_label = np.zeros((1, 4), 'float')


  32.         self.address = ('192.168.1.103', 8484)
  33.         self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  34.         self.s.connect(self.address)

  35.         pygame.init()
  36.         window_size = Rect(0,0,100,100)#设置窗口的大小
  37.         screen = pygame.display.set_mode(window_size.size)#设置窗口模式
  38.         self.collect_image()

  39.     def collect_image(self):

  40.         saved_frame = 0
  41.         total_frame = 0

  42.         # collect images for training
  43.         print('Start collecting images...')
  44.         e1 = cv2.getTickCount()
  45.         image_array = np.zeros((1, 38400))
  46.         label_array = np.zeros((1, 4), 'float')

  47.         # mjpg-streamer URL
  48.         url = 'http://192.168.1.101:1010/?action=stream'
  49.         stream = urlopen(url)
  50.             
  51.         # Read the boundary message and discard
  52.         stream.readline()

  53.         sz = 0
  54.         rdbuffer = None

  55.         clen_re = re.compile(b'Content-Length: (\d+)\\r\\n')

  56.         # stream video frames one by one
  57.         try:
  58.             stream_bytes = ' '
  59.             frame = 1
  60.             while self.send_inst:
  61.                 stream.readline()                    # content type
  62.    
  63.                 try:                                 # content length
  64.                     m = clen_re.match(stream.readline())
  65.                     clen = int(m.group(1))
  66.                 except:
  67.                     break
  68.                
  69.                 stream.readline()                    # timestamp
  70.                 stream.readline()                    # empty line
  71.                
  72.                 # Reallocate buffer if necessary
  73.                 if clen > sz:
  74.                     sz = clen*2
  75.                     rdbuffer = bytearray(sz)
  76.                     rdview = memoryview(rdbuffer)
  77.                
  78.                 # Read frame into the preallocated buffer
  79.                 stream.readinto(rdview[:clen])
  80.                
  81.                 stream.readline() # endline
  82.                 stream.readline() # boundary
  83.                     
  84.                 # This line will need to be different when using OpenCV 2.x
  85.                 image = cv2.imdecode(np.frombuffer(rdbuffer, count=clen, dtype=np.byte), flags=cv2.IMREAD_GRAYSCALE)
  86.                 height, width = image.shape[:2]

  87.                 # shrink image
  88.                 size = (int(320), int(240))
  89.                 shrink = cv2.resize(image, size, interpolation=cv2.INTER_AREA)
  90.                
  91.                 # select lower half of the image
  92.                 roi = shrink[120:320,:]
  93.                
  94.                 # save streamed images
  95.                 cv2.imwrite('training_images/frame{:>05}.jpg'.format(frame), image)
  96.                 print(image.shape)
  97.                 #cv2.imshow('roi_image', roi)
  98.                 cv2.imshow('image', image)
  99.                 cv2.imshow('image_gray', roi)
  100.                 # reshape the roi image into one row array
  101.                 temp_array = roi.reshape(1, 38400).astype(np.float32)
  102.                
  103.                 frame += 1
  104.                 total_frame += 1

  105.                 # get input from human driver
  106.                 for event in pygame.event.get():
  107.                     if event.type == KEYDOWN:
  108.                         key_input = pygame.key.get_pressed()

  109.                         # complex orders
  110.                         if key_input[pygame.K_UP] and key_input[pygame.K_RIGHT]:
  111.                             print("Forward Right")
  112.                             image_array = np.vstack((image_array, temp_array))
  113.                             label_array = np.vstack((label_array, self.k[1]))
  114.                             saved_frame += 1
  115.                             self.s.send(MOTION_FORWARD_RIGHT)

  116.                         elif key_input[pygame.K_UP] and key_input[pygame.K_LEFT]:
  117.                             print("Forward Left")
  118.                             image_array = np.vstack((image_array, temp_array))
  119.                             label_array = np.vstack((label_array, self.k[0]))
  120.                             saved_frame += 1
  121.                             self.s.send(MOTION_FORWARD_LEFT)

  122.                         elif key_input[pygame.K_DOWN] and key_input[pygame.K_RIGHT]:
  123.                             print("Reverse Right")
  124.                             self.s.send(MOTION_REVERSE_RIGHT)
  125.                         
  126.                         elif key_input[pygame.K_DOWN] and key_input[pygame.K_LEFT]:
  127.                             print("Reverse Left")
  128.                             self.s.send(MOTION_REVERSE_LEFT)

  129.                         # simple orders
  130.                         elif key_input[pygame.K_UP]:
  131.                             print("Forward")
  132.                             saved_frame += 1
  133.                             image_array = np.vstack((image_array, temp_array))
  134.                             label_array = np.vstack((label_array, self.k[2]))
  135.                             self.s.send(MOTION_FORWARD)

  136.                         elif key_input[pygame.K_DOWN]:
  137.                             print("Reverse")
  138.                             saved_frame += 1
  139.                             image_array = np.vstack((image_array, temp_array))
  140.                             label_array = np.vstack((label_array, self.k[3]))
  141.                             self.s.send(MOTION_REVERSE)
  142.                         
  143.                         elif key_input[pygame.K_RIGHT]:
  144.                             print("Right")
  145.                             image_array = np.vstack((image_array, temp_array))
  146.                             label_array = np.vstack((label_array, self.k[1]))
  147.                             saved_frame += 1
  148.                             self.s.send(MOTION_RIGHT)

  149.                         elif key_input[pygame.K_LEFT]:
  150.                             print("Left")
  151.                             image_array = np.vstack((image_array, temp_array))
  152.                             label_array = np.vstack((label_array, self.k[0]))
  153.                             saved_frame += 1
  154.                             self.s.send(MOTION_LEFT)

  155.                         elif key_input[pygame.K_x] or key_input[pygame.K_q]:
  156.                             print('exit')
  157.                             self.send_inst = False
  158.                             self.s.send(MOTION_STOP)
  159.                             break
  160.                                 
  161.                     elif event.type == pygame.KEYUP:
  162.                         self.s.send(MOTION_STOP)

  163.             # save training images and labels
  164.             train = image_array[1:, :]
  165.             train_labels = label_array[1:, :]

  166.             # save training data as a numpy file
  167.             file_name = str(int(time.time()))
  168.             directory = "training_data"
  169.             if not os.path.exists(directory):
  170.                 os.makedirs(directory)
  171.             try:   
  172.                 np.savez(directory + '/' + file_name + '.npz', train=train, train_labels=train_labels)
  173.             except IOError as e:
  174.                 print(e)

  175.             e2 = cv2.getTickCount()
  176.             # calculate streaming duration
  177.             time0 = (e2 - e1) / cv2.getTickFrequency()
  178.             print('Streaming duration:', time0)

  179.             print((train.shape))
  180.             print((train_labels.shape))
  181.             print('Total frame:', total_frame)
  182.             print('Saved frame:', saved_frame)
  183.             print('Dropped frame', total_frame - saved_frame)

  184.         finally:
  185.             self.s.close()

  186. if __name__ == '__main__':
  187.     CollectTrainingData()
复制代码

使用采集程序控制小车在跑道上规范地驾驶数分钟,采集的数据集已经足够训练。

数据集制作完成,下一步就可以搭建神经网络进行训练了。
在“神经网络自动驾驶小车”的初级阶段实现里,我使用了PYNQ-Z2开发板镜像中预装的OpenCV框架中的ml机器学习模块搭建并训练神经网络。
在本作品的应用场景中,神经网络被用于分类。它的输入是数据集中的原始图像数据,输出层的类别就对应着底盘的四种运动。
由于识别目标相对简单,我们使用38400 -> 32 -> 4的单隐层神经网络,在OpenCV中,使用ml模块的ANN_MLP相关函数实现。
搭建BP神经网络,相关参数如程序所示:

  1. import cv2
  2. import numpy as np
  3. import glob

  4. print ('Loading training data...')
  5. e0 = cv2.getTickCount()

  6. # load training data

  7. image_array = np.zeros((1, 38400))
  8. label_array = np.zeros((1, 4), 'float')
  9. training_data = glob.glob('Training_Data/*.npz')

  10. for single_npz in training_data:
  11.     with np.load(single_npz) as data:
  12.         print (data.files)
  13.         train_temp = data['train']
  14.         train_labels_temp = data['train_labels']
  15.         print (train_temp.shape)
  16.         print (train_labels_temp.shape)
  17.         image_array = np.vstack((image_array, train_temp))
  18.         label_array = np.vstack((label_array, train_labels_temp))

  19. train = image_array[1:, :]
  20. train_labels = label_array[1:, :]
  21. print (train.shape)
  22. print (train_labels.shape)

  23. e00 = cv2.getTickCount()
  24. time0 = (e00 - e0)/ cv2.getTickFrequency()
  25. print ('Loading image duration:', time0)

  26. # set start time

  27. e1 = cv2.getTickCount()

  28. # create MLP

  29. layer_sizes = np.int32([38400, 32, 4])
  30. model = cv2.ml.ANN_MLP_create()

  31. model.setLayerSizes(layer_sizes)
  32. model.setTrainMethod(cv2.ml.ANN_MLP_BACKPROP)
  33. model.setBackpropMomentumScale(0.0)
  34. model.setBackpropWeightScale(0.001)
  35. model.setTermCriteria((cv2.TERM_CRITERIA_COUNT, 20, 0.01))
  36. model.setActivationFunction(cv2.ml.ANN_MLP_SIGMOID_SYM, 2, 1)

  37. print ('Training MLP ...')
  38. num_iter = model.train(np.float32(train), cv2.ml.ROW_SAMPLE, np.float32(train_labels))

  39. # set end time

  40. e2 = cv2.getTickCount()
  41. time = (e2 - e1)/cv2.getTickFrequency()
  42. print ('Training duration:', time)

  43. # save param

  44. model.save('mlp_xml/mlp.xml')

  45. print ('Ran for %d iterations' % num_iter)

  46. ret, resp = model.predict(train)
  47. prediction = resp.argmax(-1)
  48. print ('Prediction:', prediction)
  49. true_labels = train_labels.argmax(-1)
  50. print ('True labels:', true_labels)

  51. print ('Testing...')
  52. train_rate = np.mean(prediction == true_labels)
  53. print ('Train rate: %f:' % (train_rate*100))
复制代码

训练结束后,程序将训练出的模型保存。这个模型就可以直接被自动驾驶用来进行神经网络推理了。
随后,我们还需要完成交通标识识别的程序,交通标识识别的程序使用OpenCV的级联分类器,与神经网络控制器共同决定小车的运动方向。
自动驾驶程序如下:

  1. import threading
  2. import cv2
  3. import numpy as np
  4. import math
  5. import socket
  6. import re
  7. from urllib.request import urlopen
  8. from sys import exit
  9. import time


  10. MOTION_STOP = b'S'
  11. MOTION_FORWARD  = b'F'
  12. MOTION_REVERSE  = b'B'
  13. MOTION_LEFT     = b'L'
  14. MOTION_RIGHT    = b'R'
  15. MOTION_REVERSE_LEFT  = b'H'
  16. MOTION_REVERSE_RIGHT = b'J'
  17. MOTION_FORWARD_LEFT  = b'G'
  18. MOTION_FORWARD_RIGHT = b'I'

  19. SPEED_LEFT_FAST  = b'5'
  20. SPEED_RIGHT_FAST  = b'5'
  21. SPEED_LEFT_SLOW = b'1'
  22. SPEED_RIGHT_SLOW = b'1'

  23. class ObjectDetection(object):

  24.     def __init__(self):
  25.         self.red_light = False
  26.         self.green_light = False
  27.         self.yellow_light = False
  28.         self.stop_sign = False

  29.     def detect(self, cascade_classifier, gray_image, image):

  30.         # y camera coordinate of the target point 'P'
  31.         v = 0

  32.         # minimum value to proceed traffic light state validation
  33.         threshold = 150     
  34.         
  35.         # detection
  36.         cascade_obj = cascade_classifier.detectMultiScale(
  37.             gray_image,
  38.             scaleFactor=1.1,
  39.             minNeighbors=5,
  40.             minSize=(30, 30)
  41.         )
  42.         # draw a rectangle around the objects
  43.         for (x_pos, y_pos, width, height) in cascade_obj:
  44.             cv2.rectangle(image, (x_pos+5, y_pos+5), (x_pos+width-5, y_pos+height-5), (255, 255, 255), 2)
  45.             v = y_pos + height - 5
  46.             # stop sign
  47.             if width/height == 1:
  48.                 cv2.putText(image, 'STOP', (x_pos, y_pos-10), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)
  49.                 if width > 190:
  50.                     self.stop_sign = True
  51.                     print("STOP Sign")

  52.             # traffic lights
  53.             else:
  54.                 self.stop_sign = False
  55.                 roi = gray_image[y_pos+10:y_pos + height-10, x_pos+10:x_pos + width-10]
  56.                 mask = cv2.GaussianBlur(roi, (25, 25), 0)
  57.                 (minVal, maxVal, minLoc, maxLoc) = cv2.minMaxLoc(mask)
  58.                
  59.                 # check if light is on
  60.                 if maxVal - minVal > threshold:
  61.                     cv2.circle(roi, maxLoc, 5, (255, 0, 0), 2)
  62.                     
  63.                     # Red light
  64.                     if 1.0/8*(height-30) < maxLoc[1] < 4.0/8*(height-30):
  65.                         cv2.putText(image, 'Red', (x_pos+5, y_pos-5), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 2)
  66.                         if width > 70:
  67.                             self.red_light = True
  68.                             print("Red Light")
  69.                     
  70.                     # Green light
  71.                     elif 5.5/8*(height-30) < maxLoc[1] < height-30:
  72.                         cv2.putText(image, 'Green', (x_pos+5, y_pos - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2)
  73.                         if width > 70:
  74.                             self.green_light = True
  75.                             print("Green Light")
  76.                 else:
  77.                     self.red_light = False
  78.                     self.green_light = False
  79.         return v



  80. class RCControl(object):

  81.     def __init__(self):
  82.         self.address = ('192.168.1.103', 8484)
  83.         self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  84.         self.s.connect(self.address)
  85.         self.s.send(SPEED_LEFT_FAST)
  86.         time.sleep(0.01)
  87.         self.s.send(SPEED_RIGHT_FAST)
  88.         time.sleep(0.01)
  89.     def steer(self, prediction):
  90.         if prediction == 2:
  91.             self.s.send(MOTION_FORWARD)
  92.             print("Forward")
  93.         elif prediction == 0:
  94.             self.s.send(MOTION_LEFT)
  95.             print("Left")
  96.         elif prediction == 1:
  97.             self.s.send(MOTION_RIGHT)
  98.             print("Right")
  99.         else:
  100.             self.stop()

  101.     def stop(self):
  102.         self.s.send(SPEED_LEFT_FAST)
  103.         time.sleep(0.01)
  104.         self.s.send(SPEED_RIGHT_FAST)
  105.         time.sleep(0.01)
  106.         self.s.send(MOTION_STOP)
  107.         print("Stop")

  108. class VideoStream_Thread(threading.Thread):
  109.     def __init__(self):
  110.         super(VideoStream_Thread, self).__init__()
  111.         self.url = 'http://192.168.1.103:8080/?action=stream'
  112.         self.stream = urlopen(self.url)
  113.         # Read the boundary message and discard
  114.         self.stream.readline()
  115.         self.sz = 0
  116.         self.rdbuffer = None
  117.         self.clen_re = re.compile(b'Content-Length: (\d+)\\r\\n')
  118.         self.stop_cascade = cv2.CascadeClassifier('cascade_xml/stop_sign.xml')
  119.         self.light_cascade = cv2.CascadeClassifier('cascade_xml/traffic_light.xml')
  120.         self.rc_car = RCControl()
  121.         self.obj_detection = ObjectDetection()
  122.         self.model = cv2.ml.ANN_MLP_load('mlp_xml/mlp.xml')
  123.         print("model loaded")

  124.     def predict(self, samples):
  125.         ret, resp = self.model.predict(samples)
  126.         return resp.argmax(-1)

  127.     def run(self):

  128.         stop_flag = False
  129.         stop_sign_active = True

  130.         # stream video frames one by one
  131.         try:
  132.             while True:
  133.                 self.stream.readline()                    # content type
  134.                 try:                                 # content length
  135.                     m = self.clen_re.match(self.stream.readline())
  136.                     clen = int(m.group(1))
  137.                 except:
  138.                     break
  139.                 self.stream.readline()                    # timestamp
  140.                 self.stream.readline()                    # empty line
  141.                
  142.                 # Reallocate buffer if necessary
  143.                 if clen > self.sz:
  144.                     self.sz = clen*2
  145.                     self.rdbuffer = bytearray(self.sz)
  146.                     rdview = memoryview(self.rdbuffer)
  147.                
  148.                 # Read frame into the preallocated buffer
  149.                 self.stream.readinto(rdview[:clen])
  150.                
  151.                 self.stream.readline() # endline
  152.                 self.stream.readline() # boundary
  153.                
  154.                 # This line will need to be different when using OpenCV 2.x
  155.                 image = cv2.imdecode(np.frombuffer(self.rdbuffer, count=clen, dtype=np.byte), flags=cv2.IMREAD_COLOR)
  156.                 gray = cv2.imdecode(np.frombuffer(self.rdbuffer, count=clen, dtype=np.byte), flags=cv2.IMREAD_GRAYSCALE)
  157.                
  158.                 # shrink image
  159.                 size = (int(320), int(240))
  160.                 shrink = cv2.resize(gray, size, interpolation=cv2.INTER_AREA)
  161.                 # lower half of the image
  162.                 half_gray = shrink[120:240, :]

  163.                 # object detection
  164.                 v_param1 = self.obj_detection.detect(self.stop_cascade, gray, image)
  165.                 v_param2 = self.obj_detection.detect(self.light_cascade, gray, image)
  166.                 cv2.imshow("image", image)

  167.                 # cv2.imshow('image', half_gray)
  168.                 cv2.imshow('ANN_image', half_gray)




  169.                 # reshape image
  170.                 image_array = half_gray.reshape(1, 38400).astype(np.float32)
  171.                
  172.                 # neural network makes prediction
  173.                 prediction = self.predict(image_array)
  174.                 # print(prediction)

  175.                 # else:
  176.                 if self.obj_detection.stop_sign == True or self.obj_detection.red_light == True:
  177.                     self.rc_car.stop()
  178.                     if cv2.waitKey(1) & 0xFF == ord('q'):
  179.                         time.sleep(0.2)
  180.                         break
  181.                     continue

  182.                 self.rc_car.steer(prediction)


  183.                 if cv2.waitKey(1) & 0xFF == ord('q'):
  184.                     self.rc_car.stop()
  185.                     time.sleep(0.2)
  186.                     break

  187.             cv2.destroyAllWindows()

  188.         finally:
  189.             self.rc_car.s.close()
  190.             print("Connection closed on thread 1")


  191. class ThreadServer(object):
  192.     video_thread = VideoStream_Thread()
  193.     video_thread.start()

  194. if __name__ == '__main__':
  195.     ThreadServer()
复制代码

PC运行自动驾驶程序,小车就可以在跑道上自动行驶了,经过简单修改,自动驾驶程序可以同样直接运行在PYNQ-Z2开发板上,但是由于图像处理由板载双核ARM Cortex-A9处理器配合512M DDR运行,程序的控制帧率会相对有所下降。
至此,神经网络自动驾驶小车的初级实现就已经全部完成了。

a469660451 2019-6-28 23:18:23
请问是在Linux上面进行训练吗

举报

评论

高级模式
您需要登录后才可以回帖 登录 | 注册

发经验
课程
    关闭

    站长推荐 上一条 /10 下一条

    快速回复 返回顶部 返回列表