本文介绍了cvtColor()转换为HSV颜色空间后的Numpy 8/16/32位图像数据类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 cv2.cvtColor 将图像从RGB转换为HSV表示。但是当将 np.float32 dtype的结果图像转换为 np.uint16 np时。 uint8 通过重新缩放然后转换,使用 cv2.imshow 时生成的图像对于整数版本看起来不同。因此,我现在想知道我是否正确地完成了转换,或者这是否实际上是由于某些信息在转换过程中丢失了?我试图了解发生了什么,但无法弄清楚原因。

I'm converting an image from RGB to HSV representation by using cv2.cvtColor. But when converting the resulting image of np.float32 dtype to np.uint16 and np.uint8 by rescaling and then casting, the resulting images when using cv2.imshow look different for the integer versions. Thus, I am now wondering if I have done the conversion correctly or if this is actually caused by some information being lost during the conversion? I am trying to understand what's going on but couldn't figure out why.

import cv2
import numpy as np

im = cv2.imread(r'C:\Users\310293649\Desktop\photo.png')
print(im.dtype)
print(im)
cv2.namedWindow('im', cv2.WINDOW_NORMAL)
cv2.imshow('im',im)

#Conversion from 8uint to float32 before cvtColor()
im = im.astype(np.float32)          #Cast Image data type
im *= 1./255                         #Scale value to float32 range 0-1
print(im.dtype)                     #Print to check data type
print(im)                           #Print pixel value
#Colour Space Conversion to HSV
im = cv2.cvtColor(im, cv2.COLOR_BGR2HSV)
cv2.namedWindow('im1', cv2.WINDOW_NORMAL)
cv2.imshow('im1',im)

#Conversion from float32 to uint16
im *= 65535                         #Scale value to uint16 range 0-65535
print(im)                           #Check Value
im = im.astype(np.uint16)           #Cast Image data type
print(im.dtype)
cv2.namedWindow('im2', cv2.WINDOW_NORMAL)
cv2.imshow('im2', im)

#Conversion from uint16 to uint8
im = im*(255./65535)                #Scale value to uint8 range 0-255
print(im)                           #Check Value
im = im.astype(np.uint8)            #Cast Image data type
print(im.dtype)
cv2.namedWindow('im3', cv2.WINDOW_NORMAL)
cv2.imshow('im3', im)

示例图像:

Sample Images:

每次转换的结果:

Result for each conversion:

每张印刷品的数据:

>>>
========== RESTART: C:\Users\310293649\Desktop\DatatypeLearning.py ==========
uint8
[[[ 6  4  4]
  [15 13 13]
  [13 11 11]
  ...,
  [43 45 45]
  [43 45 45]
  [34 36 36]]

 [[ 9  7  7]
  [22 20 20]
  [19 17 17]
  ...,
  [49 51 51]
  [47 49 49]
  [36 38 38]]

 [[24 22 22]
  [28 26 26]
  [23 21 21]
  ...,
  [45 47 47]
  [41 43 43]
  [28 30 30]]

 ...,
 [[11 12 16]
  [ 6  7 11]
  [ 1  2  6]
  ...,
  [ 7  7  7]
  [ 7  7  7]
  [ 7  7  7]]

 [[10 11 15]
  [ 6  7 11]
  [ 2  3  7]
  ...,
  [ 7  7  7]
  [ 7  7  7]
  [ 7  7  7]]

 [[ 8  9 13]
  [ 6  7 11]
  [ 4  5  9]
  ...,
  [ 7  7  7]
  [ 7  7  7]
  [ 7  7  7]]]
float32
[[[ 0.02352941  0.01568628  0.01568628]
  [ 0.05882353  0.0509804   0.0509804 ]
  [ 0.0509804   0.04313726  0.04313726]
  ...,
  [ 0.16862746  0.17647059  0.17647059]
  [ 0.16862746  0.17647059  0.17647059]
  [ 0.13333334  0.14117648  0.14117648]]

 [[ 0.03529412  0.02745098  0.02745098]
  [ 0.08627451  0.07843138  0.07843138]
  [ 0.07450981  0.06666667  0.06666667]
  ...,
  [ 0.19215688  0.20000002  0.20000002]
  [ 0.18431373  0.19215688  0.19215688]
  [ 0.14117648  0.14901961  0.14901961]]

 [[ 0.09411766  0.08627451  0.08627451]
  [ 0.10980393  0.10196079  0.10196079]
  [ 0.09019608  0.08235294  0.08235294]
  ...,
  [ 0.17647059  0.18431373  0.18431373]
  [ 0.16078432  0.16862746  0.16862746]
  [ 0.10980393  0.11764707  0.11764707]]

 ...,
 [[ 0.04313726  0.04705883  0.0627451 ]
  [ 0.02352941  0.02745098  0.04313726]
  [ 0.00392157  0.00784314  0.02352941]
  ...,
  [ 0.02745098  0.02745098  0.02745098]
  [ 0.02745098  0.02745098  0.02745098]
  [ 0.02745098  0.02745098  0.02745098]]

 [[ 0.03921569  0.04313726  0.05882353]
  [ 0.02352941  0.02745098  0.04313726]
  [ 0.00784314  0.01176471  0.02745098]
  ...,
  [ 0.02745098  0.02745098  0.02745098]
  [ 0.02745098  0.02745098  0.02745098]
  [ 0.02745098  0.02745098  0.02745098]]

 [[ 0.03137255  0.03529412  0.0509804 ]
  [ 0.02352941  0.02745098  0.04313726]
  [ 0.01568628  0.01960784  0.03529412]
  ...,
  [ 0.02745098  0.02745098  0.02745098]
  [ 0.02745098  0.02745098  0.02745098]
  [ 0.02745098  0.02745098  0.02745098]]]
[[[  1.57284000e+07   2.18448906e+04   1.54200012e+03]
  [  1.57284000e+07   8.73798047e+03   3.85500024e+03]
  [  1.57284000e+07   1.00822871e+04   3.34100024e+03]
  ...,
  [  3.93204025e+06   2.91266455e+03   1.15650000e+04]
  [  3.93204025e+06   2.91266455e+03   1.15650000e+04]
  [  3.93204025e+06   3.64082983e+03   9.25200000e+03]]

 [[  1.57284000e+07   1.45632822e+04   2.31300000e+03]
  [  1.57284000e+07   5.95771875e+03   5.65400000e+03]
  [  1.57284000e+07   6.89840918e+03   4.88300000e+03]
  ...,
  [  3.93204025e+06   2.56999805e+03   1.31070010e+04]
  [  3.93204025e+06   2.67490112e+03   1.25930010e+04]
  [  3.93204025e+06   3.44920728e+03   9.76600000e+03]]

 [[  1.57284000e+07   5.46124707e+03   6.16800049e+03]
  [  1.57284000e+07   4.68106592e+03   7.19600049e+03]
  [  1.57284000e+07   5.69868750e+03   5.91100000e+03]
  ...,
  [  3.93204025e+06   2.78872144e+03   1.20790000e+04]
  [  3.93204025e+06   3.04813696e+03   1.10510000e+04]
  [  3.93204025e+06   4.36899463e+03   7.71000049e+03]]

 ...,
 [[  7.86415812e+05   2.04796504e+04   4.11200000e+03]
  [  7.86415250e+05   2.97885508e+04   2.82700000e+03]
  [  7.86415125e+05   5.46122266e+04   1.54200012e+03]
  ...,
  [  0.00000000e+00   0.00000000e+00   1.79900012e+03]
  [  0.00000000e+00   0.00000000e+00   1.79900012e+03]
  [  0.00000000e+00   0.00000000e+00   1.79900012e+03]]

 [[  7.86415062e+05   2.18449570e+04   3.85500024e+03]
  [  7.86415250e+05   2.97885508e+04   2.82700000e+03]
  [  7.86415250e+05   4.68105117e+04   1.79900012e+03]
  ...,
  [  0.00000000e+00   0.00000000e+00   1.79900012e+03]
  [  0.00000000e+00   0.00000000e+00   1.79900012e+03]
  [  0.00000000e+00   0.00000000e+00   1.79900012e+03]]

 [[  7.86415062e+05   2.52057109e+04   3.34100024e+03]
  [  7.86415250e+05   2.97885508e+04   2.82700000e+03]
  [  7.86415125e+05   3.64082109e+04   2.31300000e+03]
  ...,
  [  0.00000000e+00   0.00000000e+00   1.79900012e+03]
  [  0.00000000e+00   0.00000000e+00   1.79900012e+03]
  [  0.00000000e+00   0.00000000e+00   1.79900012e+03]]]
uint16
[[[ 254.07003891   84.99610895    6.        ]
  [ 254.07003891   33.99610895   15.        ]
  [ 254.07003891   39.22957198   13.        ]
  ...,
  [ 254.53696498   11.3307393    45.        ]
  [ 254.53696498   11.3307393    45.        ]
  [ 254.53696498   14.16342412   36.        ]]

 [[ 254.07003891   56.66536965    9.        ]
  [ 254.07003891   23.17898833   22.        ]
  [ 254.07003891   26.84046693   19.        ]
  ...,
  [ 254.53696498    9.99610895   51.        ]
  [ 254.53696498   10.40466926   49.        ]
  [ 254.53696498   13.42023346   38.        ]]

 [[ 254.07003891   21.24902724   24.        ]
  [ 254.07003891   18.21400778   28.        ]
  [ 254.07003891   22.17120623   23.        ]
  ...,
  [ 254.53696498   10.84824903   47.        ]
  [ 254.53696498   11.85992218   43.        ]
  [ 254.53696498   16.99610895   30.        ]]

 ...,
 [[ 254.93774319   79.6848249    16.        ]
  [ 254.93774319  115.90661479   11.        ]
  [ 254.93774319  212.49805447    6.        ]
  ...,
  [   0.            0.            7.        ]
  [   0.            0.            7.        ]
  [   0.            0.            7.        ]]

 [[ 254.93774319   84.99610895   15.        ]
  [ 254.93774319  115.90661479   11.        ]
  [ 254.93774319  182.14007782    7.        ]
  ...,
  [   0.            0.            7.        ]
  [   0.            0.            7.        ]
  [   0.            0.            7.        ]]

 [[ 254.93774319   98.07392996   13.        ]
  [ 254.93774319  115.90661479   11.        ]
  [ 254.93774319  141.66536965    9.        ]
  ...,
  [   0.            0.            7.        ]
  [   0.            0.            7.        ]
  [   0.            0.            7.        ]]]
uint8


推荐答案

不同产生的原因不是因为转换为整数时精度下降。实际上,问题是您希望能够与表示。但是,当表示为float32时,RGB三元组中的所有组件都介于0和1之间,这对于HSV三元组不再适用。对于HSV,第二和第三分量(即S和V)仍然在0和1之间,但第一个分量H(ue)是0到360之间的角度(参见的文档。

The difference arises not because of a decrease of accuracy when converting to integers. Actually, the problem is that you expect the HSV to work equivalently to the RGB representation. But whereas all components in an RGB triple are between 0 and 1 when represented as a float32, this no longer holds true for HSV triples. For HSV the second and third component (namely S and V) are still between 0 and 1 but the first component, H(ue), is an angle between 0 and 360 (see the documentation of cv2.cvtColor).

这对你的转换以及 cv2.imshow()都有问题,它要求0和0之间有三个组件。 1也是。在将所有值与65535相乘后,将dtype转换为 np.uint8 时,转换会导致溢出。阅读人们可能会期待调用 cv2.imshow 时内部转换的结果相同,但是 imshow 将传递的数组解释为RGB图像确实只是减少了大于1比1的所有值。

This is problematic for both, your conversion as well as cv2.imshow() which expects three components between 0 and 1 as well. While your conversion results in an overflow when you cast the dtype to np.uint8 after multiplying all values with 65535. After reading the documentation of cv2.imshow one might expect the same result for the internal conversion when calling cv2.imshow but as imshow interprets the passed array as an RGB image it does simply reduce all values that are bigger than 1 to 1.

如果您在转换前手动执行相同的操作,您将获得三次相同的图像:

If you manually do the same before your conversion, you will get the same image three times:

import cv2
import numpy as np

im = cv2.imread(r'C:\Users\310293649\Desktop\photo.png')
cv2.namedWindow('im', cv2.WINDOW_NORMAL)
cv2.imshow('im', im)

#Conversion from 8uint to float32 before cvtColor()
im = im.astype(np.float32)          #Cast Image data type
im /= 255.                          #Scale value to float32 range 0-1
#Colour Space Conversion to HSV
im = cv2.cvtColor(im, cv2.COLOR_BGR2HSV)
cv2.namedWindow('im1', cv2.WINDOW_NORMAL)
cv2.imshow('im1', im)

im[:, :, 0] = np.where(im[:, :, 0]>1.0, 1.0, im[:, :, 0])
im *= 65535                         #Scale value to uint16 range 0-65535
im = im.astype(np.uint16)           #Cast Image data type
cv2.namedWindow('im2', cv2.WINDOW_NORMAL)
cv2.imshow('im2', im)

#Conversion from uint16 to uint8
im = im*(255./65535)                #Scale value to uint8 range 0-255
im = im.astype(np.uint8)            #Cast Image data type
cv2.namedWindow('im3', cv2.WINDOW_NORMAL)
cv2.imshow('im3', im)

这将为 np.float32 np.uint16 np提供相同的图像.uint8

(有趣的是, cv2.imwrite 似乎没有做同样的转换,因为得到了不同的结果对于 np.float32 版本。)

(Funnily, cv2.imwrite does not seem to do the same conversion, as one gets a different result for the np.float32 version.)

这篇关于cvtColor()转换为HSV颜色空间后的Numpy 8/16/32位图像数据类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-28 21:26