如何使用白色叠加层修复或平衡图像?

How to fix or balance the image with an white color overlay?

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

这是将内部区域的平均值与外部区域的平均值相匹配的简单尝试。它的效果不是很好,因为它是全局变化,没有考虑整个图像的亮度变化。但是您可以先尝试一下。

它获取一张蒙版图像并获取内部和外部区域的均值。然后求差,从内部区域减去。

输入:

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()

结果:

这是我的最佳尝试:

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

你看,与白色的混合导致直方图被挤压并向右移动。原始值 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)

就是这样。