python - QImage 倾斜某些图像,但不倾斜其他图像

标签 python matplotlib python-3.5 pyqt5 qimage

我正在使用 tif 堆栈,QImage 似乎将某些图像倾斜到 45 度角。 Matplotlib 能够在两个测试用例中毫无问题地显示图像(下面提供了两个 tif 堆栈的链接),所以我不认为我在某个地方搞砸了我的数组。

这是一个工作示例:(注意:为简单起见,此示例仅显示 tif 堆栈中的第一个图像)

import matplotlib.pyplot as plt
import sys
from PIL import Image
from PyQt5.QtGui import QPixmap, QImage 
from PyQt5.QtWidgets import (QMainWindow, QApplication, QVBoxLayout, 
                             QWidget, QFileDialog, QGraphicsPixmapItem, QGraphicsView,
                             QGraphicsScene)

import numpy as np


class Example(QMainWindow):
    def __init__(self):
        super().__init__()

        self.initUI()


    def initUI(self):
        # set up a widget to hold a pixmap
        wid = QWidget(self)
        self.setCentralWidget(wid)
        self.local_grview = QGraphicsView()
        self.local_scene = QGraphicsScene()
        vbox = QVBoxLayout()                
        self.local_grview.setScene( self.local_scene )
        vbox.addWidget(self.local_grview)
        wid.setLayout(vbox)

        # load and display the image
        self.loadImage()

        # display the widget
        self.show()

        # also use matplotlib to display the data as it should appear
        plt.imshow(self.dataUint8[0], cmap='gray')
        plt.show()


    def loadImage(self):
        fname = QFileDialog.getOpenFileName(self, 'Open file', '/home')[0]

        # use the tif reader to read in the tif stack
        self.data = self.readTif(fname)

        # convert to uint8 for display
        self.dataUint8 = self.uint8Convert(self.data)

        ###############################################################################################################################
        # I suspect this is where something goes wrong
        ###############################################################################################################################
        # create a QImage object
        self.im = QImage(self.dataUint8[0], self.dataUint8[0].shape[1], self.dataUint8[0].shape[0], QImage.Format_Grayscale8)
        # if we save using self.im.save() we also have a skewed image
        ###############################################################################################################################

        # send the QImage object to the pixmap generator
        self.pixmap = QPixmap(self.im)


        self.pixMapItem = QGraphicsPixmapItem(self.pixmap, None)
        self.local_scene.addItem(self.pixMapItem)

    def readTif(self, filename): # use this function to read in a tif stack and return a 3D numpy array
        # read in the file
        stack = Image.open(filename)    

        # extract each frame from the file and store in the frames variable
        frames = []
        i = 0
        while True:
            try:
                stack.seek(i) # move to the ith position in the stack
                frames.append(np.array(stack) )
                i += 1
            except EOFError:
                # end of stack
                break
        del stack # probably unnecessary but this presumably saves a bit of memory

        return frames 


    def uint8Convert(self, frames): # use this function to scale a 3D numpy array of floats to 0-255 so it plays well with Qt methods

        # convert float array to uint8 array
        if np.min(frames)<0:
            frames_uint8 = [np.uint8((np.array(frames[i]) - np.min(frames[i]))/np.max(frames[i])*255) for i in range(np.shape(frames)[0])]
        else:
            frames_uint8 = [np.uint8(np.array(frames[i])/np.max(frames[i])*255) for i in range(np.shape(frames)[0])]

        return frames_uint8


if __name__=='__main__':
    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())

这是输出的屏幕截图:

Qimage 与 matplotlib

enter image description here

以下是正确显示的 tif 堆栈的链接:

https://drive.google.com/uc?export=download&id=0B9EG5AHWC9qzX3NrNTJRb2toV2c

这是一个指向 TIF 堆栈的链接,该链接在显示时会倾斜:

https://drive.google.com/uc?export=download&id=0B9EG5AHWC9qzbFB4TDU4c2x1OE0

如果能帮助理解为什么QImage 会扭曲该图像,我们将不胜感激。两个 tif 堆栈之间唯一的主要区别是,倾斜显示的堆栈在图像周围有一个填充的黑色区域(零),这使得阵列更大。

更新:我现在发现,如果我将有问题的图像裁剪为 1024x1024 或 512x512 或 1023x1024 QImage 会正确显示,但按 1024x1023 裁剪会显示倾斜。因此,x(水平)长度似乎必须是 2 的幂才能让 QImage 按预期进行处理。这是一个可笑的限制!一定有什么我不明白的地方。当然有一种方法可以让它处理任意形状的数组。

...我想,原则上,人们可以首先对图像应用倾斜,然后让QImage将其倾斜回来...(<==不喜欢这个解决方案)

最佳答案

非常感谢 bnaecker 提供的 32 位对齐提示并提供源链接。这是解决方案。

QImage 需要知道数组每行有多少字节,否则它只会猜测(并且在某些情况下猜测错误)。因此,在 loadImage() 函数中使用以下内容会产生正确的输出。

# get the shape of the array
nframes, height, width = np.shape(self.dataUint8)

# calculate the total number of bytes in the frame 
totalBytes = self.dataUint8[0].nbytes

# divide by the number of rows
bytesPerLine = int(totalBytes/height)

# create a QImage object 
self.im = QImage(self.dataUint8[0], width, height, bytesPerLine, QImage.Format_Grayscale8)

其余代码相同。

关于python - QImage 倾斜某些图像,但不倾斜其他图像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41596940/

相关文章:

python - 无法从 GAE 本地环境中获取 URL

python - 如何让我的 Python 模块在 Linux 系统范围内可用?

python - 如何使 IPython 笔记本 matplotlib 绘图内联

python - Heroku:即使使用 runtime.txt,也无法检测到此 python 应用程序的默认语言

python - 在 Python 中,str 和 int 之间的哪种转换方式更快?

python - 获取错误 : You've reached your account limit of 3 concurrent processes with Heroku

python - 来自 numpy.linalg.svd 的大型矩阵的 MemoryError

python - 用 matplotlib 显示每一行的最终 y 轴值

Python StatsModels 时间序列分解重复图

python - pandas.read_csv 与其他用于将 CSV 加载到 Postgres 数据库中的 csv 库