Package pyforms :: Package gui :: Package Controls :: Package ControlPlayer :: Module VideoGLWidget |
[hide private]
[frames] | no frames]

# Source Code for Module pyforms.gui.Controls.ControlPlayer.VideoGLWidget

      1  #!/usr/bin/python
      2  # -*- coding: utf-8 -*-
      3
      4  """ pyforms.gui.Controls.ControlPlayer.VideoGLWidget
      5
      6  """
      7
      8  import pyforms.Utils.tools as tools
      9  import math
     10  from PyQt4 import uic
     11  from PyQt4.QtOpenGL import QGLWidget
     12  from PyQt4 import QtCore
     13  import OpenGL.GL as GL
     14  import OpenGL.GLU as GLU
     15  try:
     16      import cv2
     17  except:
     18      print("Warning: was not possible to import cv2 in ControlPlayer")
     19  from PyQt4.QtGui import QApplication
     20
     21  __author__ = "Ricardo Ribeiro"
     22  __credits__ = ["Ricardo Ribeiro"]
     23  __license__ = "MIT"
     24  __version__ = "0.0"
     25  __maintainer__ = "Ricardo Ribeiro"
     26  __email__ = "ricardojvr@gmail.com"
     27  __status__ = "Development"
     28
     29
     30 -class VideoGLWidget(QGLWidget):
     31
     32      image2Display = []
     33      texture = []
     34      _x = 0.0
     35      _y = 0.0
     36      zoom = 1.0
     37      _width = 1.0
     38      _height = 1.0
     39      _mouseX = 0.0
     40      _mouseY = 0.0
     41      _mouseDown = False
     42      _glX = 0.0
     43      _glY = 0.0
     44      _glZ = 0.0
     45      _lastGlX = 0.0
     46      _lastGlY = 0.0
     47
     48 -    def __init__(self, parent=None):
     49          QGLWidget.__init__(self, parent)
     50          self.image2Display = []
     51          self.texture = []
     52          self.setMouseTracking(True)
     53          self.zoom = 1.0
     54          self._mouseX = 0.0
     55          self._mouseY = 0.0
     56          self._glX = 0.0
     57          self._glY = 0.0
     58          self._glZ = 0.0
     59          self._lastGlX = 0.0
     60          self._lastGlY = 0.0
     61          self._mouseDown = False
     62          self._mouseLeftDown = False
     63          self._mouseRightDown = False
     64
     65          self._rotateZ = 0
     66          self._rotateX = 0
     67
     68          self._mouseStartDragPoint = None
     69          # Message to show on the left corner of the screen
     70          self._helpText = None
     71
     72          self.setMinimumHeight(100)
     73
     74          self._point = None
     75
     76 -    def initializeGL(self):
     77          GL.glClearDepth(1.0)
     78          GL.glClearColor(0, 0, 0, 1.0)
     79          GL.glEnable(GL.GL_DEPTH_TEST)
     80
     81 -    def resizeGL(self, width, height):
     82          GL.glViewport(0, 0, width, height)
     83          GL.glMatrixMode(GL.GL_PROJECTION)
     84          GL.glLoadIdentity()
     85          GLU.gluPerspective(40.0, float(width) / float(height), 0.01, 10.0)
     86
     87 -    def drawVideo(self, _width, _height, x, y, z):
     88          GL.glPushMatrix()
     89
     90          GL.glTranslatef(x, y, z)
     91          GL.glBegin(GL.GL_QUADS)
     92          GL.glTexCoord2f(0.0, 1.0)
     93          GL.glVertex3f(0, -_height / 2.0, 0)  # top left
     94          GL.glTexCoord2f(0.0, 0.0)
     95          GL.glVertex3f(0, _height / 2.0, 0)  # bottom left
     96          GL.glTexCoord2f(1.0, 0.0)
     97          GL.glVertex3f(_width, _height / 2.0, 0)  # bottom right
     98          GL.glTexCoord2f(1.0, 1.)
     99          GL.glVertex3f(_width, -_height / 2.0, 0)  # top right
    100          GL.glEnd()
    101          GL.glPopMatrix()
    102
    103 -    def drawPyramid(self, size=0.01):
    104          """Draw a multicolored pyramid"""
    105          GL.glBegin(GL.GL_TRIANGLES)
    106          GL.glVertex3f(0.0, size, 0.0)
    107          GL.glVertex3f(-size, -size, size)
    108          GL.glVertex3f(size, -size, size)
    109          GL.glVertex3f(0.0, size, 0.0)
    110          GL.glVertex3f(size, -size, size)
    111          GL.glVertex3f(size, -size, -size)
    112          GL.glVertex3f(0.0, size, 0.0)
    113          GL.glVertex3f(size, -size, -size)
    114          GL.glVertex3f(-size, -size, -size)
    115          GL.glVertex3f(0.0, size, 0.0)
    116          GL.glVertex3f(-size, -size, -size)
    117          GL.glVertex3f(-size, -size, size)
    118          GL.glEnd()
    119
    120 -    def paintGL(self):
    121          GL.glClearColor(0.5, 0.5, 0.5, 1.0)
    122          GL.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT)
    123          GL.glMatrixMode(GL.GL_MODELVIEW)
    124          GL.glLoadIdentity()
    125
    126          translateX = (len(self.texture) * self._width) / 2
    127
    128          if len(self.texture) > 0:
    129              GL.glTranslatef(-translateX, -self._height / 2, -self.zoom)
    130              GL.glTranslatef(0, self._height / 2.0, 0)
    131
    132              if self._point is not None:
    133                  GL.glColor4f(0, 0, 1, 1.0)
    134                  GL.glPushMatrix()
    135                  GL.glTranslatef(self._point[0], self._point[1], self._point[2])
    136                  self.drawPyramid()
    137                  GL.glPopMatrix()
    138                  GL.glColor4f(1, 1, 1, 1.0)
    139
    140              GL.glRotatef(self._rotateX, -1, 0, 0)
    141              GL.glRotatef(self._rotateZ, 0, 0, 1)
    142
    143              GL.glDisable(GL.GL_TEXTURE_2D)
    144              GL.glColor4f(0.5, 0.5, 0.5, 1.0)
    145              GL.glBegin(GL.GL_QUADS)
    146              GL.glVertex3f(20, -20, -.01)
    147              GL.glVertex3f(20, 20, -.001)
    148              GL.glVertex3f(-20, 20, -.001)
    149              GL.glVertex3f(-20, -20, -.001)
    150              GL.glEnd()
    151
    152              GL.glColor4f(1, 1, 1, 1.0)
    153
    154              if self._mouseDown:
    155                  modelview = GL.glGetDoublev(GL.GL_MODELVIEW_MATRIX)
    156                  projection = GL.glGetDoublev(GL.GL_PROJECTION_MATRIX)
    157                  viewport = GL.glGetIntegerv(GL.GL_VIEWPORT)
    158                  winX = float(self._mouseX)
    159                  winY = float(viewport[3] - self._mouseY)
    160                  winZ = GL.glReadPixels(
    161                      winX, winY, 1, 1, GL.GL_DEPTH_COMPONENT, GL.GL_FLOAT)
    162                  self._glX, self._glY, self._glZ = GLU.gluUnProject(
    163                      winX, winY, winZ[0][0], modelview, projection, viewport)
    164
    165              GL.glEnable(GL.GL_TEXTURE_2D)
    166              GL.glDisable(GL.GL_DEPTH_TEST)
    167
    168              for texture_index in range(0, len(self.texture)):
    169                  if texture_index > 0:
    170                      GL.glTranslatef(self._width,  0, 0)
    171
    172                  GL.glBindTexture(GL.GL_TEXTURE_2D, self.texture[texture_index])
    173
    174                  if self._mouseRightDown:
    175                      self.drawVideo(self._width, self._height, self._x - (
    176                          self._lastGlX - self._glX), self._y - (self._lastGlY - self._glY), 0.0)
    177                  else:
    178                      self.drawVideo(
    179                          self._width, self._height, self._x, self._y, 0.0)
    180
    181              GL.glEnable(GL.GL_DEPTH_TEST)
    182
    183          if self._helpText is not None:
    184              self.qglColor(QtCore.Qt.white)
    185              self.renderText(4, 15, self._helpText)
    186
    187 -    def reset(self):
    188          self.texture = []
    189          self.image2Display = []
    190
    191 -    def paint(self, frames):
    192
    193          if len(self.image2Display) == 0:
    194              self.imgHeight, self.imgWidth = frames[0].shape[:2]
    195              if self.imgWidth > self.imgHeight:
    196                  self._width = 1
    197                  self._height = float(self.imgHeight) / float(self.imgWidth)
    198                  self._x = -float(self._width) / 2
    199                  self._y = 0
    200              else:
    201                  self._height = 1
    202                  self._width = float(self.imgWidth) / float(self.imgHeight)
    203                  self._y = 0.5
    204
    205          # self._x = -self._width/2
    206
    207          if len(self.texture) > len(frames):
    208              for i in range(len(self.texture) - len(frames)):
    209                  GL.glDeleteTextures(self.texture.pop())
    210
    211          self.image2Display = frames
    212
    213          for index, frame in enumerate(frames):
    214              if len(frame.shape) == 2:
    215                  color = GL.GL_LUMINANCE
    216              else:
    217                  color = GL.GL_BGR
    218
    219              if len(self.texture) < len(self.image2Display):
    220                  self.texture.append(GL.glGenTextures(1))
    221
    222              w = len(frame[0])
    223              h = len(frame)
    224
    225              GL.glEnable(GL.GL_TEXTURE_2D)
    226              GL.glPixelStorei(GL.GL_UNPACK_ALIGNMENT, 1)
    227              GL.glBindTexture(GL.GL_TEXTURE_2D, self.texture[index])
    228              GL.glTexParameterf(
    229                  GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_S, GL.GL_CLAMP_TO_BORDER)
    230              GL.glTexParameterf(
    231                  GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_T, GL.GL_CLAMP_TO_BORDER)
    232              GL.glTexParameterf(
    233                  GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR)
    234              GL.glTexParameterf(
    235                  GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR)
    236              GL.glTexImage2D(
    237                  GL.GL_TEXTURE_2D, 0, GL.GL_RGB, w, h, 0, color, GL.GL_UNSIGNED_BYTE, frame)
    238
    239          self.repaint()
    240
    241 -    def wheelEvent(self, event):
    242          if event.delta() < 0:
    243              self.zoom += 0.1
    244          else:
    245              self.zoom -= 0.1
    246          if self.zoom < 0.01:
    247              self.zoom = 0.02
    248          self.repaint()
    249
    250 -    def mouseDoubleClickEvent(self, event):
    251          self._mouseX = event.x()
    252          self._mouseY = event.y()
    253          self.repaint()
    254          if hasattr(self, 'imgWidth'):
    255              self.onDoubleClick(event, (self._glX - self._x) * float(self.imgWidth),
    256                                 (self._height - self._glY + self._y) * float(self.imgWidth) - self.imgHeight / 2.0)
    257
    258 -    def mouseReleaseEvent(self, event):
    259          self._mouseDown = False
    260
    261          if event.button() == 4:
    262              self._mouseRightDown = False
    263              self._x -= self._lastGlX - self._glX
    264              self._y -= self._lastGlY - self._glY
    265              self._lastGlX = self._glX
    266              self._lastGlY = self._glY
    267
    268          if event.button() == 1:
    269              if hasattr(self, 'imgWidth') and self._mouseLeftDown:
    270                  self.onEndDrag(self._mouseStartDragPoint, ((self._glX - self._x) * float(self.imgWidth),
    271                                                             (self._height - self._glY + self._y) * float(self.imgWidth) - self.imgHeight / 2.0))
    272              self._mouseLeftDown = False
    273
    274 -    def mousePressEvent(self, event):
    275          super(QGLWidget, self).mousePressEvent(event)
    276          self.setFocus(QtCore.Qt.MouseFocusReason)
    277
    278          self._mouseDown = True
    279          self._mouseX = event.x()
    280          self._mouseY = event.y()
    281          self.repaint()
    282
    283          if hasattr(self, 'imgWidth'):
    284              self.onClick(event, (self._glX - self._x) * float(self.imgWidth),
    285                           (self._height - self._glY + self._y) * float(self.imgWidth) - self.imgHeight / 2.0)
    286
    287          if event.button() == 1:
    288              self._mouseLeftDown = True
    289              self._mouseStartDragPoint = (
    290                  self._glX - self._x, self._height - self._glY + self._y)
    291
    292          if event.button() == 4:
    293              self._mouseRightDown = True
    294              self._lastGlX = self._glX
    295              self._lastGlY = self._glY
    296
    297 -    def mouseMoveEvent(self, event):
    298          self._mouseX = event.x()
    299          self._mouseY = event.y()
    300          self.repaint()
    301          if self._mouseLeftDown and self._mouseDown:
    302              self.onDrag(self._mouseStartDragPoint, ((self._glX - self._x) * float(self.imgWidth),
    303                                                      (self._height - self._glY + self._y) * float(self.imgWidth) - self.imgHeight / 2.0))
    304
    305 -    def keyReleaseEvent(self, event):
    306          super(QGLWidget, self).keyReleaseEvent(event)
    307          # Control video playback using the space bar to Play/Pause
    308          if event.key() == QtCore.Qt.Key_Space:
    309              self._control.pausePlay()
    310          # Jumps 1 frame forward
    311          if event.key() == QtCore.Qt.Key_D:
    312              self._control.video_index += 1
    313              self._control.updateFrame()
    314
    315          # Jumps 1 frame backwards
    316          if event.key() == QtCore.Qt.Key_A:
    317              self._control.video_index -= 1
    318              self._control.updateFrame()
    319
    320          self.onKeyRelease(event)
    321
    322 -    def onDoubleClick(self, event, x, y): pass
    323
    324 -    def onClick(self, event, x, y): pass
    325
    326 -    def onDrag(self, startPoint, endPoint): pass
    327
    328 -    def onEndDrag(self, startPoint, endPoint): pass
    329
    330 -    def onKeyRelease(self, event): pass
    331
    332      @property
    333 -    def rotateX(self): return self._rotateX
    334
    335      @rotateX.setter
    336 -    def rotateX(self, value):
    337          self._rotateX = value
    338          self.repaint()
    339
    340      @property
    341 -    def rotateZ(self): return self._rotateZ
    342
    343      @rotateZ.setter
    344 -    def rotateZ(self, value):
    345          self._rotateZ = value
    346          self.repaint()
    347
    348      @property
    349 -    def point(self): return self._point
    350
    351      @point.setter
    352 -    def point(self, value):
    353          if hasattr(self, 'imgWidth'):
    354              x = value[0] / float(self.imgWidth)  # +self._x
    355              y = -value[1] / float(self.imgWidth)  # -self._y-self._height)
    356              z = 0.1  # value[2]
    357              self._point = x, y, z
    358