• 图像随机抖动算法


    本文参考知乎博客:图像处理之 Dithering(https://zhuanlan.zhihu.com/p/110104674)

    图像抖动(dithering)常用于颜色量化(color quantization)的后处理,即去除颜色量化产生的一些视觉上不合理的“色带”。如下所示:左侧是原图,右侧是颜色量化的结果,可以看到猫的脖子以及头部有很多不合理的色带,颜色抖动的目标就是去除这些色带,使之更加平滑。
    在这里插入图片描述
    图像抖动最经典的技术为误差扩散方法,可以参考博客:Floyd-Steinberg扩散抖动算法
    这里介绍另一种简单且好玩的抖动算法,随机抖动。
    请添加图片描述

    假设现在给定如上所示的图像,不失一般性,将颜色归一化到[0,1]范围,我们给定8种颜色的调色板正好对应RGB cube的8个顶点),分别为: ( 0 , 0 , 0 ) , ( 1 , 0 , 0 ) , ( 0 , 1 , 0 ) , ( 0 , 0 , 1 ) , ( 0 , 1 , 1 ) , ( 1 , 1 , 0 ) , ( 1 , 0 , 1 ) , ( 1 , 1 , 1 ) (0,0,0),(1,0,0),(0,1,0),(0,0,1),(0,1,1),(1,1,0),(1,0,1),(1,1,1) (0,0,0),(1,0,0),(0,1,0),(0,0,1),(0,1,1),(1,1,0),(1,0,1),(1,1,1), 也就是说8个颜色,每种颜色的三通道取值要么是0,要么是1。

    1. 固定阈值抖动

    给定固定值 x = 0.5 x = 0.5 x=0.5, 对于每个像素点 I p I_p Ip, 分别检查它的三个通道,并重新赋值:
    I p ( r / g / b ) = { 0      I p ( r / g / b ) < x 1      I p ( r / g / b ) ≥ x I_p(r/g/b)=\left\{

    0    Ip(r/g/b)<x1    Ip(r/g/b)x" role="presentation">0    Ip(r/g/b)<x1    Ip(r/g/b)x
    \right. Ip(r/g/b)={0    Ip(r/g/b)<x1    Ip(r/g/b)x

    固定阈值抖动代码:

    def dithering_v1(input_img, save_path):
    	quant_img = input_img.copy()
    	quant_img[input_img > 0.5] = 1
    	quant_img[input_img < 0.5] = 0
    	cv2.imwrite(save_path, quant_img*255)
    
    • 1
    • 2
    • 3
    • 4
    • 5

    抖动效果如下所示,可以看到,这里原始细节信息损失很严重。
    请添加图片描述

    2. 独立随机抖动

    对于每个像素点 I p I_p Ip, 生成对应的随机数值 x = r a n d ( ) x = rand() x=rand(), 注意这里每个像素生成一个独立的随机 x x x. 分别检查它的三个通道,并重新赋值:
    I p ( r / g / b ) = { 0      I p ( r / g / b ) < x 1      I p ( r / g / b ) ≥ x I_p(r/g/b)=\left\{

    0    Ip(r/g/b)<x1    Ip(r/g/b)x" role="presentation">0    Ip(r/g/b)<x1    Ip(r/g/b)x
    \right. Ip(r/g/b)={0    Ip(r/g/b)<x1    Ip(r/g/b)x

    随机抖动代码1:

    def dithering_v2(input_img, save_path):
    	shape = input_img.shape
    	input_img = input_img.flatten()
    	quant_img = input_img.copy()
    
    	for i in range(input_img.shape[0]):
    		x = np.random.rand()
    		if quant_img[i] > x: quant_img[i] = 1
    		else: quant_img[i] = 0
    
    	cv2.imwrite(save_path,quant_img.reshape(shape)*255)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    抖动效果如下所示,可以看到,效果比固定阈值抖动好很多,但有很多噪点。
    请添加图片描述

    3. 多次独立随机抖动

    直接上代码,这里对每个像素生成20个随即数 x x x,生成20个颜色值并求平均。

    def dithering_v3(input_img, save_path):
    	shape = input_img.shape
    	input_img = input_img.flatten()
    	quant_img = input_img.copy()
    
    	for i in range(input_img.shape[0]):
    		color = 0
    		n = 20
    		for k in range(n):
    			if quant_img[i] > np.random.rand(): color += 1
    		quant_img[i] = color / n
    
    	cv2.imwrite(save_path, quant_img.reshape(shape)*255)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    结果如下所示,看起来非常接近原始图像,这是为什么呢?
    请添加图片描述

    注意到这里每个像素点 I p I_p Ip 的颜色是这样计算的:
    令: c = 0 c = 0 c=0
    第1次: x 1 = r a n d ( ) , c + = I p > x 1 x1 = rand(), c += I_p > x1 x1=rand(),c+=Ip>x1
    第2次: x 2 = r a n d ( ) , c + = I p > x 2 x2 = rand(), c += I_p > x2 x2=rand(),c+=Ip>x2
    第3次: x 3 = r a n d ( ) , c + = I p > x 3 x3 = rand(), c += I_p > x3 x3=rand(),c+=Ip>x3

    第n次: x n = r a n d ( ) , c + = I p > x n xn = rand(), c += I_p > xn xn=rand(),c+=Ip>xn
    最终, I p = c / n I_p = c / n Ip=c/n

    任意一次, I p > x i , x i = r a n d ( ) I_p > xi, xi = rand() Ip>xi,xi=rand(), 可以发现 x i = r a n d ( ) < I p xi = rand() < I_p xi=rand()<Ip 的概率就是 I p I_p Ip, 比如 I p = 0.8 I_p = 0.8 Ip=0.8, 那么在[0,1]范围生成随即数 x < 0.8 x < 0.8 x<0.8的概率就是0.8,为此, I p = 1 I_p = 1 Ip=1的概率就是 0.8. 通过多次随机采样,最终的期望值就等于 I p I_p Ip本身的像素值。

    因此,这个算法其实并不实用,因为颜色值已经不再是调色板中的颜色值,而是接近像素值本身。。。

  • 相关阅读:
    flinksql读写redis
    Kyligence 入选 Gartner 指标中台创新洞察报告
    使用Eclipse搭建SpringBoot项目
    如何使用adb command来设置cpu频率和核数
    专业韩语论文翻译,论文中译韩哪里比较专业?
    煤炭无人值守称重系统的管理功能有哪些?
    我用Python做了一个超级简单上手的中考成绩网页
    10快速入门Query函数使用的Pandas的查询示例
    Gradle系列——Gradle文件操作,Gradle依赖(基于Gradle文档7.5)day3-1
    基于JavaSwing开发通讯录管理系统+开题报告+论文 毕业设计 课程设计 大作业
  • 原文地址:https://blog.csdn.net/u011426016/article/details/127281673