笔记5:函数【numpy.frombuffer()】在Carla中的使用

背景:

class SensorManager(object):
    def __init__(self, world, car):
        self.surface = None
        self.world = world
        self.car = car
        # 添加RGB相机
        blueprint_library = world.get_blueprint_library()
        self.camera_bp = blueprint_library.find('sensor.camera.rgb')
        self.camera_bp.set_attribute('image_size_x', '1280')
        self.camera_bp.set_attribute('image_size_y', '720')
        self.camera_bp.set_attribute('fov', '110')
        camera_transform = carla.Transform(carla.Location(z=50), carla.Rotation(yaw=90, pitch=-90))
        self.camera = self.world.spawn_actor(self.camera_bp, camera_transform, attach_to=self.car.ego_vehicle)
        # set the callback function
        self.camera.listen(lambda image: self._parse_image(image))       

在最后一行调用函数 

    def _parse_image(self, image):
        # print(image)                                                      # Image(frame=202, timestamp=3.459176, size=1280x720)
        # print(image.raw_data)                                             # <memory at 0x000001F86613E348>    ---   image.raw_data 是一个缓冲区对象,它包含了图像的原始数据
        # print(type(image.raw_data))                                       # <class 'memoryview'>              ---   将图片以【字节】的方式存储在【缓冲区】
        array = np.frombuffer(image.raw_data, dtype=np.dtype("uint8"))      # numpy.frombuffer 函数将缓冲区的内容转换为一个一维的 NumPy 数组,每个字节在缓冲区中对应数组中的一个元素,frombuffer 将 data 以流("以流的形式"是指将数据视为连续的字节流,而不需要按特定的数据结构或分隔符进行解析,即每次读取一个字节作为一个 ndarray 中的值,而不是读到一个分隔符为止的所有字节作为 ndarray 中的一个值)的形式读入转化成ndarray对象
        # print(array)                                                      # [0   0  13 ...  93 114 255]
        # print(len(array))                                                 # 3686400 = 1280 * 720 * 4          ---   【一张 image 有 1280*720 个像素点,每个点有四个数值 RGBA】
        array = np.reshape(array, (image.height, image.width, 4))
        array = array[:, :, :3]
        array = array[:, :, ::-1]
        self.surface = pygame.surfarray.make_surface(array.swapaxes(0, 1))
        # image.save_to_disk('imagespath/%06d.png' % image.frame)

 其中的函数【numpy.frombuffer()】的参数类型到底是什么困扰了我

查阅资料:

(1)官方文档:

(2)翻译:

          

 其中的参数【buffer】的数据类型是【buffer_like】

(3)什么是【buffer_like】:

(4)总结1:

函数 【numpy.frombuffer()】的参数buffer指代的数据类型是上面的任意一种即可,而

【carla.Image.raw_data】返回的对象的类型是【memoryview】,可作为函数的参数进行传入

(5)总结2:函数的作用

numpy.frombuffer 函数将缓冲区的内容转换为一个一维的 NumPy 数组,每个字节在缓冲区中对应数组中的一个元素,frombuffer 将 data 以流("以流的形式"是指将数据视为连续的字节流,而不需要按特定的数据结构或分隔符进行解析,即每次读取一个字节作为一个 ndarray 中的值,而不是读到一个分隔符为止的所有字节作为 ndarray 中的一个值)的形式读入转化成ndarray对象

补充:

(1)我在菜鸟教程看到这个一句话:

 (2)以及例子:

(3)我的想法:

因为函数【numpy.frombuffer()】的参数 buffer 的可接受数据类型中没有【str】,所以要想将【str 】类型的数据传入函数【numpy.frombuffer()】中,就必须先将其转化为函数可接受的数据类型,例如【bytes】

同时,【str】类型在内存中的存储方式是【Unicode编码】形式,而不是【类似于内存缓冲区】的类型,内存缓冲区中存储的数据应该是以字节方式存在的,所以str类型的数据很明显不满足这个条件,所以直接传入 str 数据作为参数 buffer 的话,不符合函数 frombuffer() 的功能,因为这个函数是以字节流的方式读取数据的,每次读取一个字节,对于Unicode编码形式的字符串,一次读取一个字节很显然会破坏 str 本身存储的信息,使其变成无意义的一堆十进制数字

所以才需要【s = b'Hello World' 】,在前面加【b】,可以直接将【字符串】转化为【字节串】,这样【Hello World】在内存中的存储方式由【Unicode编码】变为【字节串】,即里面的英文字母的存储由【Unicode编码】变为【Ascii编码(ASCII编码本身就是一个字节大小)】

(4)关于【字符串】和【字节串】的细节:

1.在Python3中,【字符串】在内存中默认以【Unicode编码】形式存储

                           【字节串】在内存中默认以【字节】形式存储

2.字符串和字节串是不同的数据类型,用于处理不同类型的数据。

       1)字符串用于表示【文本数据】

       2)字节串用于表示【二进制数据】

    它们的存储方式和表示内容有所区别,但可以相互转换

3.更细节内容看图:

 

 总结:

        1)【btypes】类型的数据:

使用【字节方式存储】,即这样类型的数据在内存中存储时,是按照一个一个字节的方式存储的,字节之间相互独立互不干扰,一个字节代表一个独立的十进制数字

我们可以很容易的理解,他这样的存储方式【不适合进行 “文本内容” 的存储】,因为往往一个汉语文字的unicode编码可不止一个字节,但是把这个文字转化为字节存储的话,那么这两个字节之间相互独立,可能两个字节合起来可以读出【“好”】这个字,但是分开存储的字节只能读出【255】【8】这样的两个毫不相干的十进制数字

所以字节类型的存储方式适用于如图像、音频、视频、网络传输数据等这种情况,字节串中的每个字节可以表示任意的二进制数据,没有具体的字符含义,字节串可以进行字节级别的处理操作,如切片、索引、拼接等

        2)【str】类型的数据:

使用【Unicode编码方式存储】,世界上的每一个文字都有它对应的独一无二的Unicode编码,而unicode编码方式有很多中,如UTF-8、UTF-16和UTF-32等,以UTF-32举例,每个字符都要有四个字节表示,所以在内存中str类型的数据存储的时候,字节之间并不是独立的,而是四个字节为一单位存储,读取的时候也是四个字节为一单位读取,这样就可以一口气读取四个字节的内容,进而就知道了他表示的是哪个字符。当我们创建一个字符串对象时,Python会将该字符串转换为Unicode代码点的序列,并以这种形式在内部存储字符串的内容。这意味着字符串对象内部存储的是字符的抽象表示,而不是它们的字节表示

我们可以很容易的理解,他这样的存储方式【不适合进行 “大批量无意义数据” 的存储】,否则对内存的压力太大了,要找到连续的,整块的空间来存储数据

所以它可以表示文本数据,包括字母、数字、符号和特殊字符等,字符串可以进行文本处理操作,如拼接、切片、查找、替换等

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值