PyQt5-QImage、QPixmap、Opencv与QLabel、Matplotlib的互动

article/2025/10/19 5:33:48

文章目录

  • 前言
  • 一、转换
    • 1.1 Opencv_to_QPixmap
    • 1.2 QImage_to_QPixmap
    • 1.3 QPixmap_to_Opencv
    • 1.4 QImage_to_Opencv
    • 1.5 Opencv_to_QImage
  • 二、实战案例
    • 2.1 案例1-图像旋转
  • 总结


前言

早期进行图像旋转用的笨方法是:

  1. cv2.imread()读取图像
  2. numpy旋转图像
  3. 将旋转后的图像保存cv2.imwrite()并且从新读取图像

由于图像基本操作我是个小白,什么都没有接触过。因此,前期的想法就是这样,这种方法简单,明了,但是缺点你懂的

后来,偶尔看到了这篇文章:【PyQt5】显示多张图片并支持滚动,其中的一行代码:label.setScaledContents(True) 自适应窗口控件大小,于是就在网上搜集各种资料,并且自己测试,最终总结为该篇博客。

这里基本汇聚了简单的图像处理+图像界面设计用到的基本格式转换,希望可以帮助到你!


一、转换

  • 测试图像
    在这里插入图片描述
    在这里插入图片描述
  • path、photo
path = r'F:\python\gradu_design\gra_des\compr\bamarket115.jpg'
# r'F:\python\gradu_design\gra_des\imges\logo1_1.jpg'# 调用
photo = QImage(path)
# print('photo type:', type(photo), photo.width(), photo.height())

下面方法涉及到的参数photopath来源于此

  • 显示问题

下面方法会看到两张在一起对比的图片:这是单独使用matplotlib显示查看转换的效果:
matplotlib是显示RGB图片的,由于测试图片是红色的,因此若结果显示蓝色,则证明图片是BGR格式的,反之若和原图一样则是RGB个格式

# image 类型必须为<class 'numpy.ndarray'>,plt才可以显示
def plt_show(self,image):plt.subplot(121)plt.title('格式检查-BGR')plt.imshow(image)plt.subplot(122)plt.title('格式检查-RGB')plt.imshow(image[:,:,::-1])  # 正常显示plt.show()

1.1 Opencv_to_QPixmap

完整过程:Opencv -> QImage -> QPixmap

  • 代码
# 调用  cv2 读取图像 -> QPixmap 让QLabel显示
self.cvread_labelshow(pic_show_label=self.label,path=path)# cv2 读取图像 -> QPixmap 让QLabel显示
def Opencv_to_QPixmap(self,pic_show_label,path):print('-----cvread_labelshow-----')# 图片路径img_path = path# 通过cv读取图片  BGR格式img = cv2.imread(img_path)print('cv2 : ',type(img))# cv2 :  <class 'numpy.ndarray'>plt.subplot(121)plt.title('BGR-格式')plt.imshow(img)  # img本来是BGR格式,通过img[:,:,::-1]转为RGB格式# 通道转化  BGR->RGBRGBImg = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)plt.subplot(122)plt.title('RGB-格式')plt.imshow(RGBImg)  # matplotlib只能显示RGB图像plt.show() # 将图片转化成Qt可读格式   QImageqimage = QImage(RGBImg, RGBImg.shape[1], RGBImg.shape[0], QImage.Format_RGB888)print('qimage type:', type(qimage))piximage = QPixmap(qimage)print('piximage type:', type(piximage))# 显示图片pic_show_label.setPixmap(piximage)pic_show_label.setScaledContents(True)print('pic_show_label mess:',pic_show_label.width(), pic_show_label.height())print('piximage mess:',piximage.width(),piximage.height())
  • 测试结果
  1. 在这里插入图片描述

  2. 在这里插入图片描述

  3. 在这里插入图片描述

  • 结论
  • matplotlib只能显示numpy.adarry类型,且显示RGB格式
  • 自适应并没有改变图像的实际大小

1.2 QImage_to_QPixmap

  • 代码
self.QImage_to_QPixmap(photo)# 让读取的图像自适应QLabel  QImage -> QPixmap
def QImage_to_QPixmap(self,photo):print('-----Adjust_Img_Size-----')width = self.label.width()height = self.label.height()print('photo size:',type(photo),photo.width(),photo.height())size = QSize(width, height)# Qt.IgnoreAspectRatio、Qt.KeepAspectRatio、# https://www.cnblogs.com/qixianyu/p/6891054.htmlpixphoto = QPixmap.fromImage(photo.scaled(size, Qt.KeepAspectRatio,Qt.SmoothTransformation)) # QImage -> QPixmap  IgnoreAspectRatio:忽略纵横比self.label.setPixmap(pixphoto)self.label.setScaledContents(True)  # 图像自适应窗口大小print('pixphoto type:', type(pixphoto), width,height)
  • 测试结果
  1. 在这里插入图片描述

将代码

  • pixphoto = QPixmap.fromImage(photo.scaled(size, Qt.KeepAspectRatio,Qt.SmoothTransformation))

改为

  • pixphoto = QPixmap(photo)

QPixmap形状改变

  1. 在这里插入图片描述

1.3 QPixmap_to_Opencv

  • 代码
pixphoto = QPixmap(path)
# 调用 Pixmap_to_Opencv
pixarr = self.Pixmap_to_Opencv(pixphoto)
plt.imshow(pixarr)
plt.show()
print('pixarr : ', type(pixarr))  # 看测试结果1# QPixmap 转为 CV2
def Pixmap_to_Opencv(self,qtpixmap):print('-----QPixmap_to_Opencv-----')print('qtpixmap type:',type(qtpixmap))qimg = qtpixmap.toImage()  # QPixmap-->QImageprint('qimg type:', type(qimg))temp_shape = (qimg.height(), qimg.bytesPerLine() * 8 // qimg.depth())temp_shape += (4,)ptr = qimg.bits()ptr.setsize(qimg.byteCount())result = np.array(ptr, dtype=np.uint8).reshape(temp_shape)result = result[..., :3]# cv2.imwrite('./result.jpg',result) # 保存的话会显示RGB格式return result
  • 测试结果
  1. 在这里插入图片描述

  2. 在这里插入图片描述

  3. 仔细审阅代码你会发现有这一行代码:
    cv2.imwrite('./result.jpg',result)
    由测试结果1可知调用Pixmap_to_Opencv方法后图像是BGR格式,那保存该图像也会是BGR格式吗?
    答:不是 (这行代码就是用来测试效果的)
    保存的图像居然是彩色的(若是BGR格式,图像应该为蓝色),因此我们推断使用opencv进行图像保存到时候应该存在格式准换(有兴趣的可以去查看源码,在此不做赘述)

    在这里插入图片描述

  4. 修改调用代码
    pixphoto = QPixmap(path) ① pixarr = self.Pixmap_to_Opencv(pixphoto)② print('pixarr : ', type(pixarr)) ③
    改为
    pixphoto = QPixmap(path)① pixarr = self.Pixmap_to_Opencv(pixphoto)② print('pixarr : ', type(pixarr))③ self.plt_show(pixarr)④

    查看matlibplot显示的效果:

    在这里插入图片描述

1.4 QImage_to_Opencv

  • 代码
# 调用 QImage_to_Opencv
Imagearr = self.QImage_to_Opencv(photo)
print('Imagearr : ', type(Imagearr))
self.plt_show(Imagearr)# QImage 转为 Opencv
def QImage_to_Opencv(self,qimg):print('-----QImage_to_Opencv-----')tmp = qimg# 使用numpy创建空的图象cv_image = np.zeros((tmp.height(), tmp.width(), 3), dtype=np.uint8)print('begin cv_image type:',type(cv_image))for row in range(0, tmp.height()):for col in range(0, tmp.width()):r = qRed(tmp.pixel(col, row))g = qGreen(tmp.pixel(col, row))b = qBlue(tmp.pixel(col, row))# cv_image[row, col, 0] = r# cv_image[row, col, 1] = g# cv_image[row, col, 2] = bcv_image[row, col, 0] = bcv_image[row, col, 1] = gcv_image[row, col, 2] = rprint('end cv_image type:', type(cv_image))cv2.imwrite('./QImage_to_Opencv.jpg',cv_image)return cv_image
  • 测试结果
  1. 在这里插入图片描述
  2. 在这里插入图片描述

1.5 Opencv_to_QImage

需求:在进行图像旋转90°的情况下发生了失真情况,如下:

旋转90° 图像失真

分析:
图像旋转的整个过程是 QPixmap -> Qpencv -> QPixmap,我分别在QPixmap -> Qpencv ①和Qpencv -> QPixmap②两个过程中进行测试,发现过程②是问题所在原因,因此我将整个过程改为:
QPixmap -> Qpencv -> QImage -> QPixmap

  • 代码
# 调用 QPixmap_to_Opencv
pixphoto = QPixmap(path)
pixarr = self.QPixmap_to_Opencv(pixphoto)print('pixarr : ', type(pixarr))
img_rotate = np.rot90(pixarr, 1)print('img_rotate : ', type(img_rotate))
plt.imshow(img_rotate[:, :, ::-1])
plt.show()# 调用 Opencv_to_QImage
QtImg = self.Opencv_to_QImage(img_rotate)
self.QImage_to_QPixmap(QtImg,self.label_2) # 这是QImage_to_QPixmap 的修改版def Opencv_to_QImage(self,img):# 将图片转成BGRA模式;img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2BGRA)QtImg = QImage(img_rgb.data, img_rgb.shape[1], img_rgb.shape[0],QImage.Format_RGB32)# # 显示图片到label中;# self.labImage.resize(QSize(img_rgb.shape[1],img_rgb.shape[0]))# self.labImage.setPixmap(QPixmap.fromImage(QtImg))return QtImg
  • 测试结果
    在这里插入图片描述

完整源码见 2.1 案例1-图像旋转


二、实战案例

2.1 案例1-图像旋转

  • test_resize.ui文件
    在这里插入图片描述
  • 图像旋转源码
import sys
import cv2
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *import numpy as np
import matplotlib.pyplot as plt
from PyQt5.uic import loadUiclass QLabel_resize(QMainWindow):def __init__(self):super().__init__()self.setupUi()self.resize_QLabel()def setupUi(self):loadUi('./test_resize.ui', self)plt.rcParams['font.sans-serif'] = ['KaiTi']def resize_QLabel(self):print('-----resize_QLabel-----')path = r'F:\python\gradu_design\gra_des\compr\jasper_johns.jpg'photo = QImage(path)print('photo type:', type(photo), photo.width(), photo.height())self.all_iamge_type_conversion(path,photo)def all_iamge_type_conversion(self,path,photo):# QImage_to_QPixmap 先读取图像显示在QLabelself.QImage_to_QPixmap(photo,self.label)  pixphoto = QPixmap(path)pixarr = self.QPixmap_to_Opencv(pixphoto)print('pixarr : ', type(pixarr))img_rotate = np.rot90(pixarr, 1)print('img_rotate : ', type(img_rotate))plt.imshow(img_rotate[:, :, ::-1])plt.show()# 调用 Opencv_to_QImageQtImg = self.Opencv_to_QImage(img_rotate)self.QImage_to_QPixmap(QtImg,self.label_2)# 让读取的图像自适应QLabel  QImage -> QPixmapdef QImage_to_QPixmap(self,photo,label):print('-----Adjust_Img_Size-----')label.setStyleSheet("border:1px solid gray") # 使QLabel带有边框width = self.label.width()height = self.label.height()print('photo size:',type(photo),photo.width(),photo.height())size = QSize(width, height)# Qt.IgnoreAspectRatio、Qt.KeepAspectRatio、# https://www.cnblogs.com/qixianyu/p/6891054.htmlpixphoto = QPixmap.fromImage(photo.scaled(size, Qt.KeepAspectRatio,Qt.SmoothTransformation)) # QImage -> QPixmap  IgnoreAspectRatio:忽略纵横比# pixphoto = QPixmap(photo)label.setPixmap(pixphoto)# QPixmap 转为 Opencv   def QPixmap_to_Opencv(self,qtpixmap):print('-----QPixmap_to_Opencv-----')print('qtpixmap type:',type(qtpixmap))qimg = qtpixmap.toImage()  # QPixmap-->QImagetemp_shape = (qimg.height(), qimg.bytesPerLine() * 8 // qimg.depth())temp_shape += (4,)ptr = qimg.bits()ptr.setsize(qimg.byteCount())result = np.array(ptr, dtype=np.uint8).reshape(temp_shape)result = result[..., :3]return resultdef Opencv_to_QImage(self,img):# 将图片转成BGRA模式;img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2BGRA)QtImg = QImage(img_rgb.data, img_rgb.shape[1], img_rgb.shape[0],QImage.Format_RGB32)return QtImgdef main():app = QApplication(sys.argv)window = QLabel_resize()window.show()app.exec_()if __name__ == "__main__":main()
  • 测试效果
    在这里插入图片描述

总结

  • 参考资源
  1. matplotlib面向对象绘图小白终结版
  2. 将Python Opencv图片对象转成PyQt4中的QImage对象 ⭐
  3. python pyqt5图片(QPixmap)和opencv图片数据结构相互转换 ⭐
  4. PyQt5番外篇(1):PyQt5与Opencv的小小融合

http://chatgpt.dhexx.cn/article/hm3XWMvJ.shtml

相关文章

QImage 图片分割、保存

QImage 图片分割、保存 简介 之前一直只用Qt做图片显示&#xff0c;这次突发奇想想用Qt做做图像相关的&#xff0c;就尝试了一下图片切割&#xff0c;保存。 QImage介绍 QImage类为Qt提供的一个支持图像算法处理的类库&#xff0c;可以精确到像素及单位。在我理解不是提供了…

QImage类

QImage类提供了一个硬件无关的图像表示方法&#xff0c;该图像可以逐像素被访问和用于画图设备。 Qt提供了QImage、QPixmap、QBitmap和QPicture四种图像操作类。QImage类主要用于I/O和直接逐像素访问、操作&#xff1b;QPixmap主要用于在屏幕中显示图像&#xff1b;QBitmap是一…

Qt使用QImage保存成JPG(PNG)图像到本地

一、QImage类简介 QImage提供了一个与硬件无关的图像表示方法&#xff0c;允许直接访问像素数据&#xff0c;可用作绘图设备。QImage类支持QImage::Format、enum描述的多种图像格式。包括8-bit, 32-bit 和alpha混合图像QImage 提供很多可以用于获取图像信息和进行图像变换的函…

QImage

一、描述 QImage 类提供了一种独立于硬件的图像表示&#xff0c;允许直接访问像素数据&#xff0c;并且可以用作绘图设备。 QImage 是为 I/O 和直接像素访问和操作而设计和优化的&#xff0c; 因为 QImage 是 QPaintDevice 的子类&#xff0c;所以 QPainter 可用于直接在图像…

图像处理 QImage

在Qt中有四种处理图像的方法&#xff1a; QImage &#xff1a;使用I/O &#xff0c;可以对像素进行处理QPixmap&#xff1a;主要用在屏幕的显示QBitmap&#xff1a; QPixmap的子类&#xff0c;处理颜色深度&#xff0c;只能显示黑白两种颜色&#xff0c;用于遮罩QPicture&…

QImage的用法

QImage提供了几种加载图像文件的方法&#xff1a; &#xff08;1&#xff09;构造QImage对象 Image myImage1 QImage(filename); 根据文件名打开图像 支持的图片格式是&#xff1a; &#xff08;2&#xff09;QImage(uchar *data, int width, int height, Format format …) 用…

QImage使用说明

详细描述 QImage类提供独立于硬件的图像表示&#xff0c;允许直接访问像素数据&#xff0c;并可用作绘制设备。 Qt提供了四个用于处理图像数据的类&#xff1a;QImage、QPixmap、QBitmap和QPicture。QImage针对I/O、直接像素访问和操作进行了设计和优化&#xff0c;而QPixmap…

QImage类详解(QImage类型转换、QImage类函数及QImage像素操作)

QImage类&#xff08;QImage类型转换、QImage类函数及QImage像素操作&#xff09; 打开Qt帮助文档&#xff0c;会看到有关于QImage的描述如下&#xff1a;The QImage class provides a hardware-independent image representation that allows direct access to the pixel dat…

J1939 协议

J1939 协议简介 J1939协议是基于CAN 2.0B所发展的出来的&#xff0c;基于CAN 的物理层。主要用于commercial vehicle的通信。J1939的主要目的是制定统一的上层application诊断的信息。 J1939的最大特点是定义了PGN&#xff08;Parameter Group Number). 大多数的PGN是8个字节…

SAE J1939学习笔记(三)

J1939故障代码种类 J1939 由几个不同的诊断信息&#xff1a; –诊断信息 1 - DM1 – 现行故障代码 –诊断信息 2 - DM2 – 非现行故障代码 –诊断信息 3 - DM3 – 清除非现行故障代码 通常地&#xff0c;用户会用 DM1 信息来读取现行故障码。 DM1 信息是 PGN 65226 or FECA h…

新功能发布—TSMaster如何实现J1939多帧报文收发

前言 众所周知&#xff0c;J1939协议是由美国汽车工程师协会&#xff08;SAE&#xff09;定义的一组标准。J1939标准用于卡车、公共汽车和移动液压等重型车辆。如今大多数车辆都通过CAN进行ECU通信。但是CAN总线仅仅是提供了通信的基础&#xff08;就像是电话&#xff09;&…

CAN协议 J1939

转自&#xff1a;http://blog.sina.com.cn/s/blog_bf97bd7e0102wl2y.html 这几天在公司看了SAE推行的 J1939标准&#xff08;SAE&#xff1a;美国汽车工程协会&#xff09;&#xff0c;这里整理下学习要点&#xff0c;主要包含以下几个协议&#xff1a; 物理层 SAE J1939-11…

J1939协议与CAN2.0对应关系图表

SAE J1939 消息帧格式定义与CAN 2.0B帧格式对应关系 J1939应用层协议详细描述了用于J1939网络的每个参数&#xff0c;包括其数据长度、数据类型、分辨率、范围及参考标签&#xff0c;并为每个参数分配了一个编号&#xff08;SPN&#xff09;。由于J1939协议是以协议数据单元&am…

Python实现CAN总线J1939报文接收、发送

前言 J1939协议是由美国汽车工程师协会&#xff08;SAE&#xff09; (SAE协会简介)定义的一组标准。J1939标准用于卡车、公共汽车和移动液压等重型车辆。在许多方面&#xff0c;J1939标准类似于旧版J1708和J1587标准&#xff0c;但J1939标准协议建立在CAN&#xff08;控制器区域…

J1939标准概述【小白入门】

文章目录 J1939标准概述&#xff1a;J1939/11物理层J1939/13板外诊断连接器J1939/21数据链路层J1939/31网络层J1939/71车辆应用层J1939/73应用层-诊断层J1939/81网络管理总结 J1939标准概述&#xff1a; J1939由下列子标准组成&#xff1a; J1939 – 串行控制和通信车辆网络…

J1939-21数据链路层多帧协议PDU解析

一、协议数据单元&#xff08;PDU&#xff09; P 是优先级&#xff0c;R 是保留位&#xff0c;DP 是数据页&#xff0c;PF 是PDU 格式&#xff0c;PS 是特定PDU&#xff0c;SA 是源地址 优先级&#xff08;P&#xff09;&#xff1a;这三位仅在总线传输中用来优化消息延迟&…

CAN总线的特点及J1939协议通信原理、内容和应用

众多国际知名汽车公司早在20世纪80年代就积极致力于汽车网络技术的研究及应用。迄今已有多种网络标准&#xff0c;如专门用于货车和客车上的SAE的J1939、德国大众的ABUS、博世的CAN、美国商用机器的AutoCAN、ISO的VAN、马自达的PALMNET等。 在我国的轿车中已基本具有电子控制和…

IPEmotion采集J1939协议信号

一 背景 由于商用车相对于乘用车更注重实用性&#xff0c;功能也较单一&#xff0c;且具有产量小的特点&#xff0c;因此在设计开发时需要进行约束&#xff0c;以更大程度实现软硬件的复用和成本的降低&#xff0c;在此需求下J1939协议便随之产生了。 J1939协议是由美国汽车工…

SAE J1939协议读取车辆故障码

基于SAE J1939协议的车辆&#xff0c;默认开启数据广播。当有故障码时&#xff0c;也会按照故障码的格式进行广播。 此处基于外设主动&#xff1a;读取故障码个数->读取故障码->故障码解析 这个步骤来讲&#xff0c;如果被动接收故障码广播&#xff0c;如下解析也适用。 …

车用总线技术 | J1939协议实用指南与J1939数据记录方案

“没错&#xff0c;这是一份SAE J1939协议的简单、实用指南。”—虹科 开篇&#xff1a;在这篇介绍中&#xff0c;我们介绍了J1939协议的基本知识&#xff0c;其中包括PGN和SPN。因为这是一篇偏向应用的简介&#xff0c;所以您还将会学习到如何通过DBC文件解码J1939数据、如何…