回到首页 返回首页
回到顶部 回到顶部
返回上一页 返回上一页

【DF冬季AI挑战赛第三轮】二哈眼中的编码世界 简单

头像 kylinpoet 2020.03.31 855 1

步骤1 前言

既然前两轮都是信息编码的思路。那么最后一轮也以编码作为结束。第一轮我们认识了区位码,第二轮介绍了旗语系统,第三轮和大家分享下base16编码。

base16、base32、base64编码都属于一个差不多的概念,它们将ASCII字符集中可打印的字符(数字0~9和字母A~Z等)对应的二进制字节数据进行编码,好处非常明显,对于传输二进制文件来说,用它们进行编码的信息,可以很容易并且不丢失地进行传输。

其中base16编码方式最简单,它用0-9,ABCDEF这十六个字符进行编码,非常方便识别。唯一的问题是用它进行编码后,信息的大小会变成原来的两倍。

project-image

步骤2 原理介绍

Base16的编码方式:

1.将数据(根据ASCII编码,UTF-8编码等)转成对应的二进制数,不足8比特位高位补0.然后将所有的二进制全部串起来,4个二进制位为一组,转化成对应十进制数.

2.根据十进制数值找到Base16编码表里面对应的字符.Base16是4个比特位表示一个字符,所以原始是1个字节(8个比特位)刚好可以分成两组,也就是说原先如果使用ASCII编码后的一个字符,现在转化成两个字符.数据量是原先的2倍.

project-image

步骤3 实现

既然要使用16个字符进行编码,那么编码的字符从哪里来呢?本来李工在3月31号发布了二哈的0.49物体分类固件的时候是相当兴奋的,正好可以手动选择有趣的内容进行编码。第一个想法是用灯带的四盏灯2^4正好16种状态来表示,应该会相当简单,无奈白色的LED干扰太大,只好作罢。后来想生动点,搞了这样的编码信息。

project-image

准备16个内容进行区分,可以识别率太低,又只好放弃。最后,只能重新刷回0.47固件,选用了官方提供的35个二维码标签识别。

PS:从这35个标签来看。二哈的图像识别用的是全连接神经网络,而不是卷积神经网络,不知道猜测对不对。

project-image

选用16个标签作为编码主体,2个标签作为控制位,3个标签作为开始结束位,共使用21个标签。(最主要是mind+的窗口放不下了)。

具体的实现方式是:

1.将想要传输的内容进行编码。

2.将编码的字符串按8个字符为一组,通过不同的二维码标签表示相应的0-9,A-F字符

3.二哈进行识别,将这8个字符传到接收端

4.接收端进行字符组合。

请看下图。

project-image
project-image

全景图:

project-image

每个精灵的代码,内容都差不多。主要是由于排列位置的不同,选用的是以8个字符为批次的不同位置的字符。

project-image

接收端在树莓派上进行,

project-image
代码
#!/usr/bin/python3
# -*- coding: utf-8 -*-

from time import sleep
from huskylensPythonLibrary import HuskyLensLibrary
from base64 import b16decode

b16_table = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', 'A', 'B', 'C', 'D', 'E', 'F']
hu = HuskyLensLibrary("I2C", "", address=0x32)
encode_str = ''
control_flag = 0
while 1:
    ret_learned = hu.command_request_blocks_learned()
    if len(ret_learned) == 10:
        # 返回的顺序不合要求,自行排序
        ret_learned.sort(key=lambda x: x[1])
        ret1 = sorted(ret_learned[:4], key=lambda x: x[0])
        ret2 = sorted(ret_learned[4:8], key=lambda x: x[0])
        ret3 = ret_learned[-2:]
        ret_learned = ret1 + ret2 + ret3
        if ret_learned[-1][4] == 18:
            continue
        elif ret_learned[-1][4] == 20:  # 最后一位是控制位,20是停止位标签
            break
            pass
        elif ret_learned[-1][4] == 19:  # 19表示开始
            # 如果接收信息,ret_learned的长度应该是 10
            if control_flag != ret_learned[8][4]:  # index 8 是控制位
                for rec in ret_learned[:-2]:
                    # 第index 4 位是标签,前面的0-3是矩形框位置
                    # 这里为了方便计算,就不判断位置了
                    encode_str = encode_str + b16_table[rec[4]]
                    control_flag = ret_learned[8][4]  # index 8 是控制位
    sleep(0.3)
print(b16decode(encode_str).decode('utf-8'))

其中的一个插曲是二哈识别标签后返回的内容是按照标签的识别先后的ID进行排序的。而本人的8个二维码标签是从左到右,从上到下顺序排列的。在这里坑了一会儿。排查到原因后,用如下方式,按照每个二维码框的中心位置的(xcenter,ycenter)值进行排序。

project-image
project-image

步骤4 过程演示

project-image

字符串:AI冬季赛第三轮

base16编码为:4149E586ACE5ADA3E8B59BE7ACACE4B889E8BDAE

二维码标签:8个字符为一组排列传输

除了传输文字,编码器还可以用来传输图片:

当然,用同样的方法,也是可以传递语音的。这里就不演示了。

完整代码如下:

万物皆可字符!

评论

user-avatar
  • hacker_

    hacker_2023.05.10

    666

    0