问题:
我已经使用一些循环定义了自己的色彩空间(黄-蓝),并希望使用一些后处理过滤器将标准HD图像从RGB实时转换为YB,但我编写的方法执行此有利任务的速度较慢。
上下文:
我想知道狗会看到什么颜色,结果发现它们分不清绿色和红色:
所以我决定定义我自己的YB色彩空间,如下图所示:
∮ ∮ ∮ ∮ ∮一个月一个月
bits = 8
values = 2 ** bits - 1
color_count = values * 6
def hues():
lst = []
for i in range(color_count):
r = g = b = 0
turn = (i // values) + 1
if turn == 1:
r = values
g = i % values
b = 0
elif turn == 2:
r = values - i % values
g = values
b = 0
elif turn == 3:
r = 0
g = values
b = i % values
elif turn == 4:
r = 0
g = values - i % values
b = values
elif turn == 5:
r = i % values
g = 0
b = values
elif turn == 6:
r = values
g = 0
b = values - i % values
r = round(r / values * 255)
g = round(g / values * 255)
b = round(b / values * 255)
lst.append((r, g, b))
return lst
def dues():
lst = []
for i in range(color_count):
r = g = b = 0
turn = (i // values) + 1
if turn == 1:
r = values
g = values
b = round((values - i % values) / 2)
elif turn == 2:
r = values
g = values
b = round((i % values) / 2)
elif turn == 3:
if i % values < values / 2:
r = values
g = values
b = round((values / 2 + i % values))
else:
r = round((3 / 2 * values - i % values))
g = round((3 / 2 * values - i % values))
b = values
elif turn == 4:
r = round((values - i % values) / 2)
g = round((values - i % values) / 2)
b = values
elif turn == 5:
r = round((i % values) / 2)
g = round((i % values) / 2)
b = values
elif turn == 6:
if i % values < values / 2:
r = round((values / 2 + i % values))
g = round((values / 2 + i % values))
b = values
else:
r = values
g = values
b = round((3 / 2 * values - i % values))
r = round(r / values * 255)
g = round(g / values * 255)
b = round(b / values * 255)
lst.append((r, g, b))
return lst
def rgb_to_hsl(color: tuple):
r, g, b = color
r /= 255
g /= 255
b /= 255
cmax = max(r, g, b)
cmin = min(r, g, b)
delta = cmax - cmin
h = 0
l = (cmax + cmin) / 2
if delta == 0:
h = 0
elif cmax == r:
h = ((g - b) / delta) % 6
elif cmax == g:
h = ((b - r) / delta) + 2
elif cmax == b:
h = ((r - g) / delta) + 4
h *= 60
if delta == 0:
s = 0
else:
s = delta / (1 - abs(2 * l - 1))
return h, s, l
def hsl_to_rgb(color: tuple):
h, s, l = color
c = (1 - abs(2 * l - 1)) * s
x = c * (1 - abs((h / 60) % 2 - 1))
m = l - c / 2
r = g = b = 0
if 0 <= h < 60:
r = c
g = x
elif 60 <= h < 120:
r = x
g = c
elif 120 <= h < 180:
g = c
b = x
elif 180 <= h < 240:
g = x
b = c
elif 240 <= h < 300:
r = x
b = c
elif 300 <= h < 360:
r = c
b = x
r = round((r + m) * 255)
g = round((g + m) * 255)
b = round((b + m) * 255)
return r, g, b
在保存列表值时,我获得了预期的色调:
现在,主要处理包括按以下顺序逐个像素地转换颜色:
1.获取RGB
- RGB--〉HSL
1.将色调值更改为dues_hsl
列表中的相应值
1.新建HSL--〉RGB
1.在另一个数组中的相同坐标处设置新的RGB值
对图像中的每个像素重复该过程,并且在尺寸为481 x 396
像素的测试图像上花费大约58秒
输入和输出:
一个四个一个一个一个五个一个
相同代码:
defining.py
from PIL import Image
import numpy as np
from calculating import hues, dues
from calculating import rgb_to_hsl as hsl
from calculating import hsl_to_rgb as rgb
hues = hues()
dues = dues()
# Hues = human hues
# Dues = dog hues
hues_hsl = [hsl(i) for i in hues]
dues_hsl = [hsl(i) for i in dues]
img = np.array(Image.open('dog.png').convert('RGB'))
arr_blank = np.zeros(img.shape[0:3])
print(arr_blank.shape)
print(img.shape[0:3])
total = img.shape[0] * img.shape[1]
for i in range(img.shape[0]):
for j in range(img.shape[1]):
hsl_val = hsl(tuple(img[i, j]))
h = dues_hsl[hues_hsl.index(min(hues_hsl, key=lambda x: abs(x[0] - hsl_val[0])))][0]
pixel = np.array(rgb((h, hsl_val[1], hsl_val[2])))
arr_blank[i, j, :] = pixel
print(f'{i * img.shape[1] + j} / {total} --- {(i * img.shape[1] + j)/total*100} %')
print(arr_blank)
data = Image.fromarray(arr_blank.astype('uint8'), 'RGB')
data.save('dog_color.png')
结论:
在这之后,我想添加一个高斯模糊过滤器,实时转换后,但这是需要很长的时间才一帧。有什么办法可以提高速度?
机器信息:
如果此信息有帮助:i7 - 10750H@2.6Ghz,固态硬盘,16 GB内存
谢谢!
2条答案
按热度按时间x7rlezfr1#
我忘了枕头也做HSV一样好,所以不需要OpenCV。
这在我的机器上执行大约0.45秒。
5kgi1eie2#
第1条备注:你不能像这样改变色彩空间。因为当你看到一种颜色时,人眼会解读它(因此被人类RGB图像格式)显示为黄色,例如(255,255,0),你不知道它是由黄色频率组成的(例如570 nm)激发我们的红色和绿色视锥,但不是蓝色的。如果它是由红色频率的混合物(例如690 nm)和绿色频率(530 nm),或者导致相同的红色和绿色锥体饱和(255,255)和蓝色锥体未被触摸(0)的任何其他光谱。
你需要这些信息来推断这两个狗锥是如何受到影响的。
换句话说,人的颜色和狗的颜色之间没有任何Map,用数学的话来说,真实的颜色空间(∞维,一个光谱)和人的颜色空间(3D,简化为:在真实的颜色空间和狗颜色空间(2D,也是为了简化)之间存在另一投影。但是那些投影轴不包括在另一个中。因此,在3D人类颜色空间和2D狗颜色空间之间不存在任何投影。仅利用人类如何看到颜色的知识,无法知道狗如何看到颜色;你需要知道真实的的颜色。你可以用超光谱相机来做这件事(并且做两个投影来计算人类的rgb图像和狗的yb图像)。这是假设相当天真的(但在第一近似中是正确的)想法,即这些颜色遵循初等大学水平的线性代数,而实际上,它并不完全如此。
也就是说,基于PIL或OpenCV的解决方案是一种解决方案,但更一般地说,如果你不信任PIL或OpenCV,或任何现有的库颜色模型,并真的想发明你的轮子(我尊重这一点;没有更好的方法来理解事物,那就是重新发明轮子),那么你必须遵守的一条规则就是 * 永远不要在像素上迭代 *。如果你这样做,你就失去了性能匹配。Python非常非常慢。它仍然是一种流行语言的唯一原因,以及为什么仍然有用Python制作的快速程序,是因为python编码器做了它所需要的任何事情,所以计算繁重的循环(在图像处理中,那些是像素上的循环)并不是真的在python中制作的。
所以你必须依靠numpy来对所有像素执行操作,而不是自己编写for循环。
例如,这里重写了
rgb_to_hsl
,用numpy进行批量计算,也就是说,rgb_to_hsl
不是用单一颜色调用的,而是用整个颜色数组(2d数组)调用的,也就是一个图像