• 【OpenCV】 - 显示图像API之imshow()对不同位深度(数据类型)的图像的处理方法


    参考文章

    本篇是对下面这篇「田土豆」写的文章的补充和修正。

    有关函数cv2.imshow()处理不同图像深度时的数据转化问题_田土豆的博客

    另外也参考了官方API文档

    OpenCV: High-level GUI-imshow() 

    一、imshow(windows_name, img_array) 

    显示图像的函数,第二个参数img代表了图像多维数组。

    当图像多维数组是不同的数据类型,或者说图像是不同的位深度时,最后imshow处理的机制不同。

    二、支持显示的图像有哪些位深度?

    • CV_8U,在0-255之间
    • CV_16U,在0-65535之间
    • CV_32F,单精度浮点
    • CV_64F,双精度浮点

    经测试,在OpenCV的4.5.5版本(不代表是最早不支持的版本)中,不支持CV_32S和CV_16F两种位深度图像。

    三、对各个位深度的处理方式?

    官方文档的描述如下

    • If the image is 8-bit unsigned, it is displayed as is.
    • 如果图像是无符号八位整型,是多少数字就最后显示多少;换句话说,imshow()显示图像的精度范围是在0-255之间,正好对应无符号整型。
    • If the image is 16-bit unsigned, the pixels are divided by 256. That is, the value range [0,255*256] is mapped to [0,255].
    • 如果是16位无符号整型,那么由于范围是0-65535,需要将每个像素点除以255得到范围是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].
    • 如果是32位或64位浮点型,那么因为这个位深度的图像——各像素点的正常取值范围在0-1,像素点需要先乘以255再显示。
    • 32-bit integer images are not processed anymore due to ambiguouty of required transform. Convert to 8-bit unsigned matrix using a custom preprocessing specific to image's context.
    • 32位(有)符号整型不再加工(显示)由于必要转换的模糊性;因此如果实在要显示32S的图像,先用自定义预处理程序转换至无符号8位整型,才能顺利显示。

    田大哥的文章中额外提到一个观点——如果浮点型多维数组有元素取值是负数,那么先取绝对值后再乘以255,最后按255截断。

    我在测试他的最后一块代码时,发现并非如此。

    我的OpenCV版本是4.5.5,他写文章时用的是4.1.0,兴许是版本更替所致吧!

    在4.5.5版本中,不管浮点型多维数组有无负数,都是直接乘以255,得到的数然后进行0-255的饱和运算,也即如果小于0就等于0,如果大于255就等于255。

    四、代码测试

    在Python中运行下列代码

    1. import numpy as np
    2. import cv2
    3. #新建numpy数组,注意np.zero()创建的数据类型为float64
    4. img=np.zeros((500,500,3))
    5. #openCV显示图像为BGR格式,通过下列方式,我们绘制三条粗红线
    6. print(cv2.__version__)
    7. img[150:170,150:350]=[0,0,-8000]
    8. img[250:270,150:350]=[0,0,8000]
    9. img[350:370,150:350]=[0,0,0.34]
    10. img[450:470,150:350]=[0,0,65555]
    11. cv2.imshow('img', img)
    12. cv2.waitKey()
    13. cv2.destroyAllWindows()

    显示的图像如下。因为第一条对应的像素点原值是负数,所以最后饱和运算取值为0,显示成黑色;因为saturate_8U(0.34*255)=86.7,小于saturate_8U(8000*255)=255,所以第三条显示的颜色明显更浅!而由于第四条和第二条对应的像素点都是正整数,所以最后颜色深度相同。

     

  • 相关阅读:
    2022年外资EDI证办理流程及要求
    Springboot+美妆网站的设计与实现 毕业设计-附源码211539
    花费半年整理拼多多、饿了么、蚂蚁金服等大厂Java面试题大集合
    Android 应用启动过程优化
    NorFlash的存储原理
    计算机基础(二):汇编语言与内存结构
    vite+vue3+ts项目搭建之集成Layout组件搭建、全局自动注册基础组件、缓存页面
    煤矿安全大模型:微调internlm2模型实现针对煤矿事故和煤矿安全知识的智能问答
    智慧公厕:不放过任何“卫生死角”,为公共厕所装上“净化系统”。
    Linux常用命令
  • 原文地址:https://blog.csdn.net/PSpiritV/article/details/126121940