Created
April 6, 2016 03:13
-
-
Save peace098beat/dbd05aa69b192970b2e559c9b4ec0ee2 to your computer and use it in GitHub Desktop.
GLCanvasSpectrogram
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # coding:utf-8 | |
| """PySide port of the opengl/samplebuffers example from Qt v4.x""" | |
| import struct | |
| from OpenGL import GL | |
| from OpenGL import GLU | |
| # from OpenGL import GLUT | |
| from OpenGL.GLUT import * | |
| from GLCangvas.baseglcanvas import BaseGLCanvas | |
| from utils.colorMapJet import getColorJetRGBf, getColorJetRGBi | |
| from utils.ptime import time | |
| class GLCanvasSpectrogram(BaseGLCanvas): | |
| def __init__(self, parent=None): | |
| BaseGLCanvas.__init__(self) | |
| self.resize(320, 180) | |
| # 描画タイマー | |
| # self.startTimer(30) | |
| def initializeGL(self): | |
| GL.glClearColor(0.0, 0.0, 0.0, 1.0) | |
| GL.glMatrixMode(GL.GL_PROJECTION) | |
| GL.glLoadIdentity() | |
| GLU.gluOrtho2D(-1.0, 1.0, -1.0, 1.0) | |
| def resizeGL(self, w, h): | |
| GL.glViewport(0, 0, w, h) | |
| GL.glMatrixMode(GL.GL_PROJECTION) | |
| GL.glLoadIdentity() | |
| # 軸幅の設定 | |
| xmin, xmax, ymin, ymax = self._get_axes() | |
| GLU.gluOrtho2D(xmin, xmax, ymin, ymax) | |
| def timerEvent(self, event): | |
| self.update() | |
| def paintGL(self): | |
| newtime = time() | |
| # clear the buffer | |
| GL.glClear(GL.GL_COLOR_BUFFER_BIT) | |
| # debug1 | |
| for yi, y in enumerate(self.cydata): | |
| GL.glBegin(GL.GL_LINE_STRIP) | |
| # GL.glBegin(GL.GL_POINTS) | |
| for xi, x in enumerate(self.cxdata): | |
| GL.glColor(self.cdata[xi, yi, :]) | |
| GL.glVertex(x, y) | |
| GL.glEnd() | |
| # Plot hairline | |
| self.plot_hairline() | |
| # print "glEnd spectrogram", time() - newtime, '[s]' | |
| # ************************************************************** | |
| # Setter | |
| # ************************************************************** | |
| def set_plotting_data(self, xdata, ydata, zdata): | |
| newtime = time() | |
| self.xdata = xdata | |
| self.ydata = ydata | |
| self.zdata = zdata | |
| self.zmin = self.zdata.min() | |
| self.zmax = self.zdata.max() | |
| # 描画元データサイズ | |
| w_data, h_data = self.zdata.shape | |
| print "> zdata, (w,h):", w_data, h_data | |
| # スクリーンサイズの取得 | |
| srn_w, srn_h = self.width(), self.height() | |
| # 色データに変換 | |
| from numpy import zeros as npzeros | |
| self.cdata = npzeros((self.xdata.size, self.ydata.size, 3)) | |
| print "Color ary:", self.cdata.shape, self.xdata.size * self.ydata.size | |
| # # スキップ数 | |
| # self.stepx = 1. | |
| # self.stepy = 1. | |
| # | |
| # while srn_w < w_data / self.stepx: | |
| # self.stepx += 1. | |
| # | |
| # while srn_h < h_data / self.stepy: | |
| # self.stepy += 1. | |
| # | |
| # self.stepx = int(self.stepx) | |
| # self.stepy = int(self.stepy) | |
| # | |
| # print "stepx,stepy", self.stepx, self.stepy | |
| # | |
| # self.cdata = [[getColorJetRGBf(self.zdata[xi, yi], self.zmin, self.zmax) | |
| # for yi in range(0, self.ydata.size, self.stepy)] | |
| # for xi in range(0, self.xdata.size, self.stepx)] | |
| # self.cxdata = [self.xdata[xi] for xi in range(0, self.xdata.size, self.stepx)] | |
| # self.cydata = [self.ydata[yi] for yi in range(0, self.ydata.size, self.stepy)] | |
| # | |
| # from numpy import array as nparray | |
| # | |
| # self.cdata = nparray(self.cdata) | |
| # self.cxdata = nparray(self.cxdata) | |
| # self.cydata = nparray(self.cydata) | |
| # | |
| from numpy import array as nparray | |
| w_pix = 512 | |
| h_pix = 256 | |
| # 間引き処理 | |
| # データがピクセルより少ない場合の処理 | |
| w_pix_min=512 | |
| if w_data < w_pix_min: | |
| w_pix = self.ruijou(w_data) | |
| h_pix_min=256 | |
| if h_data < h_pix_min: | |
| h_pix = self.ruijou(h_data) | |
| # 間引き数の計算 | |
| rw = w_data / w_pix | |
| rh = h_data / h_pix | |
| print "rh, rw:",rh, rw | |
| print "rh * h_pix, rw * w_pix", rh * h_pix, rw * w_pix | |
| # 色データへ変換(Jet) | |
| def ColorJetRGBf(x): | |
| def subColorJetRGBf(x): | |
| return getColorJetRGBf(x, self.zmin, self.zmax) | |
| # return map(subColorJetRGBf, x) | |
| # | |
| # | |
| # # 色データへ変換(Jet) | |
| # self.cdata = nparray(map(ColorJetRGBf, self.zdata[::rw, ::rh])) | |
| # print "cdata size ",self.cdata.shape | |
| # | |
| # # 間引き処理 | |
| # self.cxdata = self.xdata[::rw] | |
| # self.cydata = self.ydata[::rh] | |
| # | |
| # # list->ndarray に変換 | |
| # self.cdata = nparray(self.cdata) | |
| # self.cxdata = nparray(self.cxdata) | |
| # self.cydata = nparray(self.cydata) | |
| # | |
| # | |
| # # 軸の設定 | |
| # self.auto_axis() | |
| # | |
| # # 経過時間 | |
| # dt = time() - newtime | |
| # print ">screensize", self.size() | |
| # print ">set_plotting_data", dt, '[s]' | |
| # print ">set cdata size,", self.cdata.shape, self.cdata.size | |
| # | |
| # # ************************************ | |
| # # Helper | |
| # # ************************************ | |
| # def auto_axis(self): | |
| # # 幅を自動設定 | |
| # xmin, xmax = self.xdata.min(), self.xdata.max() | |
| # ymin, ymax = self.ydata.min(), self.ydata.max() | |
| # zmin, zmax = self.zdata.min(), self.zdata.max() | |
| # self.set_axes(xmin, xmax, ymin, ymax) | |
| # | |
| # | |
| # def ruijou(self, x): | |
| # from numpy import log2, floor | |
| # | |
| # y0 = log2(x) | |
| # # 最小t | |
| # p = floor(y0) | |
| # return int(2 ** p) | |
| class GLCanvasSpectrogramTexture(BaseGLCanvas): | |
| """ | |
| textureを使って画像を描画する. | |
| GL.glVertexより早ければこちらを採用 | |
| """ | |
| def __init__(self, parent=None): | |
| BaseGLCanvas.__init__(self) | |
| self.resize(320, 180) | |
| # 描画タイマー | |
| # self.startTimer(30) | |
| glutInit() | |
| def initializeGL(self): | |
| GL.glClearColor(0.0, 0.0, 0.0, 1.0) | |
| GL.glMatrixMode(GL.GL_PROJECTION) | |
| GL.glLoadIdentity() | |
| GLU.gluOrtho2D(-1.0, 1.0, -1.0, 1.0) | |
| def resizeGL(self, w, h): | |
| GL.glViewport(0, 0, w, h) | |
| GL.glMatrixMode(GL.GL_PROJECTION) | |
| GL.glLoadIdentity() | |
| # 軸幅の設定 | |
| GLU.gluOrtho2D(-1, 1, -1, 1) | |
| GL.glMatrixMode(GL.GL_MODELVIEW) | |
| def timerEvent(self, event): | |
| self.update() | |
| def paintGL(self): | |
| newtime = time() | |
| vertex = [ | |
| [-1.0, -1.0], | |
| [-1.0, 1.0], | |
| [1.0, 1.0], | |
| [1.0, -1.0] | |
| ] | |
| face = [ | |
| [0, 1, 2, 3]] | |
| uvcoord = [ | |
| [0.0, 0.0], | |
| [1.0, 0.0], | |
| [1.0, 1.0], | |
| [0.0, 1.0]] | |
| # clear the buffer | |
| GL.glClear(GL.GL_COLOR_BUFFER_BIT) | |
| GL.glMatrixMode(GL.GL_PROJECTION) | |
| GL.glLoadIdentity() | |
| GLU.gluOrtho2D(-1, 1, -1, 1) | |
| GL.glMatrixMode(GL.GL_MODELVIEW) | |
| # 画像のバイナリを作成 | |
| # wとhは2の累乗でないければいけない | |
| w = self.texture_data_w | |
| h = self.texture_data_h | |
| tex = GL.glGenTextures(1) | |
| GL.glBindTexture(GL.GL_TEXTURE_2D, tex) | |
| GL.glTexImage2D(GL.GL_TEXTURE_2D, 0, GL.GL_RGB, | |
| h, w, 0, GL.GL_RGB, GL.GL_UNSIGNED_BYTE, self.texture_data) | |
| # texture | |
| GL.glEnable(GL.GL_TEXTURE_2D) # 2次元テクスチャを使用可能にします。 | |
| # テクスチャが縮小されて張られるときの設定。 | |
| # GL_NEAREST 近いピクセルの色を使用。GL_LINEARまわりの色を補間して使用。 | |
| GL.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR) | |
| # テクスチャが拡大されて張られるときの設定。 | |
| GL.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR) | |
| GL.glColor(1,1,1) | |
| GL.glBegin(GL.GL_QUADS) | |
| for j in range(len(face)): | |
| for i in range(4): | |
| n = face[j][i] | |
| GL.glTexCoord2f(uvcoord[n][0], uvcoord[n][1]) | |
| GL.glVertex(vertex[n]) | |
| GL.glEnd() | |
| GL.glBindTexture(GL.GL_TEXTURE_2D, 0) | |
| # # 2次元テクスチャを使用不可能にします | |
| GL.glMatrixMode(GL.GL_PROJECTION) | |
| GL.glLoadIdentity() | |
| GLU.gluOrtho2D(*self._get_axes()) | |
| GL.glMatrixMode(GL.GL_MODELVIEW) | |
| # TODO:HairLineを描画したいが,Textureを張って後だとエラーが出る. | |
| # GL.glBegin(GL.GL_LINES) | |
| # GL.glVertex(20, 50) | |
| # GL.glVertex(0, 0) | |
| # GL.glEnd() | |
| # Plot hairline | |
| self.plot_hairline() | |
| GL.glColor3f(0,0,0) | |
| src_w, src_h = self.xrange, self.yrange | |
| tx = (src_w*self.hairline_x + self.xmin) | |
| ty = (src_h*self.hairline_y + self.ymin) | |
| GL.glRasterPos(tx, ty) | |
| text="%0.1f %0.1f"%(tx*1000, ty/1000) | |
| for c in text: | |
| glutBitmapCharacter(GLUT_BITMAP_HELVETICA_10, ord(c)) | |
| # print "glEnd spectrogram", time() - newtime, '[s]' | |
| # ************************************************************** | |
| # Setter | |
| # ************************************************************** | |
| def set_plotting_data(self, xdata, ydata, zdata): | |
| print "\n" | |
| from numpy import zeros as npzeros | |
| from numpy import array as nparray | |
| # 時間計測 | |
| newtime = time() | |
| # ポインタのコピー | |
| self.xdata = xdata | |
| self.ydata = ydata | |
| self.zdata = zdata | |
| # 最大値, 最小値の取得 | |
| self.zmin = self.zdata.min() | |
| self.zmax = self.zdata.max() | |
| # 描画元データサイズ | |
| w_data, h_data = self.zdata.shape | |
| print "> zdata, (w,h):", w_data, h_data | |
| # スクリーンサイズの取得 | |
| srn_w, srn_h = self.width(), self.height() | |
| print "> srn_w, srnh:", srn_w, srn_h | |
| # 画像のピクセル数(2の累乗でないければいけない) | |
| w_pix = 512 | |
| h_pix = 256 | |
| # ****************************************** | |
| # 色データに変換 | |
| # ****************************************** | |
| # 色データ配列の準備 | |
| self.cdata = npzeros((self.xdata.size, self.ydata.size, 3)) | |
| print "Color ary:", self.cdata.shape, self.xdata.size * self.ydata.size | |
| # 間引き処理 | |
| # データがピクセルより少ない場合の処理 | |
| w_pix_min=512 | |
| if w_data < w_pix_min: | |
| w_pix = self.ruijou(w_data) | |
| h_pix_min=256 | |
| if h_data < h_pix_min: | |
| h_pix = self.ruijou(h_data) | |
| # 間引き数の計算 | |
| rw = w_data / w_pix | |
| rh = h_data / h_pix | |
| print "rh, rw:",rh, rw | |
| print "rh * h_pix, rw * w_pix", rh * h_pix, rw * w_pix | |
| # 色データへ変換(Jet) | |
| def ColorJetRGBi(x): | |
| def subColorJetRGBi(x): | |
| return getColorJetRGBi(x, self.zmin, self.zmax) | |
| return map(subColorJetRGBi, x) | |
| # 色データへ変換(Jet) | |
| self.cdata = nparray(map(ColorJetRGBi, self.zdata[::rw, ::rh])) | |
| print "cdata size ",self.cdata.shape | |
| # 間引き処理 | |
| self.cxdata = self.xdata[::rw] | |
| self.cydata = self.ydata[::rh] | |
| # list->ndarray に変換 | |
| self.cdata = nparray(self.cdata) | |
| self.cxdata = nparray(self.cxdata) | |
| self.cydata = nparray(self.cydata) | |
| # wとhは2の累乗でないければいけない | |
| w = w_pix | |
| h = h_pix | |
| texdata = '' | |
| for x in range(w): | |
| for y in range(h): | |
| c = self.cdata[x, y] | |
| texdata += struct.pack('BBB', c[0], c[1], c[2]) | |
| # テクスチャの格納 | |
| self.texture_data = texdata | |
| self.texture_data_w = w | |
| self.texture_data_h = h | |
| dt = time() - newtime | |
| print "QGLCanvasSpectrogramTexture : set plot data dt:", dt | |
| self.auto_axis() | |
| pass | |
| def ruijou(self, x): | |
| from numpy import log2, floor | |
| y0 = log2(x) | |
| # 最小t | |
| p = floor(y0) | |
| return int(2 ** p) | |
| # ************************************ | |
| # Helper | |
| # ************************************ | |
| def auto_axis(self): | |
| # 幅を自動設定 | |
| xmin, xmax = self.cxdata.min(), self.cxdata.max() | |
| ymin, ymax = self.cydata.min(), self.cydata.max() | |
| zmin, zmax = self.cdata.min(), self.cdata.max() | |
| self.set_axes(xmin, xmax, ymin, ymax) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment