前视声呐目标识别定位(六)-代码解析之目标截图并传输

前视声呐目标识别定位(一)-基础知识

前视声呐目标识别定位(二)-目标识别定位模块   

前视声呐目标识别定位(三)-部署至机器人

前视声呐目标识别定位(四)-代码解析之启动识别模块

前视声呐目标识别定位(五)-代码解析之修改声呐参数

前视声呐目标识别定位(六)-代码解析之目标截图并传输

前视声呐目标识别定位(七)-代码解析之录制数据包

前视声呐目标识别定位(八)-代码解析之各模块通信

前视声呐目标识别定位(九)-声呐驱动  

        识别目标后,截取目标框大小的图片,压缩传输。

1、test_client.py

        python3 test_client.py 7 1

elif cmd == str(7):
    print("sent capture object img cmd...")
    arrBuff = bytearray(b'\xff\xbb\xff\xbb\xee\xff\xee\xff')

        在协议文件中,启动识别并截图的协议为:

        故模块将该数据包发送至auv_server。

2、auv_server.py

def test_cmd(self):
    while True:
        self.test_conn, self.test_addr = self.test_server.accept()
        test_cmd_msg = self.test_conn.recv(1024)
        if len(test_cmd_msg)>0:
            self.conn.send(test_cmd_msg)

        直接将指令转发至center_server

3、center_server.py

# send the control_center cmd from auv to the control_center module on nx
def recv_control_center_msg(self):
    while True:          
        cmd_msg = self.nx_client.recv(1024)
        if len(cmd_msg) > 3:
            # send the control_center cmd to the control_center module
            if cmd_msg[-4:] == b'\xee\xff\xee\xff':
                self.control_center_socket.send(cmd_msg)
            # send the sonar parameters cmd to the sonar module
            elif cmd_msg[-4:] == b'\xee\xaa\xee\xff':
                self.sonar_param_socket.send(cmd_msg)
            else:
                print("cmd from auv error, no such cmd...")

        根据'\ee\ff\ee\ff'判断为不带参数的指令,转control_center.py

4、control_center.py

def rcev_cmd(self):
...

    # capture the object image and sent back to auv
    elif recvmsg[0:4] == self.capture_object_img_msg[0:4]:
        if self.capture_img_subprocess:
            self.capture_img_subprocess.kill()
            self.capture_img_subprocess = subprocess.Popen(self.capture_object_img_cmd, shell=True, executable="/bin/bash")

....

        根据'\ff\bb\ff\bb'判断为启动识别程序。

self.capture_object_img_cmd = 'ros2 topic pub --once /yolov5/capture_object_image std_msgs/msg/Bool data:\ true'

        发布/yolov5/capture_object_image。

5、yolov5_sonar.py

        监听到topic: /yolov5/capture_object_image

class Yolo_Dect(Node):
    def __init__(self):
    ...
        self.object_image_capture_sub = self.create_subscription(Bool, "/yolov5/capture_object_image", self.object_image_capture_callback, 1)
    ...

        
    def object_image_capture_callback(self, msg):
        if msg.data:
            self.object_image_capture_flag = True

        获取截图数据:

def image_callback(self, image):
    ...
    # capture the image to transport
    if self.object_image_capture_flag:
        self.image_capture = np.frombuffer(image.data, dtype=np.uint8).reshape(
                image.height, image.width, -1)
        self.capture_image_h = image.height
        self.capture_image_w = image.width
        self.capture_image_channel = len(image.data) / (image.height * image.width)

     逐个将目标截图并压缩编码,每个目标截图长度和宽度均不小于300像素,通过image_min_length设置,通过image_quality(0-100)可以设置压缩图像的质量,质量越小,压缩后的图片大小越小,然后传输。

        协议文件中,目标图片的协议为:

def dectshow(self, org_img, boxs, sonar_azimuth, sonar_range):
    ...
    # tcp transport the cut and compressed object images data
    # ensure get the image
    if self.capture_image_h * self.capture_image_w > 0:
        object_image_num = len(self.objects_azimuth_range.object_azimuth_range)
        # ensure object in the image
        if object_image_num > 0:
        #if object_image_num > 1:   #ensure several object for test
            try:                    
                object_image_count = 0
                for object_a_r in self.objects_azimuth_range.object_azimuth_range:
                    # cut the object in the image
                    if object_a_r.xmax - object_a_r.xmin < (self.image_min_length / 2):
                        cut_xmin = int((object_a_r.xmin + object_a_r.xmax) / 2.0 - self.image_min_length / 2)
                        cut_xmax = int((object_a_r.xmin + object_a_r.xmax) / 2.0 + self.image_min_length / 2)
                    else:
                        cut_xmin = int(object_a_r.xmin - 50)
                        cut_xmax = int(object_a_r.xmax + 50)

                    if object_a_r.ymax - object_a_r.ymin < (self.image_min_length / 2):
                        cut_ymin = int((object_a_r.ymin + object_a_r.ymax) / 2.0 - self.image_min_length / 2)
                        cut_ymax = int((object_a_r.ymin + object_a_r.ymax) / 2.0 + self.image_min_length / 2)
                    else:
                        cut_ymin = int(object_a_r.ymin - 50)
                        cut_ymax = int(object_a_r.ymax + 50)
                    cut_image = self.image_capture[max(0, cut_ymin) : min(self.image_capture.shape[0], cut_ymax), max(0, cut_xmin) : min(self.image_capture.shape[1], cut_xmax)]
                            
                    # get the class, probability, azimuth and range of the object
                    img_buff = bytearray(b'\xff\xbb\xff\xbb')
                    img_buff += bytearray(object_image_num.to_bytes(4, byteorder='little'))
                    img_buff += bytearray(object_image_count.to_bytes(4, byteorder='little'))
                    object_class = self.object_name[object_a_r.class_name]
                    img_buff += bytearray(object_class.to_bytes(4, byteorder='little')) 
                    img_buff += struct.pack('<f', object_a_r.probability) 
                    img_buff += struct.pack('<f', object_a_r.object_azimuth)
                    img_buff += struct.pack('<f', object_a_r.object_range)

                    # get the height, width and channel of the object image
                    cut_img_height = cut_image.shape[0]
                    cut_img_width = cut_image.shape[1]
                    cut_img_channel = cut_image.shape[2]
                    img_buff += bytearray(cut_img_height.to_bytes(4, byteorder='little')) 
                    img_buff += bytearray(cut_img_width.to_bytes(4, byteorder='little')) 
                    img_buff += bytearray(cut_img_channel.to_bytes(4, byteorder='little'))                            
                            
                    # encode the object image
                    encode_param = [int(cv2.IMWRITE_JPEG_QUALITY), self.image_quality]
                    result, encode_image = cv2.imencode('.jpg', cut_image, encode_param)
                    # get object image data length
                    cut_image_data_len = len(encode_image)
                    img_buff += bytearray(cut_image_data_len.to_bytes(4, byteorder='little'))
                    # objcet image data
                    img_buff += bytearray(encode_image)

                    #print("the trans image length is", len(encode_image))
                        
                    img_buff += bytearray(b'\xff\xb0\xff\xb0')
                    self.yolo_client.sendall(img_buff)

                    #print("sent image " + str(object_image_count))
                    object_image_count += 1
                        
                self.capture_image_h = 0
                self.capture_image_w = 0
                self.image_capture = None
                self.object_image_capture_flag = False

            except Exception as e:
                self.capture_image_h = 0
                self.capture_image_w = 0
                self.image_capture = None
                print("image transport error... ", e)

目标图片数据传输至server_center.py

6、server_center.py

# recv sonar img and send to auv
def rcv_sonar_img_msg(self):
    self.sonar_param_socket, self.sonar_param_addr = self.sonar_param_server.accept()
    while True:
        img_msg = self.sonar_param_socket.recv(65536)
        if img_msg[0:4] == b'\xff\xcc\xff\xcc':
            self.nx_client.sendall(img_msg)
        if img_msg == b'':
            self.sonar_param_socket, self.sonar_param_addr = self.sonar_param_server.accept()

目标图片传输至auv_server.py

7、auv_server.py

# receive the data from auv
def recv_msg(self):
    ...
    # object images
    if pkg_head == b'\xff\xbb\xff\xbb':
        # object num in one image capture
        object_num = struct.unpack('i',recv_msg[4:8])[0]

        # current object info in the objects of the captured image
        object_info = object()
        cur_object_num = struct.unpack('i',recv_msg[8:12])[0]
        object_info.object_class = struct.unpack('i', recv_msg[12:16])[0]
        object_info.object_probability = struct.unpack('f', recv_msg[16:20])[0]
        object_info.object_azimuth = struct.unpack('f', recv_msg[20:24])[0]
        object_info.object_range = struct.unpack('f', recv_msg[24:28])[0]
        self.recv_images.object_info.append(object_info)
        # current object image info
        img_height = struct.unpack('i',recv_msg[28:32])[0]
        img_width = struct.unpack('i',recv_msg[32:36])[0]
        img_channel = struct.unpack('i',recv_msg[36:40])[0]
        img_data_len = struct.unpack('i',recv_msg[40:44])[0]

        img_data = recv_msg[44:44 + img_data_len]
        pkg_end = recv_msg[44 + img_data_len : 48 + img_data_len]
        #print(pkg_end)

        if pkg_end == b'\xff\xb0\xff\xb0':
            self.recv_images.object_image_data.append(img_data)

        if self.object_count < object_num:
            self.object_count += 1
                
        if self.object_count == object_num:
            self.display_image_flag = True
            self.object_count = 0

最后通过display_objects_image展示目标图片。

此外关于目标识别模块,还有一个功能是实时将目标的信息传输给auv辅助导航,目标信息的协议参见协议文件。

为了看log调试方便,这个功能我注释掉了,如果不需要图片信息的话,可以将其打开,在yolov5_sonar.py中:

# self.yolo_client.sendall(pkg_buff)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/518361.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

51单片机实验02- P0口流水灯实验

目录 一、实验的背景和意义 二、实验目的 三、实验步骤 四、实验仪器 五、实验任务及要求 1&#xff0c;从led4开始右移 1&#xff09;思路 ①起始灯 &#xff08;led4&#xff09; ②右移 2&#xff09;效果 3&#xff09;代码☀ 2&#xff0c;从其他小灯并向右依…

服务器设置了端口映射之后外网还是访问不了服务器

目录 排查思路参考&#xff1a; 1、确认服务是否在运行 2、确认端口映射设置是否正确 3、使用防火墙测试到服务器的连通性 4、检查服务内部的配置 5、解决办法 6、学习小分享 我们在一个完整的网络数据存储服务系统设备中都会存有业务服务器、防火墙、交换机、路由器&a…

【Laravel】09 用模型批量赋值简化代码 数据库关系

【Laravel】09 用模型批量赋值简化代码 & 数据库关系 1. 用模型批量赋值简化代码2. 数据库关系 1. 用模型批量赋值简化代码 原来存储一个值 2. 数据库关系 这里可以看到两个SQL是一样的

STM32之HAL开发——不同系列SPI功能对比(附STM32Cube配置)

不同系列STM32——SPI框图 F1系列框图 F4系列框图 TI模式时序图特性 F7系列框图 H7系列框图 注意&#xff1a;F7系列以及H7系列支持Quad-SPI模式&#xff0c;可以连接单&#xff0c;双或者四条数据线的Flash存储介质。 SPI——Cube配置流程 RCC时钟源配置 SYS系统调试模式配…

Spring 详细总结

文章目录 第一章 IOC容器第一节 Spring简介1、一家公司2、Spring旗下的众多项目3、Spring Framework①Spring Framework优良特性②Spring Framework五大功能模块 第二节 IOC容器概念1、普通容器①生活中的普通容器②程序中的普通容器 2、复杂容器①生活中的复杂容器②程序中的复…

MySQL、Oracle查看字节和字符长度个数的函数

目录 0. 总结1. MySQL1.1. 造数据1.2. 查看字符/字节个数 2. Oracle2.1. 造数据2.2. 查看字符/字节个数 0. 总结 databasecharbyteMySQLchar_length()length()Oraclelength()lengthB() 1. MySQL 1.1. 造数据 sql drop table if exists demo; create table demo (id …

Cesium 批量种树

1、准备树种建模 分各种级别建模LOD1-LODN 其中meta.json长这样&#xff1a; Gltf再3Dmax中导出Obj,再通过ObjToGltf的工具转换&#xff0c;参考 https://editor.csdn.net/md/?articleId96484597 2、准备shp点数据。&#xff08;shp中的点位就是种树的位置&#xff09; 3、准…

【并发编程】线程安全

线程安全 1. 讲一下 synchronized 关键字的底层原理 1.1 基本使用 如下抢票的代码&#xff0c;如果不加锁&#xff0c;就会出现超卖或者一张票卖给多个人 synchronized&#xff0c;同步【对象锁】采用互斥的方式让同一时刻至多只有一个线程能持有【对象锁】 其它线程再想获…

多模态AI全解析:概念、应用与风险

大家好&#xff0c;在人工智能的快速发展浪潮中&#xff0c;多模态学习作为一项革命性技术&#xff0c;正逐渐改变着我们与机器交互的方式。 自OpenAI推出ChatGPT以来&#xff0c;人工智能已经从处理单一文本输入的单模态工具&#xff0c;迈向了能够理解和生成包括文本、图像、…

【算法】【floodfill】洪水灌溉

文章目录 1. 岛屿数量2. 岛屿最大面积3. 被围绕的区域4. 太平洋大西洋水流问题5. 扫雷游戏6. 机器人的运动范围 1. 岛屿数量 &#x1f449;&#x1f517;题目链接 给你一个由 ‘1’&#xff08;陆地&#xff09;和 ‘0’&#xff08;水&#xff09;组成的的二维网格&#xff0…

查看MySQL版本的方式

文章目录 一、使用cmd输入命令行查看二、在mysql客户端服务器里查询 一、使用cmd输入命令行查看 1、打开 cmd &#xff0c;输入命令行&#xff1a; mysql --version 2、还是打开cmd&#xff0c;输入命令行&#xff1a;mysql -V (注意了&#xff0c;此时的V是个大写的V) 二、…

unity之 “Allow ‘unsafe‘ code“ 在哪里。

导入unity中的代码&#xff0c;出现如下错误&#xff0c;该如何解决&#xff1f; Unsafe code may only appear if compiling with /unsafe. Enable "Allow unsafe code" in Player Settings to fix this error 解决这个问题&#xff0c;只需要设置就可以。 设置的地…

深入理解计算机系统 家庭作业 2.80

/* 网上很多都没说清楚到底出题人是什么用意,用意就是既要又要,既要不溢出,又要不丢失精度.所以就分开处理,在丢失之前把丢失的部分保存下来,然后两部分算好再相加. 可以先看一下我的2.79题 用的是先乘后除 会溢出 符合题意 2.80要求的是先除后成 不会溢出 但会丢失精度 核…

C++中二叉搜索树的模拟实现(二叉搜索树是map,set的底层原理)

搜索二叉树 定义 搜索二叉树:左子树小于根,右子树大于根.搜索二叉树的中序序列是升序的.所以对于二叉树而言,它的左子树和右子数都是二叉搜索树 下图就是二叉搜索树 二叉搜索树的性质: 二叉搜索树的中序遍历出的数据是有序的,并且二叉树搜索树在查找某个数的时候,一般情况下…

9proxy—数据采集工具全面测评

9Proxy数据采集工具Unlock the web with 9Proxy, the top residential proxy provider. Get unlimited bandwidth, affordable prices, and secure HTTPS and Socks5 configurations.https://9proxy.com/?utm_sourceblog&utm_mediumcsdn&utm_campaignyan 前言 在当今数…

如何实现仿微信界面[我的+首页聊天列表+长按菜单功能+添加菜单功能]

如何实现仿微信界面[我的首页聊天列表长按菜单功能添加菜单功能] 一、简介 如何实现仿微信界面[我的首页聊天列表长按菜单功能添加菜单功能] 采用 uni-app 实现&#xff0c;可以适用微信小程序、其他各种小程序以及 APP、Web等多个平台 具体实现步骤如下&#xff1a; 下载…

Windows 2008虚拟机安装、安装VM Tools、快照和链接克隆、添加硬盘修改格式为GPT

一、安装vmware workstation软件 VMware workstation的安装介质&#xff0c;获取路径&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1AUAw_--yjZAUPbsR7StOJQ 提取码&#xff1a;umz1 所在目录&#xff1a;\vmware\VMware workstation 15.1.0 1.找到百度网盘中vmwa…

【Android】App通信基础架构相关类源码解析

应用通信基础架构相关类源码解析 这里主要对Android App开发时&#xff0c;常用到的一些通信基础类进行一下源码的简单分析&#xff0c;包括&#xff1a; Handler&#xff1a;处理器&#xff0c;与某个Looper&#xff08;一个线程对应一个Looper&#xff09;进行关联。用于接…

【React】React hooks 清除定时器并验证效果

React hooks 清除定时器并验证效果 目录结构如下useTime hookClock.tsx使用useTime hookApp.tsx显示Clock组件显示时间&#xff08;开启定时器&#xff09;隐藏时间&#xff08;清除定时器&#xff09; 总结参考 目录结构如下 useTime hook // src/hooks/common.ts import { u…

亚马逊AWS永久免费数据库

Amazon DynamoDB 是一项无服务器的 NoSQL 数据库服务&#xff0c;您可以通过它来开发任何规模的现代应用程序。作为无服务器数据库&#xff0c;您只需按使用量为其付费&#xff0c;DynamoDB 可以扩展到零&#xff0c;没有冷启动&#xff0c;没有版本升级&#xff0c;没有维护窗…