有關函數cv2.imshow()處理不同圖像深度時的數據轉化問題

結論

當cv2.imshow()處理圖像深度爲CV_8U(默認範圍爲[0,255])時,按原數據顯示;當處理圖像深度爲CV_16U(默認範圍爲[0,65535])時,除以256,映射到[0,255];當圖像深度爲CV_32F和CV_64F時(默認範圍爲[0,1]),乘以255映射到[0,255];當碰到負數時,首先取其絕對值,然後按照上述圖像深度將超出數據範圍的部分採取截斷操作,最後映射到[0,255]顯示圖像

注:1. 圖像深度爲CV_32S在最新版本openCV4.1.0中已經無法顯示

       2. openCV中處理數據溢出採用飽和操作,numpy處理數據溢出採用求模操作

 

我們先來簡單介紹一下函數cv2.imshow()。

cv2.imshow(winname,mat)

概要

在一個指定窗口上顯示圖像

參數

  • winname:指定窗口的名字
  • mat:要顯示的圖像

通過以下代碼可以先看看官方文件中有關數據類型轉化的說明:

import cv2
help(cv2.imshow)

截取其中部分如下:

If the image is 8-bit unsigned, it is displayed as is.
If the image is 16-bit unsigned or 32-bit integer, the pixels are divided by 256. That is, the value range [0,255\*256] is mapped to [0,255].
If the image is 32-bit or 64-bit floating-point, the pixel values are multiplied by 255. That is, the value range [0,1] is mapped to [0,255].

翻譯過來就是,如果圖像數據類型爲8位無符號整數,即範圍[0,255],則按原有數據顯示;如果數據類型爲16位無符號整數或者32位有符號整數,則將數據除以256,映射到[0,255];如果數據類型爲32位或64位浮點數,則將數據乘以255,映射到[0,255]。

 

但太過籠統,下面我們通過實例來一步步驗證:

1. 圖像深度爲CV_8U,或者numpy數據類型爲uint8

import numpy as np
import cv2
#新建numpy數組,注意np.zero()創建的數據類型爲float64,所以先轉化爲uint8
img=np.zeros((500,500,3)).astype('uint8') 
#openCV顯示圖像爲BGR格式,通過下列方式,我們繪製兩條粗紅線
img[150:170,150:350]=[0,0,100]
img[350:370,150:350]=[0,0,255] 
cv2.imshow('img',img)
cv2.waitKey() 
cv2.destroyAllWindows()

結果如下,可以看出當圖像深度爲CV_8U時,cv2.imshow()按原有數據顯示,表現爲明暗不同的兩條紅線,數字越大,亮度越大

2. 圖像深度爲CV_16U,或者numpy數據類型爲uint16

import numpy as np
import cv2
#新建numpy數組,注意np.zero()創建的數據類型爲float64,這裏轉化爲uint16
img=np.zeros((500,500,3)).astype('uint16') 
#openCV顯示圖像爲BGR格式,通過下列方式,我們繪製兩條粗紅線
img[150:170,150:350]=[0,0,1000]
img[350:370,150:350]=[0,0,65525] 
cv2.imshow('img',img)
cv2.waitKey() 
cv2.destroyAllWindows()

結果如下,可以看到,當數據類型爲uint16,由於cv2.imshow()處理數據時要將圖像矩陣先除以256,所以當原數據大小爲1000時,亮度很小,幾乎看不到。

3. 圖像深度爲CV_32S,或者numpy數據類型爲int32

import numpy as np
import cv2
#新建numpy數組,注意np.zero()創建的數據類型爲float64,這裏轉化爲int32
img=np.zeros((500,500,3)).astype('int32') 
#openCV顯示圖像爲BGR格式,通過下列方式,我們繪製兩條粗紅線
img[150:170,150:350]=[0,0,1000]
img[350:370,150:350]=[0,0,65525] 
cv2.imshow('img',img)
cv2.waitKey() 
cv2.destroyAllWindows()

運行結果報錯,個人理解可能是openCV4.1.0版本中函數cv2.imshow()的顯示圖像不再支持CV_32S的圖像深度

4. 圖像深度爲CV_32F、CV_64F,或者numpy數據類型爲float32、float64

import numpy as np
import cv2
#新建numpy數組,注意np.zero()創建的數據類型爲float64
img=np.zeros((500,500,3))
#openCV顯示圖像爲BGR格式,通過下列方式,我們繪製三條粗紅線
img[150:170,150:350]=[0,0,-8000]
img[250:270,150:350]=[0,0,8000]
img[350:370,150:350]=[0,0,0.34]
cv2.imshow('img',img)
cv2.waitKey() 
cv2.destroyAllWindows()

結果如下:

當圖像深度爲CV_32F,CV_64F時,數據大小默認的範圍爲[0,1](注:這一點有別於numpy數組)。從圖像中可以看出cv2.imshow()在處理負數時首先將其轉化爲正數,而後採用截斷操作(即大於1的數保留爲1,其餘不變)。數據值爲1最明亮;數據值爲0,最暗。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章