如何在Python PyQt5中解决高光谱图像嵌入QLabel的报错问题
问题:QPixmap嵌入高光谱图像到QLabel失败
在Qt界面中,将普通图像用QPixmap嵌入QLabel完全正常,但嵌入处理后的高光谱图像时出现错误。使用rasterio处理高光谱图像的代码如下:
img = rs.open('HYP.tif') profile = img.profile profile.update(count=3, compress='lzw') full_img = img.read() band1 = int(input('band number 1:')) band2 = int(input('band number 2:')) band3 = int(input('band number 3:')) b1 = img.read(band1) b2 = img.read(band2) b3 = img.read(band3) def normalize(array): #Normalizes numpy arrays into scale 0.0 - 1.0 array_min, array_max = array.min(), array.max() return (array - array_min) / (array_max - array_min) # Normalize the bands redn = normalize(b3) greenn = normalize(b2) bluen = normalize(b1) rgb = np.dstack((bluen, redn, greenn)) rgb1 = rgb.T rasterio.plot.show(rgb1) rgb3 = rgb1 / rgb1.max() rgb3 = rgb3 * 255 rgb3 = rgb3.astype(numpy.uint32) rasterio.plot.show(rgb3) file_list = [rgb1.read, greenn, bluen] with rs.open('outimg.png', 'w', **profile) as dest: for band_nr, src in enumerate(file_list, start=1): dest.write(src, band_nr) self.label_2.setPixmap(QtGui.QPixmap('outimg.png'))
执行self.label_2.setPixmap(QtGui.QPixmap('outimg.png'))时,报错:
foo: Sorry, can not handle images with 32-bit samples.
错误原因
- 格式不兼容:Qt的QPixmap仅支持单通道8位的RGB/RGBA图像(总像素深度24位或32位),而你生成的
outimg.png是单通道32位采样的图像,超出了QPixmap的支持范围。 - 代码数据处理错误:
- 你将
rgb3转成了uint32,但后续保存时并没有使用这个数据,反而误用了rgb1.read(这是rasterio的读取方法,不是实际图像数据)和归一化后的0-1浮点数数组,导致保存的图像格式不符合要求。 - 更新profile时未调整
dtype,原高光谱图像的高位深度被保留,最终输出的图像还是32位采样。
- 你将
解决方法
方法1:修正保存流程,生成符合要求的8位RGB图像
import rasterio as rs import numpy as np from PyQt5 import QtGui # 读取高光谱图像 img = rs.open('HYP.tif') band1 = int(input('band number 1:')) band2 = int(input('band number 2:')) band3 = int(input('band number 3:')) # 读取指定波段 b1 = img.read(band1) b2 = img.read(band2) b3 = img.read(band3) def normalize(array): # 归一化到0-1范围 array_min, array_max = array.min(), array.max() return (array - array_min) / (array_max - array_min) # 归一化各波段 redn = normalize(b3) greenn = normalize(b2) bluen = normalize(b1) # 组合为RGB图像并转换为0-255的8位无符号整数 rgb = np.dstack((bluen, redn, greenn)) * 255 rgb = rgb.astype(np.uint8) # 构建新的profile,指定8位格式和PNG驱动 profile = img.profile.copy() profile.update( count=3, dtype=np.uint8, compress='lzw', driver='PNG' ) # 转换为rasterio要求的(C, H, W)通道顺序 rgb_raster = np.transpose(rgb, (2, 0, 1)) # 保存图像 with rs.open('outimg.png', 'w', **profile) as dest: dest.write(rgb_raster) # 加载到QLabel self.label_2.setPixmap(QtGui.QPixmap('outimg.png'))
方法2:直接将numpy数组转成QPixmap(无需存文件,更高效)
在得到rgb(uint8类型的(H,W,3)数组)后,直接转换:
height, width, channel = rgb.shape bytes_per_line = channel * width # 转成QImage q_image = QtGui.QImage(rgb.data, width, height, bytes_per_line, QtGui.QImage.Format_RGB888) # 转成QPixmap并设置 self.label_2.setPixmap(QtGui.QPixmap.fromImage(q_image))
关键修正点
- 必须将图像数据转换为
np.uint8(0-255范围),确保单通道是8位采样。 - 保存图像时,profile要指定
dtype=np.uint8,同时调整通道顺序为rasterio要求的(C, H, W)。 - 避免使用
uint32这类QPixmap不支持的高位深度类型。
内容的提问来源于stack exchange,提问作者Shivanshika Chauhan
相关产品推荐
相关产品推荐

