Python 如何将一幅图像的亮度应用到另一幅图像上

How to apply brightness from one image onto another in Python

我正在尝试使用具有 3 种颜色的图像和 Perlin noise 灰度图像制作纹理。

这是原图:

这是灰度 Perlin 噪声图像:

我需要做的是将原始图像的亮度应用到灰度图像上,这样柏林噪声图像中的最暗和最亮亮度不再是 100% 黑色 (0) 和 100% 白色 (1),而是取自原始图像。然后,将新的亮度映射从灰度 Perlin 噪声图像应用回原始图像。

这是我试过的:

from PIL import Image

alpha = 0.5
im = Image.open(filename1).convert("RGBA")
new_img = Image.open(filename2).convert("RGBA")
new_img = Image.blend(im, new_img, alpha)
new_img.save("foo.png","PNG")

这是我得到的输出:

这是错误的,但想象一下深色、浅橙色和亮色具有与灰度图像相同的渐变,但没有 100% 黑色或 100% 白色。

我认为我需要:

  1. 将原始图像转换为 HSV(好吧,我已经尝试使用 colorsysmatplotlib 中的一些函数,它们给了我奇怪的数字。

  2. 从原始图像中获取最高和最低 V 值。

  3. 将灰度图像转换为HSV

  4. 使用原始 HSV 图像中的 V 值变换或规范化(我想这就是所谓的)灰度 HSV

  5. 使用新的 transformed/normalized 灰度 V 值重新映射所有原始 V 值。

我不太了解Python,但也许可以尝试将 int 转换为 float 或 double。也许它会起作用

为什么它不起作用?

您使用的方法不会按预期工作,因为您不是保留一张图像的颜色和饱和度信息并获取另一张图像的亮度信息(全部或部分),而是只是对两张图像的所有通道进行插值同时,基于一个常量alphaas stated on the docs

PIL.Image.blend(im1, im2, alpha)

Creates a new image by interpolating between two input images, using a constant alpha: out = image1 * (1.0 - alpha) + image2 * alpha

[...]

alpha – The interpolation alpha factor. If alpha is 0.0, a copy of the first image is returned. If alpha is 1.0, a copy of the second image is returned. There are no restrictions on the alpha value. If necessary, the result is clipped to fit into the allowed output range.


基本工作示例

首先,让我们运行一个基本示例。我将使用 cv2 而不是 PIL,只是因为我更熟悉它并且我已经在我的机器上安装了它。

我还将使用 HSLcv2 中的 HLS)而不是 HSV,因为我认为这将产生更接近您可能的输出正在寻找。

import cv2

filename1 = './f1.png'
filename2 = './f2.png'

# Load both images and convert them from BGR to HLS:

img1 = cv2.cvtColor(cv2.imread(filename1, cv2.IMREAD_COLOR), cv2.COLOR_BGR2HLS)
img2 = cv2.cvtColor(cv2.imread(filename2, cv2.IMREAD_COLOR), cv2.COLOR_BGR2HLS)

# Copy img1, the one with relevant color and saturation information:

texture = img1.copy()

# Replace its lightness information with the one from img2:

texture[:,:,1] = img2[:,:,1]

# Convert the image back from HLS to BGR and save it:

cv2.imwrite('./texture.png', cv2.cvtColor(texture, cv2.COLOR_HLS2BGR))

这是最终输出:


️调整亮度

好的,所以我们有一个简单的案例,但你可能不想用 img2 完全替换 img1 的亮度,所以在那种情况下只需替换这一行:

texture[:,:,1] = img2[:,:,1]

有了这两个:

alpha = 0.25
texture[:,:,1] = alpha * img1[:,:,1] + (1.0 - alpha) * img2[:,:,1]

现在,您将保留 img125% 亮度和 img275% 亮度,您可以根据需要进行调整。

对于 alpha = 0.25,输出将如下所示:


HSL & HSV

尽管 HSL and HSV look quite similar, there are a few differences,主要是关于它们如何表示纯白色和浅色,这会使该脚本在使用其中一种时生成的图像略有不同:

我们只需要改变一些东西就可以让它与 HSV:

一起工作
import cv2

filename1 = './f1.png'
filename2 = './f2.png'

# Load both images and convert them from BGR to HSV:

img1 = cv2.cvtColor(cv2.imread(filename1, cv2.IMREAD_COLOR), cv2.COLOR_BGR2HSV)
img2 = cv2.cvtColor(cv2.imread(filename2, cv2.IMREAD_COLOR), cv2.COLOR_BGR2HSV)

# Copy img1, the one with relevant color and saturation information:

texture = img1.copy()

# Merge img1 and img2's value channel:

alpha = 0.25
texture[:,:,2] = alpha * img1[:,:,2] + (1.0 - alpha) * img2[:,:,2]

# Convert the image back from HSV to BGR and save it:

cv2.imwrite('./texture.png', cv2.cvtColor(texture, cv2.COLOR_HSV2BGR))

这是使用 HSV:

时第一个示例的样子

这是第二个例子(alpha = 0.25):

您可以看到最明显的差异出现在最亮的区域。