数字图像处理 冈萨雷斯 第三版 8.18题
一个简单的解题脚本(Python)
import warnings
import numpy as np
def arith_decode(code_map, encoded_num):
assert 0 < encoded_num < 1, f"encoded_num:{encoded_num} not in (0,1)"
codes = [''] + list(code_map.keys())
acc_values = np.cumsum([0.] + list(code_map.values()))
def init_idxes():
nonlocal lower_idx, mid_idx, upper_idx
mid_idx = len(codes) >> 1
lower_idx = 0
upper_idx = len(codes) - 1
lower_idx, mid_idx, upper_idx = 0, 0, 0
init_idxes()
decode_idxes = np.empty(0xff, dtype=np.int8)
# Binary search
for decode_idx in range(0xff):
while upper_idx - lower_idx > 1:
if acc_values[mid_idx] < encoded_num <= acc_values[upper_idx]:
lower_idx = mid_idx
mid_idx = (mid_idx + upper_idx) >> 1
elif acc_values[lower_idx] <= encoded_num <= acc_values[mid_idx]:
upper_idx = mid_idx
mid_idx = (mid_idx + lower_idx) >> 1
else:
raise RuntimeError(
f"encoded_num:{encoded_num} not in ({acc_values[lower_idx]},{acc_values[upper_idx]})")
decode_idxes[decode_idx] = upper_idx
if codes[upper_idx] == '!':
# Reach the end
decode_idxes = decode_idxes[:decode_idx + 1]
break
# Shrink the range
acc_values = (acc_values - acc_values[0]) / (acc_values[-1] - acc_values[0]) * (
acc_values[upper_idx] - acc_values[lower_idx]) + acc_values[lower_idx]
# Check the range
min_gap = 1e-15 * (len(codes) - 1)
if acc_values[-1] - acc_values[0] < min_gap:
warnings.warn(
f"acc_vec[-1] - acc_vec[0] = {acc_vec[-1] - acc_vec[0]} is smaller than {min_gap}", RuntimeWarning)
decode_idxes = decode_idxes[:decode_idx + 1]
break
init_idxes()
decode_res = ''.join([codes[idx] for idx in decode_idxes])
return decode_res
if __name__ == '__main__':
code_map = {'a': .2, 'e': .3, 'i': .1, 'o': .2, 'u': .1, '!': .1}
encoded_num = 0.32256
print(arith_decode(code_map, encoded_num))
运行结果:eeoe!