当前位置: 首页 > 编程日记 > 正文

新技能 Get,使用直方图处理进行颜色校正

0285f521392ecaee9f7b16c557c584fc.gif

作者 | 小白

来源 | 小白学视觉

96a81283f836050427468d1493b1d15d.png

在这篇文章中,我们将探讨如何使用直方图处理技术来校正图像中的颜色。

像往常一样,我们导入库,如numpy和matplotlib。此外,我们还从skimage 和scipy.stats库中导入特定函数。

import numpy as np
import matplotlib.pyplot as plt
from skimage.io import imread, imshow
from skimage import img_as_ubyte
from skimage.color import rgb2gray
from skimage.exposure import histogram, cumulative_distribution
from scipy.stats import cauchy, logistic

让我们使用马尼拉内穆罗斯马尼拉大教堂的夜间图像。

cathedral = imread('cathedral.jpg')
plt.imshow(cathedral)
plt.title('Manila Cathedral')

d2cc74f6bdbec9ff0cc15be10a038bae.png

首先,让我们将图像转换为灰度。

fig, ax = plt.subplots(1,2, figsize=(15,5))
cathedral_gray = rgb2gray(cathedral)
ax[0].imshow(cathedral_gray, cmap='gray')
ax[0].set_title('Grayscale Image')
ax1 = ax[1]
ax2 = ax1.twinx()
freq_h, bins_h = histogram(cathedral_gray)
freq_c, bins_c = cumulative_distribution(cathedral_gray)
ax1.step(bins_h, freq_h*1.0/freq_h.sum(), c='b', label='PDF')
ax2.step(bins_c, freq_c, c='r',  label='CDF')
ax1.set_ylabel('PDF', color='b')
ax2.set_ylabel('CDF', color='r')
ax[1].set_xlabel('Intensity value')
ax[1].set_title('Histogram of Pixel Intensity');

4a603f8163a5c7b0035fbcc7c6a99612.png

由于图像是在夜间拍摄的,因此图像的特征比较模糊,这也在像素强度值的直方图上观察到,其中 PDF 在较低的光谱上偏斜。

由于图像的强度值是倾斜的,因此可以应用直方图处理来重新分布图像的强度值。直方图处理的目的是将图像的实际 CDF 拉伸到新的目标 CDF 中。通过这样做,倾斜到较低光谱的强度值将转换为较高的强度值,从而使图像变亮。

让我们尝试在灰度图像上实现这一点,我们假设 PDF 是均匀分布,CDF 是线性分布。

image_intensity = img_as_ubyte(cathedral_gray)
freq, bins = cumulative_distribution(image_intensity)
target_bins = np.arange(255)
target_freq = np.linspace(0, 1, len(target_bins))
new_vals = np.interp(freq, target_freq, target_bins)
fig, ax = plt.subplots(1,2, figsize=(15,5))
ax[0].step(bins, freq, c='b', label='Actual CDF')
ax[0].plot(target_bins, target_freq, c='r', label='Target CDF')
ax[0].legend()
ax[0].set_title('Grayscale: Actual vs. ''Target Cumulative Distribution')
ax[1].imshow(new_vals[image_intensity].astype(np.uint8), cmap='gray')
ax[1].set_title('Corrected Image in Grayscale');

22d68c7f63dcf458eceed7ffdd0fd51d.png

通过将实际 CDF 转换为目标 CDF,我们可以在保持图像关键特征的同时使图像变亮。请注意,这与仅应用亮度过滤器完全不同,因为亮度过滤器只是将图像中所有像素的强度值增加相等的量。在直方图处理中,像素强度值可以根据目标 CDF 增加或减少。

现在,让我们尝试在彩色图像中实现直方图处理。这些过程可以从灰度图像中复制——然而,不同之处在于我们需要对图像的每个通道应用直方图处理。为了简化实现,我们创建一个函数来对图像执行此过程。

def show_linear_cdf(image, channel, name, ax):image_intensity = img_as_ubyte(image[:,:,channel])freq, bins = cumulative_distribution(image_intensity)target_bins = np.arange(255)target_freq = np.linspace(0, 1, len(target_bins))ax.step(bins, freq, c='b', label='Actual CDF')ax.plot(target_bins, target_freq, c='r', label='Target CDF')ax.legend()ax.set_title('{} Channel: Actual vs. ''Target Cumulative Distribution'.format(name))
def linear_distribution(image, channel):image_intensity = img_as_ubyte(image[:,:,channel])freq, bins = cumulative_distribution(image_intensity)target_bins = np.arange(255)target_freq = np.linspace(0, 1, len(target_bins))new_vals = np.interp(freq, target_freq, target_bins)return new_vals[image_intensity].astype(np.uint8)

现在,我们将这些函数应用于原始图像的每个通道。

fig, ax = plt.subplots(3,2, figsize=(12,14))
red_channel = linear_distribution(cathedral, 0)
green_channel = linear_distribution(cathedral, 1)
blue_channel = linear_distribution(cathedral, 2)
show_linear_cdf(cathedral, 0, ‘Red’, ax[0,0])
ax[0,1].imshow(red_channel, cmap=’Reds’)
ax[0,1].set_title(‘Corrected Image in Red Channel’)
show_linear_cdf(cathedral, 1, ‘Green’, ax[1,0])
ax[1,1].imshow(green_channel, cmap=’Greens’)
ax[1,1].set_title(‘Corrected Image in Green Channel’)
show_linear_cdf(cathedral, 2, ‘Blue’, ax[2,0])
ax[2,1].imshow(blue_channel, cmap=’Blues’)
ax[2,1].set_title(‘Corrected Image in Blue Channel’)

b6f9dafc442ebd2d0a21bcac59c9c3a2.png

请注意,所有通道几乎都具有相同的 CDF,这显示了图像中颜色的良好分布——只是颜色集中在较低的强度值光谱上。就像我们在灰度图像中所做的一样,我们还将每个通道的实际 CDF 转换为目标 CDF。

校正每个通道的直方图后,我们需要使用 numpy stack函数将这些通道堆叠在一起。请注意,RGB 通道在堆叠时需要按顺序排列。

fig, ax = plt.subplots(1,2, figsize=(15,5))
ax[0].imshow(cathedral);
ax[0].set_title('Original Image')
ax[1].imshow(np.dstack([red_channel, green_channel, blue_channel]));
ax[1].set_title('Transformed Image');

85bf2c8fe64892e9aa8ee8736614b874.png

堆叠所有通道后,我们可以看到转换后的图像颜色与原始图像的显着差异。直方图处理最有趣的地方在于,图像的不同部分会有不同程度的像素强度转换。请注意,马尼拉大教堂墙壁的像素强度发生了巨大变化,而马尼拉大教堂钟楼的像素强度却保持相对不变。

现在,让我们尝试使用其他函数作为目标 CDF 来改进这一点。为此,我们将使用该scipy.stats库导入各种分布,还创建了一个函数来简化我们的分析。

def individual_channel(image, dist, channel):im_channel = img_as_ubyte(image[:,:,channel])freq, bins = cumulative_distribution(im_channel)new_vals = np.interp(freq, dist.cdf(np.arange(0,256)), np.arange(0,256))return new_vals[im_channel].astype(np.uint8)
def distribution(image, function, mean, std):dist = function(mean, std)fig, ax = plt.subplots(1,2, figsize=(15,5))image_intensity = img_as_ubyte(rgb2gray(image))freq, bins = cumulative_distribution(image_intensity)ax[0].step(bins, freq, c='b', label='Actual CDF')ax[0].plot(dist.cdf(np.arange(0,256)), c='r', label='Target CDF')ax[0].legend()ax[0].set_title('Actual vs. Target Cumulative Distribution')red = individual_channel(image, dist, 0)green = individual_channel(image, dist, 1)blue = individual_channel(image, dist, 2)ax[1].imshow(np.dstack((red, green, blue)))ax[1].set_title('Transformed Image')return ax

让我们使用 Cauchy 函数来试试这个。

distribution(cathedral, cauchy, 90, 30);

c81429199cc20536552721d7423f8d3e.png

使用不同的分布似乎会产生更令人愉悦的配色方案。事实上,大教堂正门的弧线在逻辑分布中比线性分布更好,这是因为在逻辑分布中像素值强度的平移比线性分布要小,这可以从实际 CDF 线到目标 CDF 线的距离看出。

让我们看看我们是否可以使用逻辑分布进一步改进这一点。

distribution(cathedral, logistic, 90, 30);

9ecf60465cff595c931a4456dbe905ab.png

请注意,门中的灯光如何从线性和Cauchy分布改进为逻辑分布的。这是因为逻辑函数的上谱几乎与原始 CDF 一致。因此,图像中的所有暗物体(低像素强度值)都被平移,而灯光(高像素强度值)几乎保持不变。

结论

我们已经探索了如何使用直方图处理来校正图像中的颜色,实现了各种分布函数,以了解它如何影响结果图像中的颜色分布。

同样,我们可以得出结论,在固定图像的颜色强度方面没有“一体适用”的解决方案,数据科学家的主观决定是确定哪个是最适合他们的图像处理需求的解决方案。

Github代码连接:

https://github.com/jephraim-manansala/histogram-manipulation

7895a3d07011edda14612ccef52bf273.gif

5a8c07a80f9adae08c6dbb0475734bb9.png

技术

基于聚类的图像分割(Python)

资讯

人工智能监考VS传统方式监考

资讯

Meta研发触觉手套助力元宇宙

图像

深度学习视频理解之图像分类

e38fae161fec649dbad863daceb22dce.png

分享

5d0b930f0ff7ee9ad9fea9004e9b6d14.png

点收藏

64271d3633413ee2157646c844907151.png

点点赞

cbed9ed67aa32147807c999a46c91fb3.png

点在看

相关文章:

Oracle数据库 之 删除RMAN备份

#su – oracle 切换至存放备份的目录,删除不需要的备份文件。 $export ORACLE_SIDorcl $rman RMAN>connect target / RMAN>crosscheck backup; RMAN>delete expired backup; RMAN>exit 转载于:https://www.cnblogs.com/hdtiny/p/8420770.html

Linux环境编程--fflush(stdout)有什么作用

代码: printf("hello\n");//fflush(stdout);fork(); 输出: hello代码: printf("hello\n");fflush(stdout);fork(); 输出: hellohello说明:系统函数fork()创建新的进程。 printh后打印内容在缓冲区…

sysdba不能远程登录,我们该怎么做 (转载)

sysdba不能远程登录这个也是一个很常见的问题了。 碰到这样的问题我们该如何解决呢? 我们用sysdba登录的时候,用来管理我们的数据库实例,特别是有时候,服务器不再本台机器,这个就更是有必要了。 当我们用sqlplus &qu…

TeaTalk 线上直播倒计时 | 云数据库技术创新研究与实践

随着云计算的发展,数据库上云已经成为趋势,云数据库服务相对于传统数据库在架构、性能与安全等方面都存在着新的挑战。11月23日,移动云TeaTalk线上沙龙带着满满的干货来了!本次技术沙龙邀请了移动云创新中心的技术专家及华中科技大…

再测Golang的JSON库

2019独角兽企业重金招聘Python工程师标准>>> 写项目一直需要进行序列化,听到了,也看到了很多同学老师对各个golang的json库进行测评。那本人为什么还要继续进行这一次测评呢? 因为实践过的知识最有说服力,也是属于自己…

一、JAVA通过JDBC连接mysql数据库(连接)

JDBC ----JDBC(Java DataBase Connectivity)是Java与数据库的接口规范,JDBC定义了一个支持标准SQL功能的通用低层的应用程序编程接口(API),它由Java 语言编写的类和接口组成,旨在让各数据库开发商为Java程序员提供标准的数据库API。 JDBC API…

给你一个热爱阅读的机会,走到哪儿,看到哪儿的读书体验

整理 | 禾木木出品 | AI科技大本营(ID:rgznai100)不知道在自我介绍的时候是不是都有一个共同的爱好:阅读。但是喜欢阅读就代表会经常去图书馆或者是阅读室吗?不!这是一个肯定的答案。通常会因为太忙或是懒惰而选择放弃…

Linux环境编程--进程

查看正在运行的进程 #ps -ef #ps ax 可以看到状态查看nice值 #ps -l #ps -fsystem函数 传递命令,如同在shell中执行 char * p"ps ax"; system(p);或者 "ps ax &";//ps一启动shell就返回execl,execlp,execle函数 exec启动一个新程序&#xf…

芝麻HTTP:Scrapy-Splash的安装

2019独角兽企业重金招聘Python工程师标准>>> Scrapy-Splash是一个Scrapy中支持JavaScript渲染的工具,本节来介绍它的安装方式。 Scrapy-Splash的安装分为两部分。一个是Splash服务的安装,具体是通过Docker,安装之后,会…

用bind架设自己的智能DNS

中国的南北网络问题,是许多做网站的人的心病除了使用双通或者多通机房以外,还可以通过多台镜像服务器的方法来提高用户的访问速度 但是,如果使用的双通机房并不是单IP的,或者使用多台镜像的做法,就会面临多个不同的服务…

漫漫运维路——集群基础知识

集群的基本概念随着计算机科学的发展,对计算机的性能要求越来越高,比如在很多流量比较大的门户网站以及科学实验环境中需要海量计算的环境,这时候就迫切需要后端的服务器性能有提升。而对于提升后端服务器性能所采用的方式有两种,…

数据爆发时代,英特尔携手腾讯构筑全面的数据长城

作者 | 贾凯强 出品 | AI科技大本营(ID:rgznai100) 5G到来,边缘需求不断,IoT持续爆棚,数据在爆炸式增长。 在数据增长的过程中, 相应的其处理能力也需要增长,CPU等算力核心也在提升,…

python3 _笨方法学Python_日记_DAY3

Day3 习题 13: 参数、解包、变量from sys import argvscript, first, second, third argvprint("The script is called:",script) print("Your first variable is:",first) print("Your second variable is:",second) print("Your third…

动漫风格迁移 AnimeGANv2 ,发布线上运行 Demo

作者 | 神经星星出品 | HyperAI超神经By 超神经内容一览:最强二次元风格迁移模型 AnimeGAN 更新啦,现在可以在线上轻松运行模型,还可以调整风格参数,输出你想要的照片效果。关键词:风格迁移 机器视觉 二次元AnimeGANv2…

linux学习笔记一

常用命令 文件操作命令 cat命令 显示文件内容 复制代码 -b 从1开始对所有非空输出行进行编号 -n 从1开始对所有输出行进行编号 ctrls停止滚屏 ctrlq恢复滚屏 ctrlc终止命令的执行 cat file1 file2同时显示文件file1和file2的内容cat file1 file2 > file3将文件file1和f…

解决SecureCRT中文乱码

由于工作和学习需要在Windows7上使用Securecrt操作Linux(Red Hat Enterprise Linux 5)。一看汉字是乱码。Google一下。基本上是两个方面考虑解决问题:1、首先是Linux要支持汉字字符集:一般UTF-8。在etc/sysconfig/i18n中把LANG改成…

7000 字精华总结,Pandas/Sklearn 进行机器学习之特征筛选,有效提升模型性能

作者 | 俊欣来源 | 关于数据分析与可视化今天小编来说说如何通过pandas以及sklearn这两个模块来对数据集进行特征筛选,毕竟有时候我们拿到手的数据集是非常庞大的,有着非常多的特征,减少这些特征的数量会带来许多的好处,例如提高预…

徒手撸出一个类Flask微框架(三)根据业务进行路由分组

所谓分组就是按照前缀分布映射如&#xff1a;/product/(\w)/(?P<id>\d # 匹配/product/123123 的前缀比如什么类别&#xff0c;类别下的什么产品 等&#xff0c;用request path进行正则匹配&#xff0c;所以需要用到正则分组分析我们当前代码&#xff0c;只有__…

TCP编程函数和步骤

TCP编程的服务器端一般步骤是1、 创建一个socket&#xff0c;用函数socket()&#xff1b;2、 设置socket属性&#xff0c;用函数setsockopt(); * 可选3、 绑定IP地址、端口等信息到socket上&#xff0c;用函数bind();4、 开启监听&#xff0c;用函数listen()&#xff1b;5、 接…

OSD的主要实现方法和类型(转)

源&#xff1a;OSD的主要实现方法和类型 目前有两种主要的OSD实现方法&#xff1a;外部OSD发生器与视频处理器间的叠加合成;视频处理器内部 支持OSD&#xff0c;直接在视频缓存内部叠加OSD信息。 外部OSD发生器与视频处理器间的叠加合成的实现原理是&#xff1a;由一个MCU内建的…

为什么要研究游戏 AI 呢?

作者 | 叶鑫来源 | DatawhaleAI作为时下计算机算法的超级巨星&#xff0c;在例如CV、NLP、语音、机器人等诸多领域都有广泛的应用。而在游戏领域&#xff0c;AI的应用往往被认为只是把游戏角色拟人化&#xff0c;算法的第一印象也通常是强化学习。但实际当中&#xff0c;AI在游…

oracle 工具:tkprof

https://docs.oracle.com/cd/B10501_01/server.920/a96533/ex_plan.htm http://blog.csdn.net/dba_waterbin/article/details/8010629 oracle sql执行计划怎么看 https://zhidao.baidu.com/question/1178766860347033659.html

Linux环境编程--文件基本操作

Linux 下目录是/这样的 而windows是\怎么记呢&#xff1f;\和w是不是一样的反向&#xff1f;所以Linux的目录就是反的反向&#xff0c;好记了。 一&#xff1a;open函数名称&#xff1a;open目标&#xff1a;打开一个文件。头文件&#xff1a;#include <sys/types.h>#in…

Firefox插件

为什么80%的码农都做不了架构师&#xff1f;>>> 网站优化必备的9个Firefox插件 在网页设计制作中经常使用到的火狐浏览器插件工具&#xff1a; 1. Firebug Firebug是开发人员们钟爱火狐浏览器的一个重要原因&#xff0c;Firebug是火狐浏览器上一个集成式的强大调试…

马斯克公开支持“上班摸鱼”:让工作更愉快!

整理 | 王晓曼出品 | 程序人生 &#xff08;ID&#xff1a;coder _life&#xff09;11月16日&#xff0c;在国美集团批评员工上班摸鱼的通报中&#xff0c;一名员工在网易云音乐上使用了22.5G的流量格外显眼。11月18日&#xff0c;网易云音乐也紧跟热点上线了摸鱼计算器活动&am…

瀚思首发三款产品 推动大数据安全战略布局

安全已成为了当下社会最为关注的几个问题之一&#xff0c;随着大数据时代的来临&#xff0c;如今的安全问题也变得严峻和复杂。近日&#xff0c;HanSight瀚思在北京召开了产品战略暨融资发布会&#xff0c;推出了瀚思用户行为分析系统&#xff08;HanSight UBA&#xff09;、瀚…

Linux环境编程--编辑器基本操作

vim使用 新建文件 #vim hello.c 插入模式 按下I键&#xff0c;底下出现- - 插入- - 换行&#xff1a;按下Enter 删除字符&#xff1a;普通模式下按x 删除整行&#xff1a;按dd 恢复删除&#xff1a;按u 取消命令&#xff1a; CtrlR 对U后果弥补 复制&#xff1a;y y2w复制2个…

2021 IDEA大会开启AI思想盛宴,用“创业精神”做科研

11月22日上午10时许&#xff0c;由深圳市福田区人民政府、深圳市福田区科技创新局和粤港澳大湾区数字经济研究院&#xff08;International Digital Economy Academy, 简称“IDEA”&#xff09;联合举办的2021 IDEA大会在深圳福田开幕。大会以“The World Needs a Few Good IDE…

Android不同分辨率和不同密度适配

官方原文地址&#xff1a;http://developer.android.com/training/multiscreen/screendensities.html 本文主要介绍&#xff1a; 1.dip dp sp 简单用法 2.适配不同分辨率屏幕图片的处理方法 支持不同的密度或分辨率 本课介绍如何通过提供不同的资源和使用的测量分辨率独立单元支…

网络工程师成长日记333-某城市政府项目

网络工程师成长日记333-某城市政府项目 这是我的第333篇原创文章&#xff0c;记录网络工程师行业的点点滴滴&#xff0c;结交IT行业有缘之人 直接上干货&#xff0c;拓扑图&#xff1a; 工程目的&#xff1a;排除故障配置如下&#xff1a;LinWei#show running-configBuilding c…