python 实现 BCH 纠错码的方法
BCH码是一类重要的纠错码,它把信源待发的信息序列按固定的κ位一组划分成消息组,再将每一消息组独立变换成长为n(n>κ)的二进制数字组,称为码字。如果消息组的数目为M(显然M>=2),由此所获得的M个码字的全体便称为码长为n、信息数目为M的分组码,记为n,M。把消息组变换成码字的过程称为编码,其逆过程称为译码。
- 我这里考虑输入是
torch.Tensor
的一个 只包含0 ,1 元素的张量 - 对于输入是numpy或者0,1字符串的方法就更简单了,总之都先要将输入处理成为 0,1字符串,例如
“1010”
- 首先构造一个输入:
import random
a = [1 for i in range(16)]
b = [0 for i in range(16)]
a.extend(b)
random.shuffle(a)
a = np.array(a)
a = torch.Tensor(a)
- 将 a 处理成为 0,1字符串:
a = str(a.numpy().tolist())[1:-1].replace('.0','').replace(',','').replace(' ','')
-
构造添加BCH码的方法
-
注意,这里我们使用的bch 生成多项式是
bin(137)
,对于多项式,我们可以在这里查找对应的多项式
-
比如bch(255,155),即码字255bits,有效载荷155bits(就是你的有效信息),bch code长度为255+1-155=101
-
但是对于bchlib是以字节为单位作为为输入的(长度为8的倍数)
-
则bch code的长度为top(101/8)*8 = 104
import bchlib
BCH_POLYNOMIAL = 137
BCH_BITS = 5
def add_bch(wm):
'''
对于 str类型:a='1010' 或者 a='0b1010'
bytearray(a, encoding='utf-8')= bytearray(b'0b1010')
对于16进制表示的二进制 ecc
''.join(format(x, '08b') for x in ecc)=str(1010)='1010'
'''
full_wm_bytes = bytes(int(wm[i : i + 8], 2) for i in range(0, len(full_wm), 8)) #将bin转化为bytes
a = bytearray(full_wm_bytes)
print(f"{len(a)}:{a}")
bch = bchlib.BCH(BCH_POLYNOMIAL, BCH_BITS)
ecc = bch.encode(a)
print(f"{len(ecc)}:{ecc}")
ecc = ''.join(format(x, '08b') for x in ecc) #使用format函数,将bytearray中存储的十进制数转换为二进制
print(f"{len(ecc)}:{ecc}")
return torch.Tensor([int(i) for i in full_wm+ecc])
- 构造BCH纠错的方法
# do error correct
def do_ec(wm):
#56位BCH校验
full_wm = str(wm.numpy().tolist())[1:-1].replace('.0','').replace(',','').replace(' ','')
bch = bchlib.BCH(BCH_POLYNOMIAL, BCH_BITS)
full_wm = bytes(int(full_wm[i : i + 8], 2) for i in range(0, len(full_wm), 8)) #将bin转化为bytes
full_wm= bytearray(full_wm)
wm = full_wm[:-bch.ecc_bytes]
#wm = bytearray(wm, encoding='utf-8')
ecc = full_wm[-bch.ecc_bytes:]
#ecc = bytes(int(ecc[i : i + 8], 2) for i in range(0, len(ecc), 8))
bitflips = bch.decode_inplace(wm, ecc)
if bitflips != -1:
try:
code = wm.decode("utf-8")
print(code)
except:
pass
print('Failed to decode')
wm = ''.join(format(x, '08b') for x in wm)
return torch.Tensor([int(i) for i in wm])
- 测试 BCH 生成
- 加入扰动和纠错
BCH_POLYNOMIAL = 137
BCH_BITS = 5
bched = new_add_bch(a)
print(f"{len(bched)}:{bched}")
bched[12:20] = 0. # add noise
wm = do_ec(bched)
print(f"{len(wm)}:{wm.detach.numpy()}")
- 输出
32:01010000011001011011100110101011
32:bytearray(b'01010000011001011011100110101011')
5:bytearray(b'\xd7\x07\xe7|\x00')
40:1101011100000111111001110111110000000000
72:tensor([0., 1., 0., 1., 0., 0., 0., 0., 0., 1., 1., 0., 0., 1., 0., 1., 1., 0.,
1., 1., 1., 0., 0., 1., 1., 0., 1., 0., 1., 0., 1., 1., 1., 1., 0., 1.,
0., 1., 1., 1., 0., 0., 0., 0., 0., 1., 1., 1., 1., 1., 1., 0., 0., 1.,
1., 1., 0., 1., 1., 1., 1., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.])
32:01010000011000000000100110101011
- 可以看到第一行和最后一行,分别对应着原始二进制串和添加扰动之后纠错的二进制串