將opencv的imread()函數讀取的圖片用QLabel顯示


switchPicture.py

from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
import numpy as np
import cv2
import sys

class MyWidget(QWidget):
    def __init__(self, parent = None):
        super().__init__(parent)
        self.setWindowTitle(self.tr('顯示圖片'))
        self.resize(500,400)
        self.label = QLabel(self)
        self.label.setFrameShape(QFrame.Box)
        self.label.setAlignment(Qt.AlignCenter)
        img = cv2.imread('girl_1.jpg')
        #cv2.imshow('111',img)
        #cv2.waitKey(0)
        width = img.shape[1]
        height = img.shape[0]
        print('cv2, width: '+str(width)+' height: '+str(height))
        cv2.cvtColor(img, cv2.COLOR_BGR2RGB,img)
        qt_img = QImage(img.data,width,height,QImage.Format_RGB888)
        #print(type(qt_img))

        #self.label.setPixmap(QPixmap.fromImage(qt_img))

        self.label.setGeometry(0, 0, 400, 300)
        n_width = qt_img.width()
        n_height = qt_img.height()
        print('Qt, width: '+str(n_width)+' height: '+str(n_height))
        if n_width / 400 >= n_height / 300:
            ratio = n_width / 400
        else:
            ratio = n_height / 300
        new_width = n_width / ratio
        new_height = n_height / ratio
        new_img = qt_img.scaled(new_width, new_height, Qt.KeepAspectRatio)
        self.label.setPixmap(QPixmap.fromImage(new_img))




if __name__ == '__main__':
    app = QApplication(sys.argv)
    widget = MyWidget()
    widget.show()
    #print(widget.children())
    sys.exit(app.exec_())

 img是<class 'numpy.ndarray'>類型的,img.shape是一個包含三個元素的元祖,img.data是<class 'memoryview'>類型的。

numpy中是這樣解釋ndarray.data的:

data

Python buffer object pointing to the start of the array's data.

所以我們可以將ndarray.data理解為一個指向存儲array數組數據的內存的指針。

 

再來看QImage的構造函數:

 1  |  QImage()
 2  |  QImage(QSize, QImage.Format)
 3  |  QImage(int, int, QImage.Format)
 4  |  QImage(bytes, int, int, QImage.Format)
 5  |  QImage(sip.voidptr, int, int, QImage.Format)
 6  |  QImage(bytes, int, int, int, QImage.Format)
 7  |  QImage(sip.voidptr, int, int, int, QImage.Format)
 8  |  QImage(List[str])
 9  |  QImage(str, format: str = None)
10  |  QImage(QImage)
11  |  QImage(Any)

我們在上面的程序中用到的是第5個構造函數,下面解釋一下第5個構造函數的各個參數:

@sip.voidptr: 把它理解為一個地址,這個地址指向的內存,存儲的是圖片的所有像素點的值

@int:代表圖像的寬度

@int:代表圖像的高度

@QImage.Format:圖像是BGR格式還是RGB格式,等等

 

在上面的程序中,我們用cv2.imread()讀取的圖片,將結果存在img中(img是一個np.ndarray數組),然后我們再將img.data傳遞給QImage的構造函數。

在這,我不禁有一個疑惑,將img.data傳遞給QImage,QImage是如何解析它並生成圖片的呢?

以下是我的理解:

img.data指向的內存連續存儲着的許多整形數字,這些數字每三個或幾個為一組表示一個像素點,在內存中沒有所謂的圖片的行和列之分,那么QImage是如何區分出圖片有多少行,有多少列呢?

QImage的構造函數中有兩個int型變量,他們分別是圖片的寬度和高度,QImage就是通過這兩個數字來識別圖片有多少行和多少列的。在最后的參數QImage.Format,它的作用就是讓QImage知道

應該讓幾個數字一組表示一個像素點。

 

 

有時,我們使用第5個構造函數會出現圖像扭曲的問題,這是我們應該用第7個構造函數QImage(sip.voidptr, int, int, int, QImage.Format),第三個int型參數表示的是每行有多少個字節

將上面程序中對應項改為下面的程序就可以了,我這里又增加了一個channel變量,用於計算每行有多少字節。

channel = img.shape[2]
qt_img = QImage(img1.data,width,height,width*channel,QImage.Format_RGB888)

出現扭曲的原因是QImage構造函數不知道圖片一行有多少個像素點了。

下面是正常顯示和扭曲的圖片:

正常:

 

扭曲:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM