繁体   English   中英

提高从 HSV 到 RGB 的颜色空间转换算法的速度

[英]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颜色会破坏最终图像。

这里有两个问题:

  1. OpenCV 将 0-180 的范围用于色调通道(因为 360 不适合 8 位整数)。
  2. OpenCV 默认为 BGR,但如果你想要 RGB,则需要使用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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM