使用 tiff/png 文件类型对 uint16_t/float 数据类型存取的无聊实验

最近看到了几篇博客,自己又比较无聊,所以做了一系列OpenCV储存和读取不同格式和不同数据类型的对比实验,具体来说,对比的是tiffpng两种文件类型和float32uint16_t两种数据类型对于数据的影响。


实验环境

Python3.7.3opencv-python(4.1.0.25)

先说结论:

  1. imshow函数对uint16_t数据友好,对float数据不友好(显示不正常,需要手动映射到8位数据来可视化)。
  2. imwrite函数,对tiff格式友好(无数制转换和损失),对png格式基本上友好,也就是存取uint16_t完全OK。
  3. uint16_t类型,png格式,显示没问题,存储读取没问题,比较可靠。

代码:

生成随机图片:

import numpy as np
import cv2

def fun1(im):
    im=np.asarray(im,np.float32)
    return im
def fun2(im):
    im=np.asarray(im,np.uint16)
    return im
if __name__ == '__main__':
    #set a depth map using np.random
    img=np.random.randint(0,65535,size=(600,600))
    img1=fun1(img)
    cv2.imshow("float_saved",img1)
    cv2.imwrite('float_saved.png',img1)
    img2=fun2(img)
    cv2.imshow("uint_saved",img2)
    cv2.imwrite('uint_saved.png',img2)
    cv2.waitKey(500)
    
    for row in range(0,20):
        for column in range(0,20):
            if img[row][column] != .0:
                print("row:{}, column:{}, x:{}, y:{}, value_img:{}, value_img1:{}, value_img2:{}"
                      .format(row,column,column,row,img[row][column],img1[row][column],img2[row][column]))

用PIL加载图片的代码:

import numpy as np
import matplotlib.pyplot as plt
from PIL import Image
def load_image(filename):
    im=Image.open(filename)
    return im
if __name__ == '__main__':
    im1=load_image('float_saved.png')
    im2=load_image('uint_saved.png')
    plt.subplot(121)
    plt.imshow(im1)
    plt.subplot(122)
    plt.imshow(im2)
    plt.show()

用OpenCV加载图片的代码:

import cv2
img1=cv2.imread("float_saved.png",-1)
cv2.imshow("float_saved -1",img1)

img2=cv2.imread("uint_saved.png",-1)
cv2.imshow("uint_saved -1",img2)

img3=cv2.imread("uint_saved.png")
cv2.imshow("uint_saved 1",img3)

img4=cv2.imread("float_saved.png",cv2.IMREAD_ANYCOLOR|cv2.IMREAD_ANYDEPTH)
cv2.imshow("float_saved any|any",img4)

img5=cv2.imread("uint_saved.png",cv2.IMREAD_ANYCOLOR|cv2.IMREAD_ANYDEPTH)
cv2.imshow("uint_saved any|any",img5)

for row in range(0,20):
    for column in range(0,20):
        if img[row][column] != .0:
            print("row:{}, column:{}, x:{}, y:{}, value_img1:{}, value_img2:{}, value_img3:{}, value_img4:{}, value_img5:{}"
                  .format(row,column,column,row,img1[row][column],img2[row][column],img3[row][column],img4[row][column],img5[row][column]))

cv2.waitKey()
cv2.destroyAllWindows()

一些实验过程中的详细结果:

使用png图像格式储存数据的时候,最大深度应该是16位。

当生成的随机数据值域处于0-255之间的时候。
显示:float显示正常,uint16_t显示正常,较黑,因为255比65535小很多吧。
数值:float数值正常,uint16_t数值正常。

当生成的随机数据值域处于0-65535之间的时候。
显示:float按照0-255显示,大于255显示为白色,uint16_t显示正常。
数值:float数值大于255的全为255,不正常,uint16_t数值正常。

当生成的随机数据值域处于65536-256*65535之间的时候。
显示:float按照0-255显示,大于255显示为白色,uint16_t被截断,相当于减去65535,显示正常。
数值:float数值大于255的全为255,不正常,uint16_t数值显示为截断之后的正常数值,其实是减去65535的数值。

使用tiff图像格式储存数据的时候,存储深度不限于16位,32位甚至64位。

当生成的随机数据值域处于0-255之间的时候。
显示:float显示正常,uint16_t显示正常,较黑,因为255比65535小很多吧。
数值:float数值正常,uint16_t数值正常。

当生成的随机数据值域处于0-65535之间的时候。
显示:float按照0-255显示,大于255显示为白色,uint16_t显示正常。
数值:float数值正常,uint16_t数值正常。

当生成的随机数据值域处于65536-256*65535之间的时候。uint16_t被截断。
显示:float按照0-255显示,大于255显示为白色,uint16_t因为被截断后相当于0-65535,因此在这个范围内,算是显示正常。
数值:float数值正常,uint16_t数值显示为截断之后的正常数值,其实是减去65535的数值。

使用tiff格式

不溢出的前提下,
float在保存前和保存后显示的时候,凡是大于255,都会显示为白色,uint16_t会显示为0-255之间,应该是0-65535之间的映射。
保存后再读取,数值都是正确的。

使用png格式

不溢出的前提下,
float在保存前和保存后显示的时候,凡是大于255,都会显示为白色,uint16_t会显示为0-255之间,应该是0-65535之间的映射。
保存后再读取,float保存后会将大于255的数值均置为255,数值是错误的,uint16_t数值正常。

关于数值恢复

经过保存为文件再读取数据,用png会导致float数据被约束到0-255,保存再读取真实数值丢失,用tiff则不会造成任何数据损失。

关于图像显示

对于float数据,只要大于255都会显示位白色,对于uint16_t,imshow函数则会将16位数据从0-65535映射到0-255.


使用了dumyy:realsense深度图像保存方法的部分代码。

你可能感兴趣的:(python,opencv,python,opencv,计算机视觉,可视化)