[英]hex <-> RGB <-> HSV Color space conversion with Python
[英]Increasing the speed of the color space conversion algorithm from HSV to RGB
我处理图像像素。 我想用特定的公式为我的图像着色,并在使用 HSV 后将图像转换并保存到 RGB 空间中。 Opencv有转换颜色空间的功能,但是图像的颜色改变了我的图像。 我使用 function 转换像素像素,但我的循环有很多时间要运行。 我在 Python 中写了一段代码,其中包含一个需要花费大量时间执行的循环。 您有哪些运营解决方案来减少执行时间? 我使用了线程,但它没有正确实现并且时间没有减少。 另外,我使用了 np.apply_along_axis,但是,这个 function 增加了运行时间!
for i in range(row):
for j in range(col):
final[i][j][0], final[i][j][1], final[i][j][2] = colorir.HSV(final[i][j][0], final[i][j][1], final[i][j][2], max_sva=255).rgb()
当我使用此代码转换颜色时,我的图像以我想要的正确颜色显示,但是当我使用以下 function 时,图像着色完全错误:
final = cv2.cvtColor(final,cv2.COLOR_HSV2RGB)
或者
final = matplotlib.colors.hsv_to_rgb(final)
我想到的另一个问题是,有没有一种方法可以保存颜色空间 HSV 中的图像而不将其转换为颜色空间 RGB? 不上色就错了吗? 这样我就不必使用上面的这段运行时代码来转换了?
编辑:
我的图像大小是可变的:例如 600x600 这些循环的执行时间大约为 15 秒,应该大约小于 1 秒。 我给灰度图像上色。
下面是我的可执行代码:
import numpy as np
from numpy import newaxis
import cv2
from colorir import HSV, sRGB
zero1 = np.zeros((row, col), dtype=int)
new1 = np.dstack((zero1, zero1, num12))
new1 = np.where(num12 > 250, 0, num12)
newww = np.where(new1 < 0, 0, new1)
minus = np.subtract(num1, num2)
minus_2 = minus
minus = np.where(minus <=0, 33, minus)
minus = np.where(num2 >= np.multiply(num1 , 1.1), 33, minus)
minus = np.where(np.logical_and(num2 <= np.multiply(num1 , 1.1),num2 >= np.multiply(num1 , 1)), 107, minus)
minus = np.where(num2 < np.multiply(num1 , 1), 209, minus)
a_255 = np.full([row, col], 255, dtype=int)
final = np.dstack((minus, newww, a_255))
for i in range(row):
for j in range(col):
final[i][j][0], final[i][j][1], final[i][j][2] = HSV(final[i][j][0], final[i][j][1], final[i][j][2], max_sva=255).rgb()
我的最终图像应该只包含我指定的绿色、蓝色和橙色 colors,但是函数 1 着色的图像是粉红色和黄色,与 colors 无关。
一个小例子:
final = [[[105, 213, 235], [105, 213, 235], [105, 213, 235], [105, 213, 235], [105, 213, 235], [105, 213, 235]]]
final = np.asarray(final)
final = cv2.cvtColor(final,cv2.COLOR_HSV2BGR)
cv2.imshow("image", final)
cv2.waitKey(0)
当我运行上面的示例代码时,使用cv2.cvtColor(final,cv2.COLOR_HSV2BGR)
,我遇到:
错误(不支持的输入图像深度:“VDepth::contains(depth)”,其中“depth”为 4 (CV_32S))
我必须使用np.float32
,但np.float32
颜色会破坏最终图像。
这里有两个问题:
cv2.COLOR_HSV2RGB
,而不是cv2.COLOR_HSV2BGR
。这是我最后的示例版本:
import numpy as np
import cv2
from colorir import HSV, sRGB
hsv = [[[105, 213, 235], [105, 213, 235], [105, 213, 235]]]
hsv = np.asarray(hsv)
rgb_colorir = np.zeros_like(hsv)
for i in range(hsv.shape[0]):
for j in range(hsv.shape[1]):
rgb_colorir[i][j][0], rgb_colorir[i][j][1], rgb_colorir[i][j][2] = HSV(hsv[i][j][0], hsv[i][j][1], hsv[i][j][2], max_sva=255).rgb()
hsv[:,:,0] //= 2 # OpenCV's different definition
hsv = hsv.astype(np.uint8) # OpenCV requires uint8
rgb_opencv = cv2.cvtColor(hsv, cv2.COLOR_HSV2RGB)
检查转换后的图像:
>>> rgb_colorir
array([[[ 88, 235, 39],
[ 88, 235, 39],
[ 88, 235, 39]]])
>>> rgb_opencv
array([[[ 91, 235, 39],
[ 91, 235, 39],
[ 91, 235, 39]]], dtype=uint8)
所以我们可以看到红色通道有一个小的差异,这很可能是由舍入误差引起的。 对于 OpenCV 的情况,我们必须将色调四舍五入到最接近的偶数度数(因为 integer 除以 2)。 应该很难看出这种差异。
如果你想使用更精确的转换,请注意colorir.HSV
只是调用colorsys.hsv_to_rgb
,并做了很多额外的工作,比如构建一个 object。但它除了规范化之外没有给你任何额外的东西。 直接使用colorsys.hsv_to_rgb
应该更快。 此外, colorsys
是标准库的一部分,直接使用它应该是首选。
使用np.apply_along_axis()
迭代你的图像。 这个应该是比较快的,但是不会像OpenCV的方案那么快。
import colorsys
rgb_colorsys = np.apply_along_axis(
lambda hsv: colorsys.hsv_to_rgb(hsv[0] / 360, hsv[1] / 255, hsv[2] / 255),
2,
hsv,
) * 255
结果:
>>> rgb_colorsys
array([[[ 87.77941176, 235. , 38.70588235],
[ 87.77941176, 235. , 38.70588235],
[ 87.77941176, 235. , 38.70588235]]])
当然,您可以尝试其他库,例如 scikit-image:
import skimage.color
rgb_skimage = skimage.color.hsv2rgb(hsv / [360, 255, 255]) * 255
Scikit-image 对于如何存储 HSV 值也有不同的定义。 它还适用于浮点格式,以避免舍入错误。 结果:
>>> rgb_skimage
array([[[ 87.77941176, 235. , 38.70588235],
[ 87.77941176, 235. , 38.70588235],
[ 87.77941176, 235. , 38.70588235]]])
使用 DIPlib(披露:我是作者):
import diplib as dip
hsv_dip = dip.Convert(dip.Image(hsv, tensor_axis=2), "SFLOAT")
hsv_dip.SetColorSpace("HSV")
rgb_dip = dip.ColorSpaceManager.Convert(hsv_dip / [1, 255, 1], "RGB")
结果:
>>> np.asarray(rgb_dip)
array([[[ 87.77941176, 235. , 38.70588235],
[ 87.77941176, 235. , 38.70588235],
[ 87.77941176, 235. , 38.70588235]]])
请注意 OpenCV 是唯一具有显着舍入误差的实现,其他实现产生相同的值。
对于浮点结果, np.round(...).astype(np.uint8)
将为您提供可以在 pyplot 中正常显示的 RGB 图像:
>>> np.round(rgb_dip).astype(np.uint8)
array([[[ 88, 235, 39],
[ 88, 235, 39],
[ 88, 235, 39]]], dtype=uint8)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.