sam1902

SpectroGen Smiley

Nov 2nd, 2018
184
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 5.90 KB | None | 0 0
  1. import wave, struct, math # To calculate the WAV file content
  2. import numpy as np # To handle matrices
  3. from PIL import Image # To open the input image and convert it to grayscale
  4.  
  5. import scipy.ndimage # To resample using nearest neighbour
  6.  
  7. def imageProcessing(imgArr):
  8.     # Invert filter
  9.     #imgArr = 1 - imgArr
  10.     return imgArr
  11.  
  12. '''
  13.    Loads a picture, converts it to greyscale, then to numpy array, normalise it so that the max value is 1
  14.    the min is 0, increase the contrast a bit, remove every pixel which intensity is lower that 0.5,
  15.    then resize the picture using nearest neighbour resampling and outputs the numpy matrix.
  16.    
  17.    FYI: imgArr[0,0] is the top left corner of the image, cheers matrix indexing
  18.    
  19.    Returns: the resized image as a high contrast, normalised between 0 and 1, numpy matrix
  20. '''
  21. def loadPicture(size, file, verbose=1):
  22.     img = Image.open(file)
  23.     img = img.convert("L")
  24.     #img = img.resize(size) # DO NOT DO THAT OR THE PC WILL CRASH
  25.    
  26.     imgArr = np.array(img)
  27.     imgArr = np.flip(imgArr, axis=0)
  28.     if verbose:
  29.         print("Image original size: ", imgArr.shape)
  30.        
  31.     # Scale between 0 and 1
  32.     imgArr -= np.min(imgArr)
  33.     imgArr = imgArr/np.max(imgArr)
  34.  
  35.     # Processes the image before down sampling
  36.     imgArr = imageProcessing(imgArr)
  37.    
  38.     if size[0] == 0:
  39.         size = imgArr.shape[0], size[1]
  40.     if size[1] == 0:
  41.         size = size[0], imgArr.shape[1]
  42.     resamplingFactor = size[0]/imgArr.shape[0], size[1]/imgArr.shape[1]
  43.     if resamplingFactor[0] == 0:
  44.         resamplingFactor = 1, resamplingFactor[1]
  45.     if resamplingFactor[1] == 0:
  46.         resamplingFactor = resamplingFactor[0], 1
  47.    
  48.     # Order : 0=nearestNeighbour, 1:bilinear, 2:cubic etc...
  49.     imgArr = scipy.ndimage.zoom(imgArr, resamplingFactor, order=0)
  50.    
  51.     if verbose:
  52.         print("Resampling factor", resamplingFactor)
  53.         print("Image resized :", imgArr.shape)
  54.         print("Max intensity: ", np.max(imgArr))
  55.         print("Min intensity: ", np.min(imgArr))
  56.     return imgArr
  57.  
  58. def genSoundFromImage(file, output="sound.wav", duration=2.5, sampleRate=44100.0, min_freq=0, max_freq=22000, stepSize=100, substepSize=250, verbose=False):
  59.     wavef = wave.open(output,'w')
  60.     wavef.setnchannels(1) # mono
  61.     wavef.setsampwidth(2)
  62.     wavef.setframerate(sampleRate)
  63.    
  64.     max_frame = int(duration * sampleRate)
  65.     max_intensity = 32767 # Defined by WAV
  66.    
  67.     steppingSpectrum = int((max_freq-min_freq)/stepSize)
  68.    
  69.     imgMat = loadPicture(size=(steppingSpectrum, max_frame), file=file, verbose=verbose)
  70.  
  71.     imgMat *= max_intensity # To scale it to max WAV audio intensity
  72.     if verbose:
  73.         print("Input: ", file)
  74.         print("Duration (in seconds): ", duration)
  75.         print("Sample rate: ", sampleRate)
  76.         print("Computing each soundframe sum value..")
  77.     for frame in range(max_frame):
  78.         if frame % 120 == 0: # Only print once in a while
  79.             print("Progress: ==> {:.2%}".format(frame/max_frame), end="\r")
  80.         signalValue, count = 0, 0
  81.         for step in range(steppingSpectrum):
  82.             intensity = imgMat[step, frame]
  83.             # nextFreq is less than currentFreq
  84.             currentFreq = (step * stepSize) + min_freq
  85.             nextFreq = ((step+1) * stepSize) + min_freq
  86.             if nextFreq - min_freq > max_freq: # If we're at the end of the spectrum
  87.                 nextFreq = max_freq
  88.             for freq in range(currentFreq, nextFreq, substepSize):
  89.                 signalValue += intensity*math.cos(freq * 2 * math.pi * float(frame) / float(sampleRate))
  90.                 count += 1
  91.         if count == 0: count = 1
  92.         signalValue /= count
  93.        
  94.         data = struct.pack('<h', int(signalValue))
  95.         wavef.writeframesraw( data )
  96.        
  97.     wavef.writeframes(''.encode())
  98.     wavef.close()
  99.     print("\nProgress: ==> 100%")
  100.     if verbose:
  101.         print("Output: ", output)
  102.  
  103. import sys
  104. import argparse
  105.  
  106. def main(argv):
  107.     parser = argparse.ArgumentParser()
  108.     parser.add_argument("inputImage", help="Input image in any PIL supported format (JPG, PNG (with and without alpha), BMP etc...)")
  109.     parser.add_argument("outputFile", help="path where to output the soundfile in WAV format")
  110.     parser.add_argument("-d", "--duration", help="Duration of the sound to output, in whole seconds, default: 2.5", type=int)
  111.     parser.add_argument("-n", "--minFreq", help="Minimum frequency to use, in Hz, default: 0", type=int)
  112.     parser.add_argument("-x", "--maxFreq", help="Maximum frequency to use, in Hz, default: 22000", type=int)
  113.     parser.add_argument("-s", "--samplerate", help="Sample rate of the sound to output, in Hertz, default: 44100", type=int)
  114.     parser.add_argument("-ss", "--stepsize", help="Each pixel's portion of the spectrum, in Hertz, default: 100", type=int)
  115.     parser.add_argument("-sss", "--substepsize", help="Step between frequencies generated in between two others, in Hertz, default: 250", type=int)
  116.     parser.add_argument("-v", "--verbose", help="Display verbose", action="store_true")
  117.     args = parser.parse_args()
  118.    
  119.     img = args.inputImage
  120.     output = args.outputFile
  121.     duration = 2.5 if not args.duration else args.duration
  122.     min_freq = 0 if not args.minFreq else args.minFreq
  123.     max_freq = 22000 if not args.maxFreq else args.maxFreq
  124.     sampleRate = 44100 if not args.samplerate else args.samplerate
  125.     stepSize = 100 if not args.stepsize else args.stepsize
  126.     substepSize = 250 if not args.substepsize else args.substepsize
  127.     verbose = args.verbose
  128.  
  129.     genSoundFromImage(
  130.             file=img,
  131.             output=output,
  132.             duration=duration,
  133.             sampleRate=sampleRate,
  134.             min_freq=min_freq,
  135.             max_freq=max_freq,
  136.             stepSize=stepSize,
  137.             substepSize=substepSize,
  138.             verbose=verbose)
  139.  
  140. if __name__ == "__main__":
  141.     main(sys.argv[1:])
Advertisement
Add Comment
Please, Sign In to add comment