matplotlib庫是一個常用的數(shù)據(jù)可視化庫。我們在做桌面應用的時候有時候需要數(shù)據(jù)的展現(xiàn)也可以使用matplotlib中。那么怎么使用pyqt實現(xiàn)將matplotlib圖像嵌入scollarea中并顯示滾動條呢?接下來這篇文章帶你了解。
前言
如題目所述,又是花費了兩天的時間實現(xiàn)了該功能,本來今天下午有些心灰意冷,打算放棄嵌入到Scoll Area中的想法,但最后還是心里一緊,仔細梳理了一下邏輯,最終實現(xiàn)了功能
效果展示
注意:當你想實現(xiàn)一個子功能的時候,可以從新創(chuàng)建兩個文件:
×××.ui文件(如上圖效果展示是和我項目里的位置一樣的)×××.py文件(用來實現(xiàn)功能)
截圖
如上圖所示,
紅色框
里的文件是實現(xiàn)效果展示的所有源文件。但是文件夾testcode
是為了實現(xiàn)將Matplotlib圖像嵌入到Scoll Area中所做的所有工作,稍后我會將參考資源
放入文章末尾
一、解決步驟
1.1 qt designer
設計ui文件,控件的位置需要和自己項目中控件的位置相同,以便功能實現(xiàn)后方便項目調用
保存為
testpiv.ui
文件
1.2 pycharm編寫程序
代碼
import cv2
import os
import sys
import math
from PyQt5 import QtCore
from PyQt5.QtWidgets import *
from PyQt5.uic import loadUi
import matplotlib
from matplotlib import pyplot as plt
matplotlib.use("Qt5Agg") # 聲明使用QT5
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
matplotlib.use("Qt5Agg") # 聲明使用QT5
from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar
#創(chuàng)建一個matplotlib圖形繪制類
class MyFigure(FigureCanvas):
def __init__(self,width, height, dpi):
# 創(chuàng)建一個Figure,該Figure為matplotlib下的Figure,不是matplotlib.pyplot下面的Figure
self.fig = plt.figure(figsize=(width, height), dpi=dpi)
# 在父類中激活Figure窗口,此句必不可少,否則不能顯示圖形
super(MyFigure,self).__init__(self.fig)
# 調用Figure下面的add_subplot方法,類似于matplotlib.pyplot下面的subplot(1,1,1)方法
class scollarea_showpic(QMainWindow):
def __init__(self, queryPath=None, samplePath=None,limit_value = None):
super().__init__()
self.queryPath = queryPath # 圖庫路徑
self.samplePath = samplePath # 樣本圖片
self.limit_value = limit_value
self.ui()
plt.rcParams['font.sans-serif'] = ['KaiTi'] # 只有這樣中文字體才可以顯示
def ui(self):
loadUi('./testpiv.ui', self)
self.SIFT(self.queryPath,self.samplePath,self.limit_value)
def getMatchNum(self,matches,ratio):
'''返回特征點匹配數(shù)量和匹配掩碼'''
matchesMask=[[0,0] for i in range(len(matches))]
matchNum=0
for i,(m,n) in enumerate(matches):
if m.distance < ratio * n.distance: #將距離比率小于ratio的匹配點刪選出來
matchesMask[i]=[1,0]
matchNum+=1
return (matchNum,matchesMask)
def SIFT(self,dirpath,picpath,limit_value):
# path='F:/python/gradu_design/gra_des/'
queryPath=dirpath #圖庫路徑
samplePath=picpath #樣本圖片
comparisonImageList=[] #記錄比較結果
#創(chuàng)建SIFT特征提取器
sift = cv2.xfeatures2d.SIFT_create()
#創(chuàng)建FLANN匹配對象
"""
FLANN是類似最近鄰的快速匹配庫
它會根據(jù)數(shù)據(jù)本身選擇最合適的算法來處理數(shù)據(jù)
比其他搜索算法快10倍
"""
FLANN_INDEX_KDTREE=0
indexParams=dict(algorithm=FLANN_INDEX_KDTREE,trees=5)
searchParams=dict(checks=50)
flann=cv2.FlannBasedMatcher(indexParams,searchParams)
sampleImage=cv2.imread(samplePath,0)
kp1, des1 = sift.detectAndCompute(sampleImage, None) #提取樣本圖片的特征
for parent,dirnames,filenames in os.walk(queryPath):
print('parent :',parent,' ','dirnames :',dirnames)
for p in filenames:
p=queryPath+p
# print('pic file name :',p)
queryImage=cv2.imread(p,0)
kp2, des2 = sift.detectAndCompute(queryImage, None) #提取比對圖片的特征
matches=flann.knnMatch(des1,des2,k=2) #匹配特征點,為了刪選匹配點,指定k為2,這樣對樣本圖的每個特征點,返回兩個匹配
(matchNum,matchesMask) = self.getMatchNum(matches,0.9) #通過比率條件,計算出匹配程度
matchRatio=matchNum*100/len(matches)
drawParams=dict(matchColor=(0,255,0),
singlePointColor=(255,0,0),
matchesMask=matchesMask,
flags=0)
comparisonImage=cv2.drawMatchesKnn(sampleImage,kp1,queryImage,kp2,matches,None,**drawParams)
comparisonImageList.append((comparisonImage,matchRatio)) #記錄下結果
comparisonImageList.sort(key=lambda x:x[1],reverse=True) #按照匹配度排序 降序
new_comparisonImageList = comparisonImageList[:limit_value]
count=len(new_comparisonImageList)
column = 1 # 列
row = math.ceil(count/column) # 行 math.ceil: 函數(shù)返回大于或等于一個給定數(shù)字的最小整數(shù)
print('列:',column, ' ','行:',row)
#繪圖顯示
F = MyFigure(width=10, height=10, dpi=100) # 500 * 400
for index,(image,ratio) in enumerate(new_comparisonImageList):
F.axes = F.fig.add_subplot(row,column,index+1)
F.axes.set_title('Similiarity %.2f%%' % ratio)
plt.imshow(image)
# 調整subplot之間的間隙大小
plt.subplots_adjust(hspace=0.2)
self.figure = F.fig
# FigureCanvas:畫布
self.canvas = FigureCanvas(self.figure) # fig 有 canvas
self.canvas.resize(self.picwidget.width(), 3000) # 畫布大小
self.scrollArea = QScrollArea(self.picwidget) # picwidget上有scroll
self.scrollArea.setFixedSize(self.picwidget.width(), self.picwidget.height())
self.scrollArea.setWidget(self.canvas) # widget上有scroll scroll有canvas
self.nav = NavigationToolbar(self.canvas, self.picwidget) # 創(chuàng)建工具欄
self.setMinimumSize(self.width(), self.height())
self.setMaximumSize(self.width(), self.height())
self.setWindowTitle('Test')
if __name__ == "__main__":
app = QApplication(sys.argv)
queryPath='F:/python/gradu_design/gra_des/imges/' #圖庫路徑
samplePath='F:/python/gradu_design/gra_des/imges/resized_logo1_1.jpg' #樣本圖片
main = scollarea_showpic(queryPath,samplePath,3)
main.show()
sys.exit(app.exec_())
總結
從目前我的認知來講,你想要實現(xiàn)的功能,基本上換一種思路、想法,都是可能會有解決方案的,只不過可能難度不同,你需要投入的精力不同。
結合本篇博客來說,從我產生這個想法來說,我一直在找資料,從一開始的簡單搜索同一個內容到后面轉變搜索思路,到最后梳理邏輯框架、代碼,最后實現(xiàn)功能,此過程耗費的時間(兩天多)不算長,但也不算短。中間的過程是煎熬的,幾次試圖想放棄,最后還是挺了過來,還是很開心的。
只要不放棄,你就可以!
以上就是怎么使用pyqt實現(xiàn)將matplotlib圖像嵌入scollarea中并顯示滾動條的詳細內容,更多PyQt5的使用介紹請關注W3Cschool其它相關文章!