2017-01-11 1 views
2

저는 tif 스택으로 작업 중이며 QImage은 45도 각도로 일부 이미지를 비뚤어지게 보입니다. Matplotlib은 두 테스트 케이스 모두에서 문제없이 이미지를 표시 할 수 있습니다 (두 개의 tif 스택에 대한 링크가 아래에 나와 있습니다). 그래서 어딘가에서 배열을 망쳤다고 생각하지 않습니다. 여기QImage는 일부 이미지를 비뚤어 지지만 다른 이미지는 왜곡하지 않습니다.

이 동작 예이다 :

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_()) 

여기서 출력의 스크린 샷이다 (참고 :이 예에서는 단순화를위한 TIF 스택의 첫번째 이미지 표시)

Qimage하기 matplotlib VS를

enter image description here

올바르게 표시되는 tif 스택에 대한 링크는 다음과 같습니다.

표시 될 때 53,691,363,210

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 (가로) 길이는 QImage이 예상대로 처리하려면 2의 제곱수 여야합니다. 그것은 우스운 제한이다! 내가 이해하지 못하는 무언가가있을거야. 물론 임의의 모양의 배열을 처리 할 수있는 방법이 있습니다.

은 ... 나는 가정, 원칙적으로, 하나는 먼저 이미지에 왜곡을 적용하고 단지 QImage가 ... 다시 뒤틀림을 방지 할 수있다 (<를 ==이 솔루션의 팬이가)

+1

@ echumoro 동의합니다! 그 파일 호스팅 사이트를 처음 사용했습니다. 나는 그들을 다시 사용하지 않을 것이다. 직접 다운로드가되도록 링크를 업데이트했습니다. 나는 또한 그 파일들이 얼마나 방대한지 알지 못했다. 새로운 것들은 훨씬 가볍다. 다운로드 시간은 2 ~ 2 분 정도 소요됩니다. – onjre

+0

감사합니다. FWIW, 문제를 재현 할 수는 있지만 현재로서는 원인에 대한 통찰력이 없습니다. – ekhumoro

+0

QImage (fname)를 사용하십시오. Tiff는 QImage에서 지원됩니다. – eyllanesc

답변

1

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) 

나머지 코드는 같습니다.

1

이미지입니다 이 아닌 경우이 비뚤어지면 기본 데이터가 잘못 해석됩니다.

사용중인 생성자에서 데이터 버퍼는 평면이며 행 및 열 크기도 픽셀로 지정해야합니다. 어떻게 든 행을 너무 길게 지정 했으므로 다음 행의 시작 부분이 현재 행의 끝에 래핑됩니다. 이것이 이미지의 "스트라이핑"을 얻는 이유이며, 이후 행에 도달 할 때 점차 더 많은 양의 줄 바꿈이 나타나는 이유입니다. 또한 QImage(fname) 버전의 생성자를 사용할 때 작동하는 이유도 설명합니다. 이 생성자는 Qt 라이브러리 코드를 사용하여 이미지 데이터를 읽습니다. 이미지 데이터는 자신의 코드에서 문제가되지 않습니다.

데이터를 잘못 읽을 수있는 곳이 몇 군데 있습니다. 필자는 PIL 패키지의 세부 사항을 모르지만, np.array(stack) 라인은 그럴듯한 후보자처럼 보입니다. 스택 객체가 버퍼 인터페이스를 어떻게 노출하는지는 모르겠지만 생각보다 다르게 수행 할 수 있습니다 (예 : 데이터가 행 메이저가 아니라 열). 또한 사용하는 QImage 생성자는 8 비트 데이터의 경우에도 32 비트 데이터 정렬을 기대합니다. 그것은 문제 일 수 있습니다.

또 다른 그럴듯한 후보는 uint8Convert 메서드이며 실수로 데이터를 전치 시키거나 앞으로/뒤로 롤링 할 수 있습니다. 이것은 사각형 크기가 작동하는 이유 일지 모르지만 사각형은 그렇지 않습니다.

+0

분명히하기 위해 직사각형과 사각형이 모두 작동하거나 실패 할 수 있습니다. 따라서 직사각형이든 사각형이든 상관 없습니다. 또한'matplotlib'을 사용하여 배열 자체가 "스트라이핑"되지 않았 음을 확인하고 있으므로'np.array (stack)'또는'uint8Convert'가 배열을 엉망으로 만들고 있다고 생각하지 않습니다 ('matplotlib'). 이 두 메소드가 호출 된 후). 하지만 ... 32 비트 정렬 요구 사항은 가능한 문제처럼 들립니다. 나는 이것이 무엇을 의미하는지 정말로 이해하지 못한다. 당신은 정교 할 수 있습니까? – onjre

+1

차갑고, 나는'np.array()'호출과'uint8Convert' 메쏘드가 아마도 괜찮다고 동의한다. 정렬 제약 조건은 데이터의 각 라인이 메모리의 32 비트 경계에서 시작되어야 함을 의미합니다. 이것은 문제인 것처럼 보인다. 나는 Qt C++ 소스를 중심으로 (* 깊은 *) 파고 들었고, 이것이 문제를 야기 할 것 같다. (시작하려면 https://code.woboq.org/qt5/qtbase/src/gui/image/qimage.cpp.html#804를 참조하십시오. 필요한 경우 자세한 내용을 보낼 수 있습니다.) 8 비트 데이터를 사용하지만 32 비트를 사용합니까? – bnaecker

+0

링크를 제공해 주셔서 감사합니다. 그게 내가 알아낼 수있게 도와 줬어. 배열의 행당 바이트 수를 지정하는 옵션이 있습니다. 이 값을 제공하면 문제가 해결됩니다. 나는 코드를 게시 할 것이다 ... – onjre

관련 문제