【问题标题】:How to fix or balance the image with an white color overlay?如何修复或平衡带有白色叠加层的图像?
【发布时间】:2021-10-12 22:17:48
【问题描述】:

大家好,我有一张上面有白色覆盖层的图像,我正在尝试均衡颜色,或者换句话说,移除白色覆盖层,使其成为一种颜色。我是图像处理的新手,我想也许可以提取颜色通道,然后使用均衡直方图,如果可行的话?最好的方法是什么?谢谢!

【问题讨论】:

  • 你需要一个通用的算法,还是只修复这张图片? 不要“均衡”直方图。这是推测白色与图像的线性混合,因此校正也是线性/仿射运算(加法/减法/乘法/除法)
  • @ChristophRackwitz 很抱歉造成混乱,是的,我正在寻找解决此问题的算法
  • 好的,所以首先你需要一个区域的掩码。然后你会计算内部和外部的直方图。假设这些直方图应该是相似的,那么您将尝试通过线性变换将内部直方图与外部直方图匹配。您可以通过蛮力(彻底迭代参数)来做到这一点,或者我认为通过累积分布函数(CDF)有更直接的方法。你应该试一试。
  • 您可以尝试将内部的均值和标准差与外部匹配。见pyimagesearch.com/2014/06/30/super-fast-color-transfer-images。正如@Christoph Rackwitz 所说,您需要一个遮罩来识别较亮矩形的内部和外部,以获得统计数据。
  • 也许简单地均衡手段就足够了。所以使用掩码来获取内部和外部的平均值。得到差异。然后从图像较亮的中心减去差异。

标签: python opencv image-processing


【解决方案1】:

这是一个简单的尝试,将内部区域的平均值与外部区域的平均值匹配。它不能很好地工作,因为它是全局变化并且没有考虑整个图像的亮度变化。但是你可以玩弄它来开始。

它获取一个掩码图像并获取内部和外部区域的均值。然后获取差值并从内部区域中减去。

输入:

import cv2
import numpy as np

# load image 
img = cv2.imread('writer.jpg', cv2.IMREAD_GRAYSCALE)

# rectangle coordinates
x = 61
y = 8
w = 663
h = 401
    
# create mask for inner area
mask = np.zeros_like(img, dtype=np.uint8)
mask[y:y+h, x:x+w] = 255

# compute means of inner rectangle region and outer region
mean_inner = np.mean(img[np.where(mask == 255)])
mean_outer = np.mean(img[np.where(mask == 0)])

# compute difference in mean values
bias = 0
diff = mean_inner - mean_outer + bias

# print mean of each
print("mean of inner region:", mean_inner)
print("mean of outer region:", mean_outer)
print("difference:", diff)

# subtract diff from img
img_diff = cv2.subtract(img, diff)

# blend with original using mask
result = np.where(mask==255, img_diff, img)

# save resulting masked image
cv2.imwrite('writer_balanced.jpg', result)

# show results
cv2.imshow("IMAGE", img)
cv2.imshow("MASK", mask)
cv2.imshow("RESULT", result)
cv2.waitKey(0)
cv2.destroyAllWindows()

mean of inner region: 195.44008004122423
mean of outer region: 154.1415758021116
difference: 41.298504239112646

结果:

您可以更改偏差以使内部区域整体更亮或更暗。

添加

这是下一个改进顺序。只需测量彼此靠近的内部和外部最暗区域,然后对最亮区域执行相同操作。然后从测量中计算强度的线性变换并应用于图像。然后使用遮罩来混合两个图像。

这类似于@Christoph Rackwitz 提出的建议。除了他做了非常严格的计算,我只是做了一些视觉测量。

例如,这里是我测量的地方:

import cv2
import numpy as np

# load image 
img = cv2.imread('writer.jpg', cv2.IMREAD_GRAYSCALE)

# rectangle coordinates
x = 62
y = 8
w = 662
h = 401
    
# create mask for inner area
mask = np.zeros_like(img, dtype=np.uint8)
mask[y:y+h, x:x+w] = 255

# measure darkest and lightest neighboring regions inside and outside mask area of input
# darkest from chair in lower right
# brightest from background wall in upper left 
in1=95
out1=8
in2=250
out2=250

# compute linear transformation equation coefficients
# let x1=in1, y1=out1, x2=in2, y2=out2
# y1=a*x1+b
# y2=a*x2+b
# y2-y1 = a*(x2-x1)
# a = (y2-y1)/(x2-x1)
# b = y2 - a*x2

x1 = in1
y1 = out1 
x2 = in2
y2 = out2
a = (y2-y1)/(x2-x1)
b = y2 - a*x2
print("a:", a, "b:", b)

# process image with linear transformation
modified = (a * img.astype(np.float64) + b).clip(0,255).astype(np.uint8)

# blend with original using mask
result = np.where(mask==255, modified, img)

# save resulting masked image
cv2.imwrite('writer_balanced2.jpg', result)

# show results
cv2.imshow("IMAGE", img)
cv2.imshow("MASK", mask)
cv2.imshow("RESULT", result)
cv2.waitKey(0)
cv2.destroyAllWindows()

结果:

【讨论】:

  • 谢谢!
【解决方案2】:

这是我最好的尝试:

参考区域的灰度直方图,以及要修复的区域:

你看,与白色的混合导致直方图被挤压并向右移动。原始值 255 映射到 255,但原始值越暗,越亮。蒙版区域包含可能是黑色(靠背)的样本,这些样本在未触及的参考区域中也是黑色的,因此我们可以估计发生了什么……原始黑色被映射到约 88 的灰度值。

我在两个光谱中都找到了最小值并将其用于线性映射:

refmax = 255
refmin = gray[~mask].min()
fixmax = 255
fixmin = gray[mask].min()

composite = im.copy()
composite[mask] = np.clip((composite[mask] - fixmin) / (fixmax - fixmin) * (refmax - refmin) + refmin, 0, 255)

就是这样。

【讨论】:

  • 不太明白,但我会尝试寻找有关此的更多信息。谢谢!
猜你喜欢
  • 1970-01-01
  • 2021-05-05
  • 1970-01-01
  • 2019-05-23
  • 2018-09-25
  • 1970-01-01
  • 2018-03-05
相关资源
最近更新 更多