Python中的运行长度编码(RLE)压缩算法教程

637 阅读5分钟

Python中的运行长度编码(RLE)压缩算法

运行长度编码是一种无损的数据压缩算法。它通过减少重复的、连续的数据来压缩数据,这些数据被称为运行。它是通过存储这些运行的数量,然后再存储数据来实现的。

在这篇文章中,我们将学习更多关于压缩算法的知识,深入了解实现RLE算法并了解其性能。

前提条件

要继续学习本教程,读者应该具备以下条件。

  1. 对Python有基本了解。
  2. 熟悉基于笔记本的界面,如Google Colab。也可以使用普通的Python文件。

简介

在了解RLE之前,让我们先看看几个例子。

  1. 对于文本AAAAAAAAAAAAAHHHEEM (19个字符),RLE将其编码为13A3H2EM (7个字符)。
  2. 对于文本AAAAHHHEEM, HAHA. ,它将被编码为4A3H2E1M1,1 1H1A1H1A1. (21个字符)。

从这些例子中,我们看到RLE适合于用少量的运行来压缩大量的数据,例如,图像像素信息。这是因为短的运行可能最终会占用相同的空间,甚至更多,正如我们在第二个例子中看到的那样。

压缩

这是一个使用算法减少文件大小的过程,所产生的文件比原始文件使用更少的存储位。

  1. 在一个人想向他/她的朋友发送一张图片的情况下,压缩将在源设备上完成,并在目标设备上解压。这使文件能够更快地被发送,并减少了传输数据的开销流量。
  2. 在WhatsApp等社交媒体应用程序中,我们注意到,收到的图像质量较低,消耗的空间也小得多。对于一些应用程序,我们可以设置要下载的媒体的质量。
  3. 我们还注意到,在视频流网站上的压缩,在互联网连接不畅时,视频以低质量加载。

压缩算法的类型

压缩算法有两个主要分类类型。

1.无损算法

当信息质量非常重要时,就会使用无损算法。我们试图避免图像质量的损失。

这些过程是可逆的,而且它们的压缩率很低,因为我们不会损失任何信息。

例子包括运行长度编码(RLE)、Huffman编码、算术编码Shannon-Fanno编码等。

压缩率--我们通过将压缩前的大小和压缩后的大小相除得到这个比率。(Size before compression/Size after compression)。

2.有损算法

在质量可能受到影响的地方,我们使用有损算法。在这里,我们实现了高的压缩率,因此有更大的尺寸减少。

有损压缩过程是不可逆的,这与无损压缩算法的过程不同。

实施

让我们跳到Python代码中。

创建一个新的笔记本,在第一个单元格中添加以下代码。

def encode_message(message):
    encoded_string = ""
    i = 0
    while (i <= len(message)-1):
        count = 1
        ch = message[i]
        j = i
        while (j < len(message)-1): 
        '''if the character at the current index is the same as the character at the next index. If the characters are the same, the count is incremented to 1'''    
            if (message[j] == message[j + 1]): 
                count = count + 1
                j = j + 1
            else: 
                break
        '''the count and the character is concatenated to the encoded string'''
        encoded_string = encoded_string + str(count) + ch
        i = j + 1
    return encoded_string

上面的代码包含一个函数encode_message() ,参数为message (字符串),要进行编码。

变量,encoded_string ,用于存储编码后的字符串。while 循环以1 (一个索引)的计数初始化,并循环浏览整个信息。最里面的while 循环检查当前索引的字符是否与下一个索引的字符相同。

如果字符相同,计数就会递增到1 。如果不相同,计数和字符就会串联到encoded_string 变量中并返回。

接下来,我们必须写一个函数来解码编码的信息。创建一个新的单元格并粘贴这个代码。

def decode(our_message):
    decoded_message = ""
    i = 0
    j = 0
    # splitting the encoded message into respective counts
    while (i <= len(our_message) - 1):
        run_count = int(our_message[i])
        run_word = our_message[i + 1]
        # displaying the character multiple times specified by the count
        for j in range(run_count):
            # concatenated with the decoded message
            decoded_message = decoded_message+run_word
            j = j + 1
        i = i + 2
    return decoded_message

函数decode() ,接收包含编码信息的参数our_message 。变量decoded_message 存储解码后的字符串。

while 循环用于将编码后的信息分离成各自的计数run_count ,以及字符run_word ,直到完成。

它包含一个for 循环,用于多次显示由计数指定的字符(run_count)以形成一个字符串。然后,该字符串与decoded_message 变量相连接。这样持续下去,直到解码后的字符串被完整地显示出来。

最后,我们编写显示我们所写内容的方法。再次打开一个新的单元格,添加以下内容。

def display():
    # the original string
    our_message = "AuuBBBCCCCCCcccccCCCCCCCCCA"
    # pass in the original string
    encoded_message=encode_message(our_message)
    # pass in the decoded string
    decoded_message=decode_message(encoded_message)
    print("Original string: [" + our_message + "]")
    print("Encoded string: [" + encoded_message +"]")
    print("Decoded string: [" + decoded_message +"]")

函数,display() ,有要编码和解码的字符串。

然后我们为这个过程调用两个方法。我们将原始字符串传给encode_message() 函数。编码后,它被存储在encoded_message 变量中。

编码后的信息,encoded_message ,被传递给decode_message 函数进行解码。此后,解码后的信息被存储在decoded_message 变量中。

输出将如下图所示。

Original string: [AuuBBBCCCCCCcccccCCCCCCCCCA]
Encoded string: [1A2u3B6C5c9C1A]
Decoded string: [AuuBBBCCCCCCcccccCCCCCCCCCA]

时间复杂度

与其他无损算法相比,该算法的复杂度为O(n) ,如Huffman的复杂度为O(nlogn) ,它的计算成本比RLE高。

结论

最后,我们已经了解了什么是压缩,压缩的类型,运行长度编码算法,以及它在Python中的实现。

编码愉快