数字图像学笔记 —— 18. 图像抖动算法

这篇具有很好参考价值的文章主要介绍了数字图像学笔记 —— 18. 图像抖动算法。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

为什么需要图像抖动

在数字图像中,为了表示数字图像的细节,像素的颜色深度信息最少也是8位,即 0 − 256 0 - 256 0256. 但是在实际中,我们有很多显示设备的颜色深度信息仅有4位,甚至1位,即黑白。这样当我们试图在这样的设备上显示一副有深度信息的图像时,如果不做特殊的处理,就会遇到很大的麻烦。

所以,图像抖动算法(Image Dithering)最早是在数字图像处理中为了解决颜色深度受限制的问题而提出的。当图像的颜色深度较低,即每个像素可以表示的颜色数量有限时,图像的颜色表现力会受到限制,这可能会导致严重的颜色带状现象(banding)和颜色失真。

图像抖动算法的核心思想是通过在图像中引入一些噪声,将颜色误差以某种方式分散到附近的像素,使得在视觉上能够模拟出更多的颜色。这种技术尤其在早期的计算机图形显示系统中被广泛使用,因为这些系统的颜色深度通常非常有限。例如,在黑白打印机或只有黑白显示能力的设备中,通过抖动算法可以产生不同灰度级别的效果。

图像抖动算法实现的基本思路

图像抖动算法的基本思路是在减少颜色深度或者灰度等级时,尽可能地保留原始图像的视觉信息。这通常涉及到一种称为"误差扩散"的方法,该方法将每个像素值从其原始值量化到最近的可用颜色或灰度等级,并将造成的误差分散到周围的像素。

以下是图像抖动算法的基本步骤:

  • 选择一个图像和一个颜色或灰度级别的集合:这个集合可能只有两个颜色(如黑白),也可能有多个颜色。

  • 遍历图像的每个像素:对于图像中的每个像素,算法都会尝试找到最接近该像素颜色的颜色,然后将该像素颜色设置为该颜色。这个步骤通常称为"量化"。

  • 计算误差:量化步骤会导致一些颜色信息的丢失。这种丢失的颜色信息被称为"误差",可以通过将原始像素颜色和量化后的像素颜色相减来计算。

  • 扩散误差:接下来,算法将这个误差分散到相邻的像素。这个步骤的目的是尽可能地减少量化步骤对图像视觉质量的影响。误差可以按照多种方式分散,具体取决于使用的抖动算法。

重复以上步骤:算法将重复以上步骤,直到遍历了图像中的所有像素。

通过这种方式,抖动算法能够在颜色或灰度级别受限的情况下,模拟出更多的颜色或灰度等级,从而提高图像的视觉质量。

数字图像学笔记 —— 18. 图像抖动算法

比方说,上图所示的Firefox标识,最左侧的是具有8位深度信息的灰度图,但是中间和右侧的都是只有1位深度信息的黑白图。从视觉看似乎很相似,甚至细节上没有太多缺失。但是如果放大后看,就是下面这个效果了。

数字图像学笔记 —— 18. 图像抖动算法

常见图像抖动算法实现

图像抖动的实现算法有很多,但是在这里我只实现了其中两种,现在就具体说明。

Floyd-Steinberg 抖动算法

Floyd-Steinberg 抖动算法将误差分散到当前像素的右边和下面的像素。具体的误差扩散模式如下:

 X   7/16
3/16 5/16 1/16

在这个模式中,X 表示当前像素,数字表示误差扩散的比例。例如,当前像素的右边像素将接收 7/16 的误差,下面一行的左边、中间和右边的像素分别接收 3/16、5/16 和 1/16 的误差。

Atkinson 抖动算法

Atkinson 抖动算法将误差分散到当前像素的右边和下面的像素,但它的误差扩散模式与 Floyd-Steinberg 不同:

 X  1/8 1/8
1/8 1/8
    1/8

在这个模式中,误差被均匀地分散到六个像素,每个像素接收 1/8 的误差。文章来源地址https://www.toymoban.com/news/detail-473025.html

算法实现

import cv2
import numpy as np


#################### Floyd-Steinberg Dithering ####################

def floyd_steinberg_dithering_kernel(image):
    for y in range(image.shape[0] - 1):
        for x in range(1, image.shape[1] - 1):
            old_pixel = image[y, x]
            new_pixel = np.round(old_pixel / 255) * 255
            image[y, x] = new_pixel
            error = old_pixel - new_pixel
            image[y, x + 1] += error * 7 / 16
            image[y + 1, x - 1] += error * 3 / 16
            image[y + 1, x] += error * 5 / 16
            image[y + 1, x + 1] += error * 1 / 16
    return image


def floyd_steinberg_dithering():
    # Load an RGB image
    image = cv2.imread("Data/test.png")

    # Convert the image to grayscale
    gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

    # Apply Floyd-Steinberg dithering
    dithered_image = floyd_steinberg_dithering_kernel(np.copy(gray_image))

    # Display the original grayscale image and the dithered image
    cv2.imshow("Original", gray_image)
    cv2.imshow("FS Dithered", dithered_image)
    cv2.waitKey(0)
    cv2.destroyAllWindows()


#################### Atkinson Dithering ####################


def atkinson_dithering_kernel(image):
    error = np.zeros_like(image, dtype=np.float32)
    for y in range(image.shape[0] - 2):
        for x in range(image.shape[1] - 2):
            old_pixel = image[y, x] + error[y, x]
            new_pixel = np.round(old_pixel / 255) * 255
            image[y, x] = new_pixel
            diff = old_pixel - new_pixel
            error[y, x + 1] += diff * 1 / 8
            error[y, x + 2] += diff * 1 / 8
            error[y + 1, x - 1] += diff * 1 / 8
            error[y + 1, x] += diff * 1 / 8
            error[y + 1, x + 1] += diff * 1 / 8
            error[y + 2, x] += diff * 1 / 8
    return image


def atkinson_dithering():
    # Load an RGB image
    image = cv2.imread("Data/test.png")

    # Convert the image to grayscale
    gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

    # Apply Atkinson dithering
    dithered_image = atkinson_dithering_kernel(np.copy(gray_image.astype(np.float32)))

    # Display the original grayscale image and the dithered image
    cv2.imshow("Original", gray_image)
    cv2.imshow("A Dithered", dithered_image.astype(np.uint8))
    cv2.waitKey(0)
    cv2.destroyAllWindows()


def main():
    # Load an RGB image
    image = cv2.imread("Data/test.png")

    # Convert the image to grayscale
    gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

    # Apply Floyd-Steinberg dithering
    fs_dithered_image = floyd_steinberg_dithering_kernel(np.copy(gray_image))

    # Apply Atkinson dithering
    atk_dithered_image = atkinson_dithering_kernel(np.copy(gray_image.astype(np.float32)))

    # Display the original grayscale image and the dithered image
    cv2.imshow("Original", gray_image)
    cv2.imshow("FS Dithered", fs_dithered_image)
    cv2.imshow("ATK Dithered", atk_dithered_image)
    cv2.waitKey(0)
    cv2.destroyAllWindows()


if __name__ == "__main__":
    # floyd_steinberg_dithering()
    # atkinson_dithering()
    main()

到了这里,关于数字图像学笔记 —— 18. 图像抖动算法的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 什么是数字化?企业为什么要数字化转型?

    什么是数字化?企业为什么要数字化转型? 深度长文,4000+字,融合了很多 国内外专业期刊观点 ,一文讲清到底什么是企业数字化转型?心急的小伙伴可以先看目录: 关于定义—— 到底什么是“数字化转型” ? 关于价值—— 数字化转型对企业到底有多重要 ? 关于框架—

    2023年04月23日
    浏览(64)
  • 建筑行业为什么要数字化转型?

    建筑行业为什么要数字化转型? 建筑行业作为国民经济的重要支柱产业之一,其 生产过程繁琐、复杂,且产业链条长,涉及众多领域 。 然而,目前传统的建筑模式已经无法适应行业的发展需求, 建筑行业的数字化转型已经成为必然趋势 。 数字化转型是指 企业或组织通过

    2023年04月21日
    浏览(43)
  • 为什么数字化时代需要 BizDevOps?

    随着云原生、元宇宙、Web3等技术拉开序幕,智能制造、智慧城市、精准医疗等应用场景徐徐展开,继人类工业文明之后,下一个大变局的奇点临近。 毫无疑问,以数字技术应用为主线的数字化转型是此次人类文明变革的核心动力。在这一变革过程中,技术与业务的关系正发

    2024年02月11日
    浏览(55)
  • 为什么数字化转型,必须是“一把手”工程?

    随着数字技术的不断发展,数字化转型已成为各行各业中不可或缺的一部分。企业需要利用数字技术来提高效率、降低成本、增强竞争力。然而,数字化转型并不是一项简单的任务,它需要领导层的积极参与和全力支持,因此“一把手”工程成为了数字化转型的必要条件。

    2023年04月08日
    浏览(41)
  • 为什么计算机对浮点型数字计算存在误差

    我们输入的十进制小数在计算机中都是以二进制进行存储。比如: 由此可见0.3在计算机中存储的值永远小于0.3,所以当使用0.3计算时,就会产生误差。 在计算机中浮点型不能直接使用等号比较也是同一个道理。举个李子: 执行结果: 可以看出当涉及到0.3的运算超出一定的精

    2023年04月11日
    浏览(47)
  • 如何对宏进行数字签名,为什么它很重要

    宏是现代计算机用户可用的最强大的工具之一,但它们也带有独特的风险。了解如何以数字方式对宏进行签名,对于确保可以安全可靠地使用宏非常重要。数字签名可确保宏代码来自可信来源,并且自创建以来未被修改过。 在本指南中,我们将解释如何对宏进行数字签名,以

    2024年02月07日
    浏览(74)
  • stable diffusion为什么能用于文本到图像的生成

      推荐基于稳定扩散(stable diffusion) AI 模型开发的自动纹理工具: DreamTexture.js自动纹理化开发包 - NSDT 如果你还没有看过它:稳定扩散是一个文本到图像的生成模型,你可以输入一个文本提示,比如“一个人一半尤达一半甘道夫”,然后接收一个图像(512x512像素)作为输出,

    2024年02月03日
    浏览(42)
  • 企业数字化转型:为什么需要做 ModelOps 模型全生命周期管理

    现如今,以大数据、云计算、人工智能、工业互联网为代表的数字科技正飞速发展,带领技术与产业向数字化、智能化的方向展开变革——数字科技正逐渐成为推动世界经济高质量发展的核心驱动力,数字经济应运而生。而对于企业来说, 数字化转型则是发展数字经济的必由

    2024年02月04日
    浏览(64)
  • “3%”与“低个位数”,暴雪为什么要跟网易玩数字游戏?

    北京时间11月17日上午,暴雪娱乐发布声明称,由于同网易的现有授权协议将在2023年1月23日到期,将暂停在中国大陆的大部分暴雪游戏服务,包括《魔兽世界》《炉石传说》《守望先锋》《星际争霸》《魔兽争霸Ⅲ:重置版》《暗黑破坏神Ⅲ》和《风暴英雄》。《暗黑破坏神

    2024年02月07日
    浏览(42)
  • 数字电源为什么一般用DSP控制,而不能用普通的单片机?

    首先你要清楚,数字电源需要一个芯片具备什么功能? 1 能发PWM波 ,并且具备保护关断功能; 电源对PWM发波 要求很高,精度要ns级甚至ps级的;同时要有关断功能,比如过流或者过压直接关死,最近很多小伙伴找我,说想要一些单片机的资料,然后我根据自己从业十年经验,

    2024年02月22日
    浏览(49)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包