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

anauzrmj  于 2023-01-21  发布在  其他
关注(0)|答案(1)|浏览(163)

我工作的图像像素。我想彩色化我的图像在一个特定的公式和转换和保存图像到RGB空间后,与HSV的工作。OpenCV有函数转换颜色空间,但图像的颜色改变了我的图像。我用函数转换像素像素,但是我的循环需要很多时间来运行。2我用Python写了一段代码,其中包含一个需要很多时间来执行的循环。3你有什么操作解决方案来减少执行时间?我使用了线程,但是它没有正确实现,时间也没有减少。另外,我使用了np. apply_along_axis,但是,这个函数增加了运行时间!

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()

当我用这段代码转换颜色时,我的图像以我想要的正确颜色显示,但当我使用下面的函数时,图像着色完全错误:

final = cv2.cvtColor(final,cv2.COLOR_HSV2RGB)

final = matplotlib.colors.hsv_to_rgb(final)

我想到的另一个问题是,有没有一种方法可以保存HSV颜色空间中的图像,而不需要将其转换为RGB颜色空间?而不需要将其着色错误?这样我就不必使用上面的运行时代码片段进行转换?
编辑:
我的图像大小是可变的:例如600 × 600,这些循环的执行时间大约是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()

我的最终图像应该只包含我指定的绿色、蓝色和橙色,但是函数1着色的图像是粉红色和黄色,以及不相关的颜色。
举个小例子:

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::包含(深度)",其中"深度"为4(CV_32S))
不得不使用np.float32,但是np.float32颜色会破坏最终的图像。

oprakyz7

oprakyz71#

这里有两个问题:

  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的情况,我们必须将色调舍入到最近的偶数度数(因为整数除以2)。要看到这个差异应该相当困难。
如果你想使用更精确的转换,请注意colorir.HSV只是调用colorsys.hsv_to_rgb,并做很多额外的工作,如构建一个对象。但它没有给你任何额外的东西,除了规范化。直接使用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)将得到一个RGB图像,可以在pyplot中正常显示:

>>> np.round(rgb_dip).astype(np.uint8)
array([[[ 88, 235,  39],
        [ 88, 235,  39],
        [ 88, 235,  39]]], dtype=uint8)

相关问题