python - 剪辑限制在 OpenCV CLAHE 中究竟意味着什么?
问题描述
我读过很多文章说剪辑限制是CDF斜率的限制。但是在OpenCV中,那个参数可以设置为0~999...,我不知道这个参数的最大值,不是PDF的总和等于1吗?斜率怎么会大于1?剪辑限制的另一种说法是每个灰度级计数的限制,例如,如果我将平铺设置为 (8,8),则该平铺中的任何灰度级都不会超过 64 像素,但如果我设置限制超过64,结果还在变化。请以任何观点启发我。
解决方案
因此,剪辑限制的实现方式如下:
- 为每个可能的像素强度计算概率密度函数 (PDF),假设我们有一个 8 位图像,因此 PDF 是一个索引为 0 到 255 的数组。PDF 是通过计算图像中的像素数来计算的该强度,例如,PDF(intensity = 0) = 26 表示图像中有 26 个像素,强度为 0。
- 计算出 PDF 后,代码将遍历 PDF 中的每个元素,并确定 PDF 中的该元素是否大于 clipLimit。因此,例如,clipLimit 为 4,我们从 PDF(0) = 26 开始,它大于 4。因此,代码在 4 by 处“剪切”强度为 0 的像素数
clipped = clipped + pdf[i] - clipLimit;
,剪切开始的位置在 0。然后裁剪 = 0 + 26 - 4 = 22。代码继续为 PDF(强度 = 1)、PDF(强度 = 2)、...、PDF(强度 = 255)执行此操作。最后,PDF 中没有单个元素大于clipLimit,并且超出的像素计数已存储在变量clipped 中。(就像 fmw42 所说的那样)。 - 然后,裁剪像素的数量在数组 PDF 中重新分布均匀。例如,假设 clipped = 128,那么 PDF 的几乎每个其他元素都会获得 +1 像素计数。所以,如果剪裁后的 PDF(0) = 4, PDF(1) = 2, PDF(2) = 0,那么重新分配后就是 PDF(0) = 4+1, PDF(1) = 2, PDF (2) = 0+1。请注意,在重新分配之后,之前处于最大值的一些像素,即 clipLimit,被略微推高超过了 clipLimit。
从Wikipedia来看,clipLimit 通常设置在 3 到 4 之间。当按上述方式实现剪辑限制时,直方图中任何元素的最大值都是有限的,因此,任意两个相邻元素之间的最大斜率(即强度变化)直方图中的元素是有限的。
- 一个不切实际但有帮助的练习是,假设大小为 1920 x 1080 像素的图像中的所有像素的强度为 1,因此 PDF 的开头是 PDF(0) = 0,PDF(1) = 2073600, PDF 的其余元素为 0。那么,CDF 的斜率 = (2073600-0)/(1-0) = 2073600。
- 然而,现在想象一下,对于同一张图像,我们将 clipLimit 设置为 4,并且整个图像只有一个直方图。剪裁后的 PDF 为:PDF(0) = 0、PDF(1) = 4、PDF(2) = 0,以此类推。剪裁后的最大斜率为 (4-0)/(1-0) = 4,远小于 2073600。重新分配后,每个直方图 bin 大约多出 8100 个像素,因此 PDF 将类似于 PDF(0) = 8100,PDF(1) = 8104,PDF(2) = 8100,以此类推。现在,剪裁和重新分配后 CDF 的最大斜率是 (8104-8100)/(1-0) = 4。
至于你的问题,PDF的总和确实是1。但是,这里的数组PDF存储了计数,即PDF的分子。因此,对于大小为 1920 x 1080 的图像,如果实际 PDF 是
- 概率(强度 = 0)= 4/(1920x1080)= 4/2073600
- P(强度 = 1) = 2/2073600
- P(intensity = 2) = 0/2073600 ,那么这些分数的总和确实是 1。这个在 OpenCV 源代码中实现的概率密度函数将在数组 PDF 中显示为:
- PDF(0) = 4
- PDF(1) = 2
- PDF(2) = 0 ,如果没有分母,这些元素的总和不会为 1。
代码的实现参考OpenCV源码。作为脚注,我对重新分配的实施做了一些简化,但希望它应该更容易理解。
推荐阅读
- c# - VSTS HttpBuildClient 更新定义异步抛出类型异常
- angular - 将普通对象注入 Angular 6 服务时出错
- javascript - ajax调用控制器后加载新页面
- perl - Perl 复制 VECT 文件的特定行
- bootstrap-4 - 关闭 - Bootstrap - 如何在 Bootstrap Studio 中对齐汉堡菜单的垂直位置
- c++ - 将指向 QML 字符串属性的指针传递给 C++
- arrays - 找到对以数组和 AVL 树组织的数据进行排序的最佳解决方案
- html - 如何在 xpath 中同时使用 (and) 和 (or)
- android - Firebase 函数响应返回 null
- r - 基于矩阵中的一列平均所有其他列