Skip to content

Instantly share code, notes, and snippets.

@peace098beat
Created April 6, 2016 03:13
Show Gist options
  • Save peace098beat/dbd05aa69b192970b2e559c9b4ec0ee2 to your computer and use it in GitHub Desktop.
Save peace098beat/dbd05aa69b192970b2e559c9b4ec0ee2 to your computer and use it in GitHub Desktop.
GLCanvasSpectrogram
# 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