images2avi.py 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. # Copyright (C) 2012, Almar Klein
  2. # All rights reserved.
  3. #
  4. # This code is subject to the (new) BSD license:
  5. #
  6. # Redistribution and use in source and binary forms, with or without
  7. # modification, are permitted provided that the following conditions are met:
  8. # * Redistributions of source code must retain the above copyright
  9. # notice, this list of conditions and the following disclaimer.
  10. # * Redistributions in binary form must reproduce the above copyright
  11. # notice, this list of conditions and the following disclaimer in the
  12. # documentation and/or other materials provided with the distribution.
  13. # * Neither the name of the <organization> nor the
  14. # names of its contributors may be used to endorse or promote products
  15. # derived from this software without specific prior written permission.
  16. #
  17. # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  18. # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  19. # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  20. # ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
  21. # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  22. # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  23. # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  24. # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  25. # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  26. # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27. #
  28. #
  29. # changes of this file GRASS (PNG instead of JPG) by Anna Petrasova 2013
  30. """ Module images2avi
  31. Uses ffmpeg to read and write AVI files. Requires PIL
  32. I found these sites useful:
  33. http://www.catswhocode.com/blog/19-ffmpeg-commands-for-all-needs
  34. http://linux.die.net/man/1/ffmpeg
  35. """
  36. import os
  37. import time
  38. import subprocess
  39. import shutil
  40. from grass.imaging import images2ims
  41. def _cleanDir(tempDir):
  42. for i in range(3):
  43. try:
  44. shutil.rmtree(tempDir)
  45. except Exception:
  46. time.sleep(0.2) # Give OS time to free sources
  47. else:
  48. break
  49. else:
  50. print("Oops, could not fully clean up temporary files.")
  51. def writeAvi(filename, images, duration=0.1, encoding='mpeg4',
  52. inputOptions='', outputOptions=''):
  53. """Export movie to a AVI file, which is encoded with the given
  54. encoding. Hint for Windows users: the 'msmpeg4v2' codec is
  55. natively supported on Windows.
  56. Images should be a list consisting of PIL images or numpy arrays.
  57. The latter should be between 0 and 255 for integer types, and
  58. between 0 and 1 for float types.
  59. Requires the "ffmpeg" application:
  60. * Most linux users can install using their package manager
  61. * There is a windows installer on the visvis website
  62. :param str filename: output filename
  63. :param images:
  64. :param float duration:
  65. :param str encoding: the encoding type
  66. :param inputOptions:
  67. :param outputOptions:
  68. """
  69. # Get fps
  70. try:
  71. fps = float(1.0/duration)
  72. except Exception:
  73. raise ValueError("Invalid duration parameter for writeAvi.")
  74. # Determine temp dir and create images
  75. tempDir = os.path.join(os.path.expanduser('~'), '.tempIms')
  76. images2ims.writeIms(os.path.join(tempDir, 'im*.png'), images)
  77. # Determine formatter
  78. N = len(images)
  79. formatter = '%04d'
  80. if N < 10:
  81. formatter = '%d'
  82. elif N < 100:
  83. formatter = '%02d'
  84. elif N < 1000:
  85. formatter = '%03d'
  86. # Compile command to create avi
  87. command = "ffmpeg -r %i %s " % (int(fps), inputOptions)
  88. command += "-i im%s.png " % (formatter,)
  89. command += "-g 1 -vcodec %s %s " % (encoding, outputOptions)
  90. command += "output.avi"
  91. # Run ffmpeg
  92. S = subprocess.Popen(command, shell=True, cwd=tempDir,
  93. stdout=subprocess.PIPE, stderr=subprocess.PIPE)
  94. # Show what ffmpeg has to say
  95. outPut = S.stdout.read()
  96. if S.wait():
  97. # An error occurred, show
  98. print(outPut)
  99. print(S.stderr.read())
  100. # Clean up
  101. _cleanDir(tempDir)
  102. raise RuntimeError("Could not write avi.")
  103. else:
  104. # Copy avi
  105. shutil.copy(os.path.join(tempDir, 'output.avi'), filename)
  106. # Clean up
  107. _cleanDir(tempDir)
  108. def readAvi(filename, asNumpy=True):
  109. """Read images from an AVI (or MPG) movie.
  110. Requires the "ffmpeg" application:
  111. * Most linux users can install using their package manager
  112. * There is a windows installer on the visvis website
  113. :param str filename: name of input movie file
  114. :param bool asNumpy:
  115. """
  116. # Check whether it exists
  117. if not os.path.isfile(filename):
  118. raise IOError('File not found: '+str(filename))
  119. # Determine temp dir, make sure it exists
  120. tempDir = os.path.join(os.path.expanduser('~'), '.tempIms')
  121. if not os.path.isdir(tempDir):
  122. os.makedirs(tempDir)
  123. # Copy movie there
  124. shutil.copy(filename, os.path.join(tempDir, 'input.avi'))
  125. # Run ffmpeg
  126. command = "ffmpeg -i input.avi im%d.jpg"
  127. S = subprocess.Popen(command, shell=True, cwd=tempDir,
  128. stdout=subprocess.PIPE, stderr=subprocess.PIPE)
  129. # Show what mencodec has to say
  130. outPut = S.stdout.read()
  131. if S.wait():
  132. # An error occurred, show
  133. print(outPut)
  134. print(S.stderr.read())
  135. # Clean up
  136. _cleanDir(tempDir)
  137. raise RuntimeError("Could not read avi.")
  138. else:
  139. # Read images
  140. images = images2ims.readIms(os.path.join(tempDir, 'im*.jpg'), asNumpy)
  141. # Clean up
  142. _cleanDir(tempDir)
  143. # Done
  144. return images