cvtColor() 转换为 HSV 色彩空间后的 Numpy 8/16/32 位图像数据类型

Sac*_*reD 4 python opencv numpy colors image-processing

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

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)
Run Code Online (Sandbox Code Playgroud)

示例图片: 在此输入图像描述

每次转换的结果: 在此输入图像描述

每次打印的数据:

>>> 
========== 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
Run Code Online (Sandbox Code Playgroud)

jot*_*asi 5

出现差异并不是因为转换为整数时精度降低。实际上,问题在于您期望HSV与RGB表示方式等效。但是,虽然当表示为 float32 时 RGB 三元组中的所有分量都在 0 和 1 之间,但对于 HSV 三元组来说,这不再适用。对于 HSV,第二个和第三个分量(即 S 和 V)仍然介于 0 和 1 之间,但第一个分量 H(ue) 是 0 到 360 之间的角度(请参阅 的文档cv2.cvtColor

这对于您的转换以及cv2.imshow()需要 0 到 1 之间的三个分量的转换都是有问题的。np.uint8虽然在将所有值与 65535 相乘后将dtype 转换为 时,转换会导致溢出。阅读文档cv2.imshow后,调用时可能会期望内部转换得到相同的结果,cv2.imshow但将imshow传递的数组解释为 RGB 图像,它只是将所有大于 1 的值减少到 1。

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

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)
Run Code Online (Sandbox Code Playgroud)

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

在此输入图像描述

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