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

文章目录

  • 为什么需要图像抖动
  • 图像抖动算法实现的基本思路
  • 常见图像抖动算法实现
    • Floyd-Steinberg 抖动算法
    • Atkinson 抖动算法
    • 算法实现

为什么需要图像抖动

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

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

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

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

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

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

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

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

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

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

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

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

在这里插入图片描述

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

在这里插入图片描述

常见图像抖动算法实现

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

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/81/8

在这个模式中,误差被均匀地分散到六个像素,每个像素接收 1/8 的误差。

算法实现

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) * 255image[y, x] = new_pixelerror = old_pixel - new_pixelimage[y, x + 1] += error * 7 / 16image[y + 1, x - 1] += error * 3 / 16image[y + 1, x] += error * 5 / 16image[y + 1, x + 1] += error * 1 / 16return imagedef floyd_steinberg_dithering():# Load an RGB imageimage = cv2.imread("Data/test.png")# Convert the image to grayscalegray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)# Apply Floyd-Steinberg ditheringdithered_image = floyd_steinberg_dithering_kernel(np.copy(gray_image))# Display the original grayscale image and the dithered imagecv2.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) * 255image[y, x] = new_pixeldiff = old_pixel - new_pixelerror[y, x + 1] += diff * 1 / 8error[y, x + 2] += diff * 1 / 8error[y + 1, x - 1] += diff * 1 / 8error[y + 1, x] += diff * 1 / 8error[y + 1, x + 1] += diff * 1 / 8error[y + 2, x] += diff * 1 / 8return imagedef atkinson_dithering():# Load an RGB imageimage = cv2.imread("Data/test.png")# Convert the image to grayscalegray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)# Apply Atkinson ditheringdithered_image = atkinson_dithering_kernel(np.copy(gray_image.astype(np.float32)))# Display the original grayscale image and the dithered imagecv2.imshow("Original", gray_image)cv2.imshow("A Dithered", dithered_image.astype(np.uint8))cv2.waitKey(0)cv2.destroyAllWindows()def main():# Load an RGB imageimage = cv2.imread("Data/test.png")# Convert the image to grayscalegray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)# Apply Floyd-Steinberg ditheringfs_dithered_image = floyd_steinberg_dithering_kernel(np.copy(gray_image))# Apply Atkinson ditheringatk_dithered_image = atkinson_dithering_kernel(np.copy(gray_image.astype(np.float32)))# Display the original grayscale image and the dithered imagecv2.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()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/253579.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

vulhub-Jarbas(易)

打靶练习Jarbas 0x00 部署0x01 信息收集:端口扫描、服务发现0x02 路径爬取0x03 反弹shell0x04 内网信息收集0x05 crontab定时任务提权0x06 总结 0x00 部署 靶机:下载地址 宿主机:kali2021版本 0x01 信息收集:端口扫描、服务发现…

什么是先进存力?曙光存储:内铸数字底座,外成实践底气

5月26日,由DOIT联合中国电子学会共同举办的2023数据基础设施技术峰会在苏州举办。中科曙光存储产品事业部副总经理张新凤受邀参会,并在主论坛发表主题演讲,与数百位业内专业嘉宾伙伴共探存力发展未来。 什么样的存力能打造数字经济底座&#…

尚硅谷在线教育视频点播

文章目录 1. 开通阿里云视频点播服务2.阿里云点播SDK实现2.1上传视频到阿里云视频点播服务2.2整合阿里云上传视频的接口 3. 课程信息的完善(为每个课程的小节添加视频)3.1 添加上传视频3.2删除视频信息3.2.1后台3.2.2前端 1. 开通阿里云视频点播服务 选…

阿里云视频点播的使用

1.简介:视频点播(ApsaraVideo for VoD)是集音视频采集、编辑、上传、自动化转码处理、媒体资源管理、分发加速于一体的一站式音视频点播解决方案。 2.视频点播的使用: 2.1引入相关依赖:阿里云上有也可以进行直接使用 …

java red5 点播_树莓派实用RED5搭建流媒体服务器实现点播功能

1,搭建流媒体服务器一直是自己想玩的一个东西,在高中玩workerman框架时有人就做过nginx通过rtmp模块搭建流媒体服务器,nginx的特性就是高并发,轻量级,一般大型企业都会采用这个服务器,但是由于,…

Nginx 搭建RTMP视频点播 直播 HLS服务器

安装Nginx --下载nginx-rtmp-module模块 git clone https://github.com/arut/nginx-rtmp-module.git--安装依赖 yum install -y wget gcc gcc-c make pcre pcre-deve zilib zlib-devel openssl-devel--下载Nginx源码包并解压 wget http://nginx.org/download/nginx-1.18.0.tar…

阿里云视频点播

目录 1.控制台介绍 2.环境准备 3.视频上传 4.视频删除 5.获取播放地址 6.获取播放凭证 1.控制台介绍 存储小于50G免费的,转码、流量都是需要付费的 视频存储 需要配置域名 2.环境准备 需要拿到这个key和secret,配置在项目中 3.视频上传 /*** 上传…

陕西发布!陕西省重点实验室申报条件类别、认定程序要求

本文整理了陕西省重点实验室申报条件,认定材料等相关内容,感兴趣的朋友快跟小编一起来看看吧! 一、总体思路 本次省重点实验室布局建设工作以填补我省优势学科领域下无省级及以上科学与工程研究类科技创新基地的空白为主,同时兼顾前沿、新兴、…

腾讯云点播视频播放器使用步骤 uniapp

微信开发后台 首先需要微信小程序的账号,各种认证,信息填写完整, 然后–>设置–>第三方设置–>插件管理–>添加插件–>搜索云点播短视频播放器–>添加插件 项目开发 在page.json文件中的globalStyle下面加入 "usin…

用Python实现腾讯云点播VOD

腾讯云点播VOD主要用于视频资源的上传和在线播放,腾讯云官方文档也有许多相关操作的介绍,但是关于Python的文档相对较少,这里我想分享一下在Python方面自己对腾讯云VOD的研究(记得看注释)。 必备知识基础:…

阿里云视频点播-记录

1.开通视频点播 开通服务 点击立即开通 找到存储管理 启用存储地址 视频加密要设置转码并将其设置为默认 修改模板-点击编辑 上传视频测试 此时已经有了默认存储地址和默认转码配置域名加速【域名已备案】 输入域名点击提交即可配置DNS 点击眼睛并复制CNAME,前…

使用阿里云视频点播上传视频

目录 前言一、目的二、实现步骤1.准备操作2.主要使用模块2.1. 上传音频2.2. 添加转码设置 3.搭建视频点播环境3.1.配置Maven仓库3.2.添加jar依赖3.3.上传视频3.4.初始化点播服务3.5.根据视频ID获取视频地址3.6.根据视频ID删除阿里云中视频3.7.根据视频ID集合删除 三、问题1.阿里…

什么是视频点播(VOD)?

点击上方“LiveVideoStack”关注我们 翻译 | Alex 技术审校 | 赵军 本文来自OTTVerse,作者为Krishna Rao Vijayanagar。 点播 Easy Tech #012# VOD代表Video on Demand(视频点播),这种视频流化和交付技术使人们可以随时随地在任何…

php视频点播系统,PHPvod 视频点播系统 v3.1 for php5.4.x

PHPvod是一款免费开源,基于PHPMysql开发的视频点播系统,系统拥有众多的优秀功能和特性,在社区成员的积极参与下,在易用性、扩展性和性能方面不断优化和改进,使得PHPvod可以在极为繁忙的服务器环境下快速稳定运行&#…

开源的在线视频点播系统,值得分享!

平时做一些商业的项目。大家都知道,github是程序员的天堂,大家要好好利用。 今天给大家推荐的这个开源项目来自于读者的投稿,我感觉非常不错,就在这里推荐给大家,如果你也有好的开源项目,我也可以帮你推荐…

uniapp - 腾讯云点播小程序插件

欢迎关注微信公众号:FSA全栈行动 👋 一、简介 微信小程序播放教育类视频要求具备有相关资质,但这些资质一般公司很难短时间申请下来(甚至有的公司压根就申请不了),而【短视频播放器小程序插件】含有《信息…

免费视频直播、点播H5播放器SkeyeWebPlayer适配移动端

免费视频直播、点播H5播放器SkeyeWebPlayer适配排除,移动端,常见移动端Web页面问题及解决方案 SkeyeVSS其独创的ws-rtsp流媒体直播技术,兼容传统安防流媒体的同时,不需要安装浏览器插件,解决互联网接入安防监控延迟高…

JAVA在线教育视频点播学习系统毕业设计 开题报告

本文给出的java毕业设计开题报告,仅供参考!(具体模板和要求按照自己学校给的要求修改) 选题目的和意义 目的:本课题主要目标是设计并能够实现一个基于java的视频点播系统,系统整体使用了基于浏览的javaMy…

如何搭建视频点播服务

要搭建一套高效、稳定、可靠的视频点播服务,通常考虑视频资源的数量、视频资源的格式、用户量和并发量等方面因素,具体包括: 1)视频资源的数量和格式,以及增量情况; 2)播放终端的适配; 3)播放并发量、访问鉴…

直播和点播的区别

先总述直播和点播的不同点: 一、时效性要求不同 二、内容存在形式不同 三、运作流程不同 四、常见场景 五、技术架构 很多时候,大家对直播和点播的区别还是很模糊,仅仅停留在一种感觉上,如果视频画面是实时的就是直播&#…