今天我想与大家探讨的是一个数学和工程学中的重要概念——稀疏性。这个概念可能听起来很抽象,但它实际上贯穿于我们生活中的许多方面。那么,稀疏性到底是什么呢?简单来说,在数学和信号处理领域,一个信号被称为稀疏,指的是它在某个域(例如时间域、频率域或其他变换域)中只有少量的非零元素。
示例
我们通过两个生活中的例子来理解一下。
窗户上的泥
让我们通过一个实际例子来描绘稀疏性。假设你有一扇带有许多小玻璃窗格的窗户。一天,沙尘暴过后,只有几个窗格上沾满了泥土,而其他的还是一尘不染。这些脏窗格像是非零元素,而干净的窗格像是零元素。你的窗户在被污染的“域”上就体现了稀疏性——只有极少数的元素是“活跃”的。
观察温度
现在让我们从窗户转换到数据。想象你正在测量一天中的温度变化,并每分钟记录一次。你可能会看到温度在大多数时间里保持相对稳定,但在日出和日落时,温度会发生快速变化。如果我们把这个数据集制作成图表,大部分数据点会形成一条直线(这些点可以视为“零”值,因为它们没有信息变化),而只有在日出和日落时的那些点会因温度变化而“跳跃”出来(非零值)。
在这个例子中,24小时的温度记录在时间域上是稀疏的,因为只有相对较少的点包含大量的信息(即温度变化显著的点)。而在其他时间点,由于温度变化很小,那些数据点并没有提供太多的信息,就像我们窗户上的干净窗格一样。
稀疏性的作用
稀疏性有什么用处呢?其实,在信号处理和数据压缩中,稀疏性是极其重要的。稀疏性使我们能够只保存那些有意义的信息点,并忽略那些“零”信息点,从而有效地减少数据的大小。这就像你在清洁窗户时只需专注于脏的窗格,无需浪费时间擦拭那些已经干净的窗格。
不仅在数据存储方面,稀疏性还在图像处理、医学成像、无线通信等领域中发挥着关键作用。通过利用信号的稀疏性,科学家和工程师能够创建更加高效的算法和技术,以解决现实世界中的问题。
总结
一个信号如果在某个域具有很多“零”值,并且只有少数非零值,我们可以说它在这个域是稀疏的。这种稀疏性是极富价值的,因为它让信息处理、存储和传输更加高效。
例子
数据稀疏性指的是数据中大量元素为零或接近零,这种数据可以通过特殊的数据结构或格式存储,从而减少存储空间。一个常见的方法是运用压缩感知(Compressive Sensing)原理,或者简单地使用稀疏表示方法,例如存储非零元素的位置和值,并忽略零值元素。
下面是一个简单的例子,以及如何在Python中实现数据压缩和解压缩:
示例
例子:假设我们有一个一维数组,里面包含很多的零值元素。
原始数组:[0, 0, 0, 0, 5, 0, 0, 3, 0, 0, 0, 0, 0, 2, 0]
我们可以通过只存储非零元素的位置(索引)和相应的值来压缩这个数组:
压缩表示:[(4, 5), (7, 3), (13, 2)]
Python实现
下面是Python中的一种实现方式:
# -*- coding: utf-8 -*-
"""
Created on Tue Feb 20 09:28:40 2024
@author: 李立宗
公众号:计算机视觉之光
知识星球:计算机视觉之光
"""
def compress_data(data):
# 压缩数据
return [(index, value) for index, value in enumerate(data) if value != 0]
def decompress_data(compressed_data, total_length):
# 解压数据
data = [0]*total_length
for index, value in compressed_data:
data[index] = value
return data
# 原始数据
original_data = [0, 0, 0, 0, 5, 0, 0, 3, 0, 0, 0, 0, 0, 2, 0]
# 原始数据
print(f'original Data: {original_data}')
# 压缩数据
compressed_data = compress_data(original_data)
print(f'Compressed Data: {compressed_data}')
# 解压缩数据
decompressed_data = decompress_data(compressed_data, len(original_data))
print(f'Decompressed Data: {decompressed_data}')
执行上述代码后,你会得到以下输出,这展示了如何从原始数据中创建压缩表示,以及如何从压缩数据恢复原始数据:
original Data: [0, 0, 0, 0, 5, 0, 0, 3, 0, 0, 0, 0, 0, 2, 0]
Compressed Data: [(4, 5), (7, 3), (13, 2)]
Decompressed Data: [0, 0, 0, 0, 5, 0, 0, 3, 0, 0, 0, 0, 0, 2, 0]
注意这只是一个非常基础的压缩方式,现实世界中可能会使用更复杂的压缩算法,比如维护一个更紧凑的数据结构或使用特殊的编码技巧来进一步提高压缩率。
问题
如果说我们的数据不完美,例如,有很多数值其实是0.02这样的数据,不是0.
那他就不是稀疏的了。
这时怎么办呢?
好办,我们直接把接近于零的值处理为0就好了。
这也是一定意义上的 “压缩”了。因为,此时数据能够更好地压缩了。
Python实现
# -*- coding: utf-8 -*-
"""
Created on Tue Feb 20 09:16:15 2024
@author: 李立宗
公众号:计算机视觉之光
知识星球:计算机视觉之光
"""
import numpy as np
import matplotlib.pyplot as plt
# 生成一个稀疏信号
np.random.seed(0)
signal_length = 100
signal = np.zeros(signal_length)
non_zero_indices = np.random.choice(range(signal_length), 10, replace=False)
signal[non_zero_indices] = np.random.randn(10)
print(signal)
# 输出原始数据尺寸大小
original_size = signal.shape
print(f'Original Data Size: {original_size} bytes')
# 绘制原始信号
plt.figure(figsize=(16, 6))
plt.subplot(1, 2, 1)
plt.stem(signal, use_line_collection=True)
plt.title('Original Sparse Signal')
# 压缩信号:设置阈值并保留非零值
threshold = 0.1
compressed_signal = signal * (abs(signal) > threshold)
print(compressed_signal)
# 输出压缩后数据尺寸大小
compressed_size = compressed_signal.shape
print(f'Compressed Data Size: {compressed_size} bytes')
# 绘制压缩后的信号
plt.subplot(1, 2, 2)
plt.stem(compressed_signal, use_line_collection=True)
plt.title('Compressed Signal')
plt.show()
# 打印压缩率
non_zero_count_original = np.count_nonzero(signal)
print(non_zero_count_original)
non_zero_count_compressed = np.count_nonzero(compressed_signal)
print(non_zero_count_compressed)
compression_rate = 1 - non_zero_count_compressed / non_zero_count_original
print(f'Compression Rate: {compression_rate:.2%}')
# 假设我们要从压缩的信号中重构原始信号
# 在这个简单的例子中,重构只是一个未压缩步骤,因为我们没有实施变换
reconstructed_signal = compressed_signal # 实际应用可能需要复杂的重建过程
示意图
处理后,几乎没有变化。
输出结果
非常小的数据被“压缩”没了。原来有10个非零值,现在是9个。
相关博文
理解并实现OpenCV中的图像平滑技术
OpenCV中的边缘检测技术及实现
OpenCV识别人脸案例实战
入门OpenCV:图像阈值处理
我的图书
下面两本书欢迎大家参考学习。
OpenCV轻松入门
李立宗,OpenCV轻松入门,电子工业出版社,2023
本书基于面向 Python 的 OpenCV(OpenCV for Python),介绍了图像处理的方方面面。本书以 OpenCV 官方文档的知识脉络为主线,并对细节进行补充和说明。书中不仅介绍了 OpenCV 函数的使用方法,还介绍了函数实现的算法原理。
在介绍 OpenCV 函数的使用方法时,提供了大量的程序示例,并以循序渐进的方式展开。首先,直观地展示函数在易于观察的小数组上的使用方法、处理过程、运行结果,方便读者更深入地理解函数的原理、使用方法、运行机制、处理结果。在此基础上,进一步介绍如何更好地使用函数处理图像。在介绍具体的算法原理时,本书尽量使用通俗易懂的语言和贴近生活的实例来说明问题,避免使用过多复杂抽象的公式。
本书适合计算机视觉领域的初学者阅读,包括在校学生、教师、专业技术人员、图像处理爱好者。
本书第1版出版后,深受广大读者朋友的喜爱,被很多高校选为教材,目前已经累计重印9次。为了更好地方便大家学习,对本书进行了修订。
计算机视觉40例
李立宗,计算机视觉40例,电子工业出版社,2022
近年来,我深耕计算机视觉领域的课程研发工作,在该领域尤其是OpenCV-Python方面积累了一点儿经验。因此,我经常会收到该领域相关知识点的咨询,内容涵盖图像处理的基础知识、OpenCV工具的使用、深度学习的具体应用等多个方面。为了更好地把所积累的知识以图文的形式分享给大家,我将该领域内的知识点进行了系统的整理,编写了本书。希望本书的内容能够对大家在计算机视觉方向的学习有所帮助。
本书以OpenCV-Python(the Python API for OpenCV)为工具,以案例为载体,系统介绍了计算机视觉从入门到深度学习的相关知识点。
本书从计算机视觉基础、经典案例、机器学习、深度学习、人脸识别应用等五个方面对计算机视觉的相关知识点做了全面、系统、深入的介绍。书中共介绍了40余个经典的计算机视觉案例,其中既有字符识别、信息加密、指纹识别、车牌识别、次品检测等计算机视觉的经典案例,也包含图像分类、目标检测、语义分割、实例分割、风格迁移、姿势识别等基于深度学习的计算机视觉案例,还包括表情识别、驾驶员疲劳监测、易容术、识别年龄和性别等针对人脸的应用案例。
在介绍具体的算法原理时,本书尽量使用通俗易懂的语言和贴近生活的示例来说明问题,避免使用复杂抽象的公式来介绍。
本书适合计算机视觉领域的初学者阅读,适于在校学生、教师、专业技术人员、图像处理爱好者使用。