误差扩散、Floyd-Steinberg 抖动、有序抖动、Riemersma 抖动算法
1.误差扩散算法详解
误差扩散算法(Error Diffusion Algorithm)是一种用于图像抖动(Dithering)和半色调(Halftoning)的技术。它通过将像素的量化误差扩散到邻近像素,从而在整体上保持图像的灰度特性。这种方法通常用于图像打印和显示,特别是将灰度图像转换为二值图像时。
算法步骤
- 遍历图像:逐像素处理图像,从左到右,从上到下。
- 量化像素:将当前像素的灰度值量化为目标值(通常是0或255)。
- 计算误差:计算当前像素的量化误差。
- 扩散误差:将误差分配给邻近像素。
常见的误差扩散算法有:
- Floyd-Steinberg算法
- Jarvis, Judice, and Ninke算法
- Stucki算法
Floyd-Steinberg 算法
Floyd-Steinberg 算法是最常用的误差扩散算法之一。其扩散矩阵如下:
这里,* 表示当前处理的像素,其他值表示扩散给邻近像素的误差比例。
公式
Python 实现
以下是Floyd-Steinberg误差扩散算法的Python实现代码:
import numpy as np
from PIL import Image
import matplotlib.pyplot as plt
def floyd_steinberg_dithering(image):
"""
Floyd-Steinberg 误差扩散算法实现
参数:
image (PIL.Image): 灰度图像
返回:
PIL.Image: 二值化后的图像
"""
# 将图像转换为灰度图像
grayscale_image = image.convert("L")
image_array = np.array(grayscale_image, dtype=float)
# 获取图像的行和列
rows, cols = image_array.shape
# 遍历图像
for y in range(rows):
for x in range(cols):
old_pixel = image_array[y, x]
new_pixel = 0 if old_pixel < 128 else 255
image_array[y, x] = new_pixel
quant_error = old_pixel - new_pixel
if x + 1 < cols:
image_array[y, x + 1] += quant_error * 7 / 16
if x - 1 >= 0 and y + 1 < rows:
image_array[y + 1, x - 1] += quant_error * 3 / 16
if y + 1 < rows:
image_array[y + 1, x] += quant_error * 5 / 16
if x + 1 < cols and y + 1 < rows:
image_array[y + 1, x + 1] += quant_error * 1 / 16
# 将处理后的数组转换为图像
dithered_image = Image.fromarray(np.clip(image_array, 0, 255).astype(np.uint8))
return dithered_image
# 示例用法
if __name__ == "__main__":
image = Image.open('example.jpg') # 打开原始图像
dithered_image = floyd_steinberg_dithering(image) # 调用Floyd-Steinberg误差扩散算法
dithered_image.show() # 显示二值化后的图像
dithered_image.save('dithered_example.jpg') # 保存二值化后的图像
# 显示原始图像和二值化后的图像
plt.figure(figsize=(12, 6))
plt.subplot(1, 2, 1)
plt.title('Original Image')
plt.imshow(image.convert("L"), cmap='gray')
plt.axis('off')
plt.subplot(1, 2, 2)
plt.title('Dithered Image')
plt.imshow(dithered_image, cmap='gray')
plt.axis('off')
plt.show()
详细解释
-
读取图像和转换为灰度图像:
image = Image.open('example.jpg') grayscale_image = image.convert("L")
-
将灰度图像转换为NumPy数组:
image_array = np.array(grayscale_image, dtype=float)
-
遍历图像并进行量化和误差扩散:
for y in range(rows): for x in range(cols): old_pixel = image_array[y, x] new_pixel = 0 if old_pixel < 128 else 255 image_array[y, x] = new_pixel quant_error = old_pixel - new_pixel if x + 1 < cols: image_array[y, x + 1] += quant_error * 7 /