直方图均衡(单独)在这里不太可能起作用,因为它可以校正整个图像的亮度级别。
您在这里处理的是亮度的均匀降低,类似于滤光片的效果。
真正需要的是对看起来更暗的“补丁”上的平均亮度水平进行校正。因此,现在的问题是找到补丁并纠正它。
我将在这篇文章的其余部分使用 Octave,但正如您将看到的,将这个想法转换为 Python 并不难。
我们来看看伤害:
%Load the image and plot its average values by column.
a = imread('SomeImage.jpg');
imshow(a); %This should simply depict the image
%Let's take the cross section of the image by "squashing" all of its columns into their average.
q = mean(a);
plot(q);
结果如下:

这张图片最显着的特征是亮度水平的急剧下降,从左边算起大约是图像宽度的三分之一。
现在让我们通过将图像的所有行“挤压”成平均列来查看垂直横截面。您只需添加:
q2=mean(a');
plot(q2);
结果如下:

事实上,如果您有 MATLAB 方便,您可能想尝试一下surf(a)
,它会非常清楚地向您显示“盆地”。出于某种原因,当我尝试这样做时,Octave 的 surf 的三角形会缠结在一起。
对,那么,我们从中观察到什么?
不连续性两侧的图像是可预测的。看起来好像您只是将波形的一部分向下滑动......类似于中性密度过滤器的效果。有一个矩形的亮度只是一个下降。
第一张图片的问题比第二张图片的问题更严重。在第二张图像上,我们观察到一个大约 4 像素宽的尖锐不连续性,但它非常非常清晰。在第一张图像上,不连续的宽度约为 8 像素。这些像素中的任何数据都已被渐变“吞噬”。
在一维中工作(起初),您可以看到,只需向倾角添加一个值或从“步长”中减去一个值,您就可以或多或少地匹配不连续性两侧的两个区域的平均值。但是对于过渡带中的那些像素,您将不得不做其他事情(例如插值)来解决问题。该区域的数据已丢失。
(大)补丁在哪里?它大约从 85,78 开始,一直延伸到图像的边缘。X 点是通过将所有列压缩成一行然后查看不连续性开始的位置来找到的,Y 点是通过执行相同操作找到的,但这次将所有行压缩成一列。
让我们尝试修正 X 方向。首先,我们要摆脱过渡梯度。这是在像素 85-93 之间(虽然不是整个图像,请记住这是一个补丁,在这里我们试图纠正一维情况)。
Q = q;
Q(85:93) = 0;
plot(Q);

现在,校正亮度。差值大约是 36。我在这里所做的只是从像素 93 开始添加一个“步长”(一个常数值),如下所示:
m=93;
Q2 = Q+36*[zeros(1,m),ones(1,length(Q)-m)];
plot(Q2);
现在看起来像这样:

对于 8 个值的差距,你能做些什么?你可以用一个常数值填充它,但这将显示为一个 8 像素的“带”,它肯定是可见的。您可以做的另一件事是用一些高斯噪声填充它,这些噪声具有大约像素值 36 的平均值和足够的方差,因此您无法将其与周围的像素区分开来。不幸的是,因为在这种情况下,噪声将是不相关的,会再次显示为条带,但这一次更加“模糊”。最后,您可以做的另一件事是训练一个模型,该模型将从周围区域“生成”现实值,以便您优雅地“治愈”乐队。
这是基本思想。要自动找到梯度,您可以提取图像的梯度,也可以imgradient
在循环中使用局部斜率上的阈值进行类似的计算。
你的问题还没有结束。正如您在所有图像中看到的那样,图像中有不止 1 个“盆地”。你的第一张图片在右上方有一个光带,它直接进入它下方的黑暗中。
希望它们都是矩形的,因此您可以根据需要简单地重复完全相同的过程多次,直到图像包含“无盆地”。
希望这可以帮助。