Skip to content

Instantly share code, notes, and snippets.

@mwgamera
Forked from adepasquale/image2spectrogram.py
Last active August 29, 2015 14:05
Show Gist options
  • Save mwgamera/7e0e7342d7bd19480eb2 to your computer and use it in GitHub Desktop.
Save mwgamera/7e0e7342d7bd19480eb2 to your computer and use it in GitHub Desktop.
#!/usr/bin/python
import cv2
import numpy as np
import wave
import struct
import sys
# usage instructions:
# ./image2spectrogram.py input.png
# sox output.wav -n spectrogram -m -o output.png
image = cv2.imread(sys.argv[1], flags=cv2.CV_LOAD_IMAGE_GRAYSCALE)
height, width = image.shape
def merge(blocks):
length = len(blocks[0])
window = np.sin([np.pi*i/length for i in range(0, length)]) ** 2
signal = np.zeros((len(blocks)-1) * (length // 2) + length)
for i in range(0, len(blocks)):
base = i * (length // 2)
signal[base:base+length] += blocks[i] * window
return signal
def imgcol2block(pixels, gamma=4.0):
pixels = (pixels / 256.) ** gamma
# randomly decorrelate phases so we have nice low level noise rather than concentrated peaks
pixels = pixels * np.exp((np.random.random(len(pixels))-0.5) * 2j * np.pi)
#samples = np.real(np.fft.ifft(np.concatenate(([0], pixels, np.conjugate(pixels[:1:-1])))[::2]))
samples = np.real(np.fft.ifft(pixels))
return samples
def autogain(samples):
peak = np.maximum.reduce(np.abs(samples))
if peak > 0:
samples = samples / peak
return samples
blocks = []
for i in range(0, width):
column = image[:, i]
flipped = np.flipud(column)
window = np.hstack((flipped[:-1], column))
blocks.append(imgcol2block(window))
samples = []
for sample in np.int32(2**31 * autogain(merge(blocks))):
samples.append(struct.pack('i', sample))
output = wave.open('output.wav', 'w')
output.setparams((1, 4, 44100, 0, 'NONE', 'not compressed'))
output.writeframes(''.join(samples))
output.close()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment