ROV采集与通信系统之上位机设计

前言

时间一晃,我已经是一名即将步入研三的老学长,趁着这个假期抓紧时间把毕业设计的大体框架完成,后续细节的优化工作再慢慢处理。毕设的课题是ROV采集与通信系统,简单来说就是ROV水下实时采集高清图像信息及各种传感器数据,通过光纤传输至水上经DDR3进行缓存,最后通过千兆以太网上传至上位机进行数据的可视化操作。整体的工作量相对来说还是比较大的,硬件部分设计会在之后的博客进行更新,今天主要来谈一下上位机设计,主要介绍udp数据的接收、图像数据的显示、传感器数据的可视化分析三部分。

UDP数据的接收

udp—–数据报文协议,是一个无连接的简单的面向数据报的运输层协议,UDP不提供可靠性,他只是将应用程序传送给IP层的数据报文发送出去,并不保证能否达到目的地。由于UDP在传输的过程中不需要和服务器建立链接。且没有超时重发的的机制。故而传输速率较快,非常适合作为图像传输的方式。
udp数据的接收部分代码相对固定化,下面直接上代码:

 def udp_connect(self):
 	 # 创建套接字
	 udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
	 #local_addr = ('192.168.0.3', 8080)
	 # 绑定本地的相关信息,如果一个网络程序不绑定,则系统会随机分配,下面是从pyqt5的文本框中获取ip地址 和端口号
	 local_addr = (str(self.ui.lineEdit_2.text()), int(self.ui.lineEdit.text()))
	 udp_socket.bind(local_addr)
	 #关闭套接字
	 udp_socket.close()

图像数据的显示

图像的显示此部分比较闹心,当时查阅资料并没有发现有关与RGB格式的图像数据流接收显示这部分内容,有的大多是服务器和客户端都采用Python实现,传输的视频流格式多是JPIE。由于传输数据是二进制流数据,所以客户端把需要传输的数据编码成二进制码流,服务器接收到再解码进行显示。
那么我的这个设计该怎么实现的图像显示呢???

  1. 像素点摆放
    按像素点顺序一个像素一个像素摆放,当一帧图像的像素全部摆放完成,那么这帧数据也就成功显示出来。首先进行测试的是RGB565格式的图像数据,一个udp数据包传输一行图像数据,开头两字节为图像的行号。代码如下所示:

    for y in range(480): 					# 接收一帧图像数据
        data, addr = udp_socket.recvfrom(1282) 
        data_list[y] = data
    # 创建一个三维数组,填充图像数据后准备成像    
    picture = np.zeros((480, 640, 3), dtype=np.uint8)
    
    for y in range(480):
    	linenumber = (data_list[y][0] << 8) + data_list[y][1]
            for x in range(640):
            	# 由于上传图像数据格式为RGB565,即两个字节表示一个像素值,所以需要进行通道分离,这里运用到RGB568——RGB888的方法:采用移位方式实现高位对齐;低位补零。
                picture [linenumber, x] = [((data_list[y][2*x+2])& 0xF8), ((((data_list[y][2*x+2])& 0x07) <<3) + (data_list[y][2*x+3]& 0xE0) >> 5)<<2, ((data_list[y][2*x+3])& 0x1F)<<3]         
    # 调用Image将数组转换为图像
    img = Image.fromarray(data5, 'RGB')
    # 显示图像
    img.imshow()  
    

    按像素点实现还有一种函数可采用,上代码:

    def draw_picture(self):
        self.image = QtGui.QImage()
        self.im = Image.open("timg.jpg")
        im_1 = self.im.resize((640, 480))#缩放
        im_2 = Image.new("RGB",(640,480))#创建图片
        
        for x in range(640):
            for y in range(480):
                im_2.putpixel((x, y),(255,255,0))
    
  2. 单通道函数显示黑白图像
    为什么会有第2小节呢? em em em,还不是因为第一种没有成功…
    这种结果其实也在意料之中,虽然C和C++的图像成像的确有这种方式,但是由于C和C++的执行效率远超Python,所以这种成像方式虽比较费事,也在承受范围之内。Python就不一样了,640*480分辨率的图像按像素操作要执行30多万次,结果可想而知。即使这样也不能放弃哈,因为Python最大的优势就行集成度高,拥有大量的现成函数可用。
    现在进行测试的是单通道的图像数据,同样是一个udp数据包传输一行图像数据,开头两字节为图像的行号。代码如下所示:

    while True:
            frame_data, addr = self.udp_socket.recvfrom(642)  # 接收数据
            if((frame_data[0]<<8)+frame_data[1] == 1):		  # 按行号接收一帧分辨率为640*480的图像数据
                break
        for y in range(479):
            row_data, addr = self.udp_socket.recvfrom(642)    # 接收数据
            frame_data = frame_data +row_data
        print('ok')
    	# 数组拷贝
        frame_list = list(frame_data)
    	self.video_display()								 # 图像显示
    	
    def video_receiving(self):
        frame = np.array(frame_list).reshape(480,642)	     # 将数组转换为二维矩阵进行图像显示前的准备工作
        frame_img = Image.fromarray(np.uint8(frame), 'L')    # L代表每个像素8bit的灰度图
        # im_1 = new_im.resize((320, 240))  # 缩放
        self.image = ImageQt.toqpixmap(frame_img)
        self.image.imshow()
    
  3. 三通道函数显示彩色图像
    话不多说,直接上彩色图像的参考代码,如下所示:

    def draw_color_image(self):
        h, w = 640, 480
        data = np.zeros((w, h, 3), dtype=np.uint8)
        print(data)
        data[240, 320] = [255, 255, 0]
        img = Image.fromarray(data, 'RGB')
    
  4. 图像放置在pyqt5的Label中
    要想将不同类生成的图像放置在pyqt5的Label中显示,首先需要将不同类的图像进行转换为QPixmap格式,然后调用函数就能成功显示。代码如下所示:

    # PIL Image 与 pyqt5中Qimage互转
    # self.image = ImageQt.toqimage(im_2)
    self.image = ImageQt.toqpixmap(im_2)
    self.ui.label_11.setPixmap(self.image)
    
    # 调用QPixmap将本地图片显示至Label
    pixmap = QtGui.QPixmap("timg.jpg").scaled(640,480)
    self.ui.label_11.setPixmap(pixmap)
    

传感器数据的可视化分析

这部分后续更新

你可能感兴趣的:(Python)