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

像往常一样,我们导入库,如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')

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

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');

由于图像是在夜间拍摄的,因此图像的特征比较模糊,这也在像素强度值的直方图上观察到,其中 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');

通过将实际 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’)

请注意,所有通道几乎都具有相同的 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');

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

现在,让我们尝试使用其他函数作为目标 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);

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

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

distribution(cathedral, logistic, 90, 30);

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

结论

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

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

Github代码连接:

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

往期精彩回顾适合初学者入门人工智能的路线及资料下载机器学习及深度学习笔记等资料打印机器学习在线手册深度学习笔记专辑《统计学习方法》的代码复现专辑
AI基础下载黄海广老师《机器学习课程》视频课黄海广老师《机器学习课程》711页完整版课件

本站qq群955171419,加入微信群请扫码:

【CV】使用直方图处理进行颜色校正相关推荐

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

    作者 | 小白 来源 | 小白学视觉 在这篇文章中,我们将探讨如何使用直方图处理技术来校正图像中的颜色. 像往常一样,我们导入库,如numpy和matplotlib.此外,我们还从skimage 和s ...

  2. 使用直方图处理进行颜色校正

    点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 在这篇文章中,我们将探讨如何使用直方图处理技术来校正图像中的颜色. ...

  3. CV中直方图比较方法

    为了比较两个直方图(H1和H2)(H_{1}和H_{2})(H1​和H2​),首先必须选择度量(d(H1H2))(d(H_{1}H_{2}))(d(H1​H2​)),以表示两个直方图匹配的程度. Op ...

  4. 使用OpenCV,Numpy计算直方图,Matplot绘制直方图及分析

    使用OpenCV,Numpy计算直方图,Matplot绘制直方图及分析 1. 效果图 2. 原理 3. 源码 3.1 直方图3种计算方法和2种绘制方法 3.2 Mask遮罩图像直方图 参考 这篇博客将 ...

  5. opencv进阶学习笔记7:直方图,直方图均衡化,直方图比较,直方图反向投影

    基础版传送门: python3+opencv学习笔记汇总目录(适合基础入门学习) 进阶版笔记目录链接: python+opencv进阶版学习笔记目录(适合有一定基础) 直方图基础讲解: opencv学 ...

  6. 基于python的对比度增强(线性变换、直方图正规化、直方图均衡化、CLAHE)

    线性变换 假设输入图像为I,宽为W,高为H,输出图像为O,图像的线性变换可以用以下公式定义: O(r,c)=a×I(r,c)+b,0≤r<H,0≤c<WO(r, c) = a × I(r, ...

  7. 【Opencv】【C++】 Opencv之calcHist() 计算直方图

    OpenCV 2.4.13 calcHist 通过图像计算直方图 函数声明如下: void calcHist( const Mat* images, int nimages,const int* ch ...

  8. OpenCV图像处理学习二十,图像直方图均衡化原理与实现

    一.图像直方图的概念 图像直方图,是指对整个图像在灰度范围内的像素值(0~255)统计出现频率次数,据此生成的直方图,称为图像直方图.直方图反映了图像灰度的分布情况,是图像的统计学特征.图像的灰度直方 ...

  9. python comparehist_opencv+python -- 图像直方图应用

    直方图均衡化 cv2.equalizeHist函数原型:equalizeHist(src[, dst]) .函数equalizeHist的作用:直方图均衡化,提高图像质量. createCLAHE函数 ...

最新文章

  1. Eclipse生成jar文件
  2. 解决事件多次绑定,执行多次问题
  3. CSS三大特性(CSS层叠性、CSS继承性、CSS优先级)
  4. AttributeError: module ‘tensorflow‘ has no attribute ‘Session‘错误解决
  5. php empty详解
  6. GNU make manual 翻译( 一百八十一)
  7. 【完结】16篇图像分类干货文章总结,从理论到实践全流程大盘点!
  8. 使用命名空间解决名字冲突
  9. c语言is stack empty,C语言实现栈的问题
  10. Python中的高阶函数sorted
  11. java B2B2C springmvc mybatis电子商务平台源码-消息队列之RocketMQ
  12. 安装串口设备驱动时遇到 Windows 无法验证此设备所需的驱动程序的数字签名。最近的硬件或软件更改安装的文件可能未正确签名或已损坏,或者可能是来自未知来源的恶意软件. 问题该如何处理?...
  13. Windows 8及以上系统安装好SQL Server 2008之后找不到SQL Server配置管理器的问题
  14. es管理kabina_ES和Kibana在Linux上的安装
  15. Full internet technology map. 最全的互联网技术图谱
  16. Python菜鸟快乐游戏编程_pygame(5)
  17. 27. 面向对象程序设计(2)
  18. 微信电脑版真的要来了 微信Windows版客户端1.0 Alpha推出
  19. linux vim命令的意思,Linux 中 vim 是什么意思?
  20. python将图片合并到PDF

热门文章

  1. 解决 wget 使用 https 下载报错的问题
  2. [WPF系列]-DynamicResource与StaticResource的区别
  3. Linux更改终端的用户名和主机名的颜色
  4. pom.xml增加依赖
  5. MySQL创建用户与授权方法
  6. js正則表達式--验证表单
  7. Js获取地址栏参数值
  8. python模块之keyword
  9. 使用c#类库绘制柱状图
  10. android adb server is out of date