run-length 編碼和解碼

run-length 編碼和解碼

來自專欄 Algo. & Data

Contact me:

Blog : cugtyt.github.io/blog/i

Email: cugtyt#qq.com, cugtyt#http://gmail.com


本文的代碼來自於Run-Length Encode and Decode paulorzp。

這個run-length是一個數值只取0和1的二維矩陣,一般的用途是描述圖像的mask,比如:

看一下簡單的內容和圖像的對應:

這裡先貼出編碼和解碼的代碼,代碼來源:

def rle_encode(img): img: numpy array, 1 - mask, 0 - background Returns run length as string formated pixels = img.flatten() pixels = np.concatenate([[0], pixels, [0]]) runs = np.where(pixels[1:] != pixels[:-1])[0] + 1 runs[1::2] -= runs[::2] return .join(str(x) for x in runs) def rle_decode(mask_rle, shape): mask_rle: run-length as string formated (start length) shape: (height,width) of array to return Returns numpy array, 1 - mask, 0 - background s = mask_rle.split() starts, lengths = [np.asarray(x, dtype=int) for x in (s[0:][::2], s[1:][::2])] starts -= 1 ends = starts + lengths img = np.zeros(shape[0]*shape[1], dtype=np.uint8) for lo, hi in zip(starts, ends): img[lo:hi] = 1 return img.reshape(shape)

我們用上面的簡單例子來一步步分析編碼和解碼的過程:

編碼

  • 定義mask:

mask = np.array([ [0, 1, 1, 0], [1, 1, 1, 1], [1, 0, 0, 1] ])

mask的圖像就是上方那個簡單的圖像。

  • 扁平化

python mask.flatten()> array([0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1])

  • 首尾加0

np.concatenate([[0], mask, [0]]) > array([0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 0])

  • 每個元素與前一個元素比較,找到不同的位置

runs = np.where(mask[1:] != mask[:-1])[0] + 1 > array([ 2, 4, 5, 10, 12, 13])

  • 作差,找到所有連續1的起始位置和個數

runs[1::2] -= runs[::2] > array([ 2, 2, 5, 5, 12, 1])

至此,編碼就完成了。

code = .join(str(x) for x in runs)

注意到它這裡的起始位置是從1開始算的

解碼

  • 從字元串中分割code成list

code = code.split() > [2, 2, 5, 5, 12, 1]

  • 解出起始位置和個數

starts, lengths = [np.asarray(x, dtype=int) for x in (code[0:][::2], code[1:][::2])] > (array([ 2, 5, 12]), array([2, 5, 1]))

  • 因為python本身是從0開始計算的,所以減1取真實的起始位置和終點位置

starts -= 1 ends = starts + lengths starts, ends > (array([ 1, 4, 11]), array([ 3, 9, 12]))

  • 最後一步,恢復原數據

decode_mask = np.zeros(3*4, dtype=np.uint8) for lo, hi in zip(starts, ends): decode_mask[lo:hi] = 1 > array([0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1], dtype=uint8)

結果圖:

總結起來就是記錄所有連續1的起始位置和長度作為編碼,解碼依據這個記錄恢復就好。

推薦閱讀:

tableau 深入了解表計算
數據嗨客HackSheet | Python快速實踐指南
在Booking這樣的公司,數據科學家的日常是怎麼樣的?
數據分析入門一 k近鄰
眼動數據預處理和部分指標提取(基於DA1文件)

TAG:編碼 | 數據分析 | 圖像分割 |