python - 使用 Numpy 更有效地改变色调
问题描述
我正在制作一个在线图像编辑器,并且我正在实现一个 Hue/Sat/Lum 编辑器。这是我用给定值更改图像的功能。
def make_edit(pixels, hue, sat, lum):
shape = pixels.shape
new = np.empty(shape)
print(time.time())
for row_count, row in enumerate(pixels):
for pixel_count, p in enumerate(row):
new_hue = p[0] + hue
if new_hue < 0:
new_hue += 255
elif new_hue > 255:
new_hue -= 255
new_sat = p[1] + sat
if new_sat < 0:
new_sat += 255
elif new_sat > 255:
new_sat -= 255
new_lum = p[2] + lum
if new_lum < 0:
new_lum = 0
elif new_lum > 255:
new_lum = 255
new[row_count, pixel_count] = np.array([new_hue, new_sat, new_lum])
print(time.time())
return new
该函数采用一个形状为 numpy 的数组(高度、宽度、3)。我逐个像素地做,然后将色调、饱和度和亮度值添加到每个像素。然而,这需要 13 秒(在 (648, 1152, 3) 形状的阵列上),显然太长了。是否有一个 numpy 函数可以将所有值抵消我给它的数量。ps 该功能还没有工作,hue 似乎可以,但是 sat 和 lum 没有给出正确的图像。
解决方案
我不认为您的算法或接受的答案是正确的-如果您将pixels
数组创建为uint8
(而不是int64
当前的),您将看到这一点,如果您将输出限制在范围 0.. 255.
您需要将色调与饱和度和亮度区别对待。色调是圆形的,这意味着它“环绕”了一个 0..255 “度”的圆圈。这意味着当它达到 255 并且您添加 1 时,您应该回到零并重新开始。在数学上,这意味着一个模数%
。饱和度和亮度不是圆形的,这意味着如果图像几乎完全明亮,比如 250,如果将亮度增加 100,它应该最大程度地“烧毁”。从数学上讲,这是“剪裁”。饱和度也是如此。
所以,我相信你想要更像这样的东西:
#!/usr/bin/env python3
import numpy as np
def make_edit(im, hue, sat, lum):
# Make signed and larger to accommodate wrap-around
im = im.astype(np.int32)
# Add constant amount of hue to each pixel, wrapping around at 255
im[:,:,0] = (im[:,:,0] + hue) % 256
# Add constant amount of saturation, and lightness to each pixel
im[:,:,1] += sat
im[:,:,2] += lum
# Clip results to range 0..255 and return as uint8
return np.clip(im,0,255).astype(np.uint8)
# Make our randomness deterministic!
np.random.seed(42)
# Create 4x2 array of HSL pixels - note UINT8
im = np.random.randint(0,255,(2,4,3),dtype=np.uint8)
# array([[[102, 220, 225],
# [ 95, 179, 61],
# [234, 203, 92],
# [ 3, 98, 243]],
#
# [[ 14, 149, 245],
# [ 46, 106, 244],
# [ 99, 187, 71],
# [212, 153, 199]]], dtype=uint8)
res = make_edit(im, 100, 50, 20)
print(res)
#[[[202 255 245]
# [195 229 81]
# [ 78 253 112]
# [103 148 255]]
#
# [[114 199 255]
# [146 156 255]
# [199 237 91]
# [ 56 203 219]]]
res = make_edit(im, -100, -50, -20)
print(res)
#[[[ 2 170 205]
# [251 129 41]
# [134 153 72]
# [159 48 223]]
#
# [[170 99 225]
# [202 56 224]
# [255 137 51]
# [112 103 179]]]
请注意,如果您只想通过在终端中运行命令来测试代码,则可以使用ImageMagick 。您可以像这样使用-modulate运算符:
magick INPUTIMAGE -modulate BRIGHTNESS,SATURATION,HUE OUTPUTIMAGE
例如,将亮度减半:
magick input.png -modulate 50 result.jpg
要将亮度保持在其先前值的 100% 不变,请将饱和度增加 20% 并将色相逆时针旋转 90 度(因为 180 的 50% 是 90):
magic input.png -modulate 100,120,50 result.jpg
关键词:Python,图像处理,色调旋转,HSL,HSV,调制。
推荐阅读
- c++ - 屏幕上字符的“宽度”
- javascript - VueJS:需要在重新加载页面之前清除浏览器缓存
- xcode - Safari iphone模拟器调试不起作用
- bash - 通过终端断开 Wi-Fi
- java - Docker CMD + ENTRYPOINT 与命令行行为不匹配
- python - 循环遍历每个元素并使用该元素作为 GBM 中的输出列名
- c++ - 如何在不将该服务的头文件包含在该类头中的情况下将模板化服务传递给类?
- asp.net - 创建一个选择框来加载数据而不刷新页面
- python - 你可以使用 PRAW 在 subreddit 中找到某人的第一条评论吗?
- c# - 为什么我的图像没有按预期加载和移动?