matplotlib与opencv图像读取与显示的问题

个人博客:Sekyoro的博客小屋
个人网站:Proanimer的个人网站

最近在用opencv和matplotlib展示图片,但是遇到了一些问题,这里展开说说
首先需要明确的是,opencv和matplotlib读取图片都是通道在最后,而前者默认可见光图像是BGR,后者是RGB.此外还有PIL以及imageio等读取图像的工具,这里不一一赘述.

Opencv

对于opencv,使用cv2.imshow,cv2.imread以及cv2.imwrite来读写以及显示.

imshow

显示图像的缩放取决于图像深度:
对 8 位无符号图像,按原样显示;
对 16 位无符号或 32 位整数图像,将像素值范围 [0,255*255] 映射到 [0,255] 显示;
对 32 位浮点图像,将像素值范围 [0,1] 映射到 [0,255] 显示;

当cv2.imshow()处理图像深度为CV_8U(默认范围为[0,255])时,按原数据显示;

当处理图像深度为CV_16U(默认范围为[0,65535])时,除以256,映射到[0,255];

当图像深度为CV_32F和CV_64F时(默认范围为[0,1]),乘以255映射到[0,255],超过255直接饱和;

当输入负数时,当作0来处理

import numpy as np
import cv2img = np.zeros((500, 500, 1))
print(img.dtype)
img[150:170, 150:350] = 10
img[250:270, 150:350] = -1
img[350:370, 150:350] = -10
print(img[350:170, 150:350])
cv2.imshow('img', img)
cv2.waitKey()

由于numpy默认类型float64,浮点数会乘以255,所以只有最上面有一条白线.负值直接黑色

image-20231116201141606
import numpy as np
import cv2
# 新建numpy数组,注意np.zero()创建的数据类型为float64
img = np.zeros((500, 500, 1))
print(img.dtype)
img[150:170, 150:350] = 10
img[250:270, 150:350] = 255
img[350:370, 150:350] = 1
print(img[350:170, 150:350])
cv2.imshow('img', img)
cv2.waitKey()
image-20231116201615437

而如果是大于1的浮点数,也是直接饱和.

如果是uint8,如果超出255,则会被numpy截取,也就是取模

img = np.zeros((500, 500, 1),dtype=np.uint8)
print(img.dtype)
img[150:170, 150:350] = 10
img[250:270, 150:350] = 20
img[350:370, 150:350] = 30
cv2.imshow('img', img)
print(img[350:370, 150:350])
cv2.waitKey()
image-20231116201823217
img = np.zeros((500, 500, 1),dtype=np.uint8)
print(img.dtype)
img[150:170, 150:350] = 10
img[250:270, 150:350] =  512
img[350:370, 150:350] = 255
cv2.imshow('img', img)
print(img[250:270, 150:350])
cv2.waitKey()

打印img[250:270, 150:350]的值发现是0

image-20231116202123379
img = np.zeros((500, 500, 1))
print(img.dtype)
img[150:170, 150:350] = 10
img[250:270, 150:350] =  512
img[350:370, 150:350] = 255
cv2.imshow('img', img)
print(img[250:270, 150:350])
cv2.waitKey()
image-20231116202222468

所以这涉及两个问题,一个是本身numpy的截取另一个是opencv的截取机制.

img = np.zeros((500, 500, 1), dtype=np.uint16)
print(img.dtype)
img[150:170, 150:350] = 2
img[250:270, 150:350] = 255*255
img[350:370, 150:350] = 255*100
cv2.imshow('img', img)
cv2.waitKey(0)
print(img[250:270, 150:350])
cv2.imwrite("test.png", img)
image-20231116202916344

如果是16位无符号整数,会除以255.

最后注意,如果是int32可能会报错

imwrite

机制与imshow类似,不过会根据保存文件的后缀进行编码参数.

cv2.imwrite() 能保存 BGR 3通道图像,或 8 位单通道图像、或 PNG/JPEG/TIFF 16位无符号单通道图像

注意:如果保存float32的图像值超过了1,此时会与imshow机制不同,表现为值被归到0-255

a = np.ones([255,255,1],dtype=np.float32)
a[0:255,0:255] = 10
print(a)
cv2.imshow("img",a)
cv2.waitKey()
cv2.imwrite("test.png",a)

在这里插入图片描述

image-20231116222107874

上面有两张图,分别是imwrite的图片与imshow的图片,由于是浮点数,imshow展示时乘了255导致饱和白色.所以会说imwrite对浮点数不友好,不符合imshow的道理,

imread

注意如果有通道则通道在最后,可以设置

IMREAD_UNCHANGED = -1, //如果设置,则返回的数据带有alpha通道(R,G,B,A 四个通道),否则没有alpha通道
IMREAD_GRAYSCALE = 0, //如果设置,则将图像转换为单通道灰度图像
IMREAD_COLOR = 1, //如果设置,则将图像转换成3通道BGR彩色图像
IMREAD_ANYDEPTH = 2, //如果设置,则在输入具有相应深度时返回16位/32位图像,否则将其转换为8位
IMREAD_ANYCOLOR = 4, //如果设置,则图像可能以任何颜色格式读取
IMREAD_LOAD_GDAL = 8, //如果设置,使用gdal驱动程序加载图像
IMREAD_REDUCED_GRAYSCALE_2 = 16, //如果设置,总是将图像转换为单通道灰度图像且图像大小减少1/2
IMREAD_REDUCED_COLOR_2 = 17, //如果设置,总是将图像转换为3通道BGR彩色图像且图像大小减少1/2
IMREAD_REDUCED_GRAYSCALE_4 = 32, //如果设置,总是将图像转换为单通道灰度图像且图像大小减少1/4
IMREAD_REDUCED_COLOR_4 = 33, //如果设置,总是将图像转换为3通道BGR彩色图像且图像大小减少1/4
IMREAD_REDUCED_GRAYSCALE_8 = 64, //如果设置,总是将图像转换为单通道灰度图像且图像大小减少1/8
IMREAD_REDUCED_COLOR_8 = 65, //如果设置,总是将图像转换为3通道BGR彩色图像且图像大小减少1/8
IMREAD_IGNORE_ORIENTATION = 128 //如果设置,不会根据EXIF的方向标志旋转图像

Matplotlib

imshow

主要讲讲matplotlib的imshow

matplotlib在imshow时,如果接收到的是二维矩阵,会自动归一化,映射到彩色。如果输入的矩阵里面值都是一样的,归一化会把他们全部变为255,也就是呈现黑色。

用于在使用 cmap 映射到颜色之前将标量数据缩放到 [0, 1] 范围的归一化方法。默认情况下,使用线性缩放,将最低值映射到 0,将最高值映射到 1。

imshow的输入

图像数据。支持的数组形状有:(M,N):具有标量数据的图像。使用归一化和颜色图将值映射到颜色。请参阅参数norm、cmap、vmin、vmax。

(M, N, 3):具有 RGB 值(0-1 float 或 0-255 int)的图像。

(M, N, 4):具有 RGBA 值(0-1 float 或 0-255 int)的图像,即包括透明度。前两个维度(M、N)定义图像的行和列。超出范围的 RGB(A) 值将被剪裁。

所以如果使用单通道的数据,会默认norm,而这种norm是根据输入值的min-max进行norm,并不是norm到0-255

image-20231116210309620

img = torch.ones(152,152,1,dtype=torch.uint8)*220
img = img.numpy()
plt.imshow(img,cmap="gray")
plt.show()

解决办法是设置vmin=0,vmax=255,当然使用三通道也可以

image-20231116210559535

相关问题

  1. matplotlib 可视化图像明明255,结果出来全为黑色的问题_plt.imshow 不加vmin和vmax参数是全黑的_佳hong的博客-CSDN博客
  2. 有关函数cv2.imshow()处理不同图像深度时的数据转化问题_cv2.cv_8u图像深度-CSDN博客这篇文章有点问题,目前opencv将负值作为0处理
  3. opencv中imwrite对float的处理 - siren27 - 博客园 (cnblogs.com)
  4. 【精选】使用 tiff/png 文件类型对 uint16_t/float 数据类型存取的无聊实验_float存储方式和uint16-CSDN博客

如有疑问,欢迎各位交流!

服务器配置
宝塔:宝塔服务器面板,一键全能部署及管理
云服务器:阿里云服务器
Vultr服务器
GPU服务器:Vast.ai

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/209487.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

(学习笔记)Xposed模块编写(一)

前提:需要已经安装Xposed Installer 1. 新建一个AS项目 并把MainActvity和activity_main.xml这两个文件删掉,然后在AndriodManifest.xml中去掉这个Activity的声明 2. 在settings.gralde文件中加上阿里云的仓库地址,否则Xposed依赖无法下载 m…

9款热门API接口分享,值得收藏!

电商API接口 干货分享 开始 “ API是什么? API的主要目的是提供应用程序与开发人员以访问一组例程的能力,而又无需访问源码,或理解内部工作机制的细节。提供API所定义的功能的软件称作此API的实现。API是一种接口,故而是一种抽象…

Banana Pi最新的路由器板BPI-R4上市销售,基于MediaTek MT7988A

Banana Pi 发布了一款新的路由器板 Banana Pi BPI-R4,基于配备四核 Arm CPU 的 MediaTek MT7988A SoC。该板不仅仅是Raspberry Pi 的另一个替代品,而且是用于家庭网络和自动化的设备。 Banana Pi BPI-R4 的外形尺寸比单板计算机更像网络设备。对于那些希…

Python函数的基本使用(一)

Python函数的基本使用(一) 一、函数概述二、函数的定义2.1 函数的语法2.2 语法说明2.3 函数定义的方式2.4 总结 三、函数的调用3.1 函数调用语法3.2 语法说明3.3 函数调用 四、函数的参数4.1 参数的分类4.2 必需参数4.3 默认值参数4.4 关键字参数4.5 不定…

风变科技千万营收的AIGC项目,在Fanbook成功落地,专访风变科技CMO江育麟

在AIGC时代,创作生产力被下放到了每一位普通人身上,然后用户与AIGC应用之间还存在一定的认知与技术沟壑。 最近,【AIGC开放社区】注意到一款AIGC课程项目受到了相当的关注,让许多0基础的学员轻松地学会了使用AIGC技术的基本方法。…

风控交易系统跟单系统资管软件都有哪些功能特点?

资管分仓软件的主要功能就是母账户可以添加子账号,并且设置出入金,手续费、保证金、风控等功能,同时监控端更可以直观的看子账户的交易情况直接折线图展示更加直观,在监控端的最高权限可以直接一键平仓子账户(如果子账…

基于jsp的搜索引擎

摘 要 随着互联网的不断发展和日益普及,网上的信息量在迅速地增长,在2004年4月,全球Web页面的数目已经超过40亿,中国的网页数估计也超过了3亿。 目前人们从网上获得信息的主要工具是浏览器,搜索引擎在网络中占有举足轻…

23种设计模式之C++实践(二)

23种设计模式之C++实践 3. 设计模式(二)组合型模式7. 适配器模式——不兼容结构的协调7.2:类适配器模式7.3:双向适配器模式适配器模式总结8.桥接模式——处理多维度变化桥接模式总结9. 组合模式——树形结构的处理9.2 透明组合模式9.3 安全组合模式组合模式总结10. 装饰模式…

【海思SS528 | VDEC】MPP媒体处理软件V5.0 | 视频解码模块——学习笔记

😁博客主页😁:🚀https://blog.csdn.net/wkd_007🚀 🤑博客内容🤑:🍭嵌入式开发、Linux、C语言、C、数据结构、音视频🍭 🤣本文内容🤣&a…

HR看好的字符函数和字符串处理函数!!!

本篇会加入个人的所谓‘鱼式疯言’❤️❤️❤️鱼式疯言:❤️❤️❤️此疯言非彼疯言,而是理解过并总结出来通俗易懂的大白话,我会尽可能的在每个概念后插入鱼式疯言,帮助大家理解的,可能说的不是那么严谨.但小编初心是能让更多人能接受我们这个概念 前言 在本篇…

智能监控平台/视频共享融合系统EasyCVR接入RTSP协议视频流无法播放原因是什么?

视频集中存储/云存储/视频监控管理平台EasyCVR能在复杂的网络环境中,将分散的各类视频资源进行统一汇聚、整合、集中管理,实现视频资源的鉴权管理、按需调阅、全网分发、智能分析等。AI智能/大数据视频分析EasyCVR平台已经广泛应用在工地、工厂、园区、楼…

深入理解Go语言GC机制

1、Go 1.3之前的标记-清除(mark and sweep)算法 Go 1.3之前的时候主要用的是普通的标记-清除算法,此算法主要由两个主要的步骤: 标记(Mark phase)清除(Sweep phase) 1&#xff09…

Spring Boot整合RabbitMQ

一、简介 在Spring项目中,可以使用Spring-Rabbit去操作RabbitMQ 尤其是在spring boot项目中只需要引入对应的amqp启动器依赖即可,方便的使用RabbitTemplate发送消息,使用注解接收消息。 一般在开发过程中: 生产者工程&#xf…

文心一言 VS 讯飞星火 VS chatgpt (148)-- 算法导论12.2 3题

三、用go语言,写出过程 TREE-PREDECESSOR 的伪代码。 文心一言: 以下是使用Go语言编写的TREE-PREDECESSOR函数的伪代码: func TREE-PREDECESSOR(node) { if node.parent ! nil { return node.parent } // 如果节点是根节点&#xff0c…

TDA4VM EVM开发板调试笔记

文章目录 1. 前言2. 官网资料导读3. 安装 Linux SDK4. 制作SD 启动卡5. 验证启动1. 前言 TDA4作为一般经典的车规级SOC芯片,基于它的低阶智驾方案目前成为各家智驾方案公司的量产首选,这也使得基于TDA4的开发需求陡增,开发和使用TDA4既要熟悉Linux驱应用开发,还要熟悉传统…

「计算机网络」Cisco Packet Tracker计算机网络仿真器的使用

介绍 Cisco Packet Tracker:网络仿真工具,用于模拟网络配置。 (一) 配置交换机(Switch)(通过 带外管理) 带外:Out-of-Band, OOB写在前面:如何打开Console页…

数据结构与算法-动态查找表

查找 🎈3动态查找表🔭3.1二叉排序树🏆3.1.1二叉排序树的类定义🏆3.1.2二叉排序树的插入和生成🏆3.1.3二叉树的查找🏆3.1.4二叉排序树的删除 🔭3.2平衡二叉树🏆3.2.1平衡二叉树的调整…

YOLOv8 区域计数 | 入侵检测 | 人员闯入

大家好,昨天的 YOLOv8 新增加了一个功能,区域计数,用这个功能我们能实现很多的任务, 比如入侵检测,流量统计,人员闯入等,使用方式也非常的方便,但是一定要使用最新版的 YOLOv8 代码(2023/12/03更新的代码)。 低版本是不具备这个功能的,上面是演示效果。 使用非常的方…

分享74个节日PPT,总有一款适合您

分享74个节日PPT,总有一款适合您 74个节日PPT下载链接:https://pan.baidu.com/s/18YHKkyJsplx-Gjj7ofpFrg?pwd6666 提取码:6666 Python采集代码下载链接:采集代码.zip - 蓝奏云 学习知识费力气,收集整理更不易…

如何赚钱?聊聊程序员的副业与生意

说到副业和赚钱一直都是大家非常关心的话题,特别是在今年大环境不好,各大公司频繁裁员的行情之下。单一的收入结构会导致家庭抗风险能力特别差。最近特别火的【中产陷阱话题】说的就是这个道理。 所以,获得除目前工资之外的其他收入&#xf…