I am trying to clean up and make the following code more efficient -
https://gist.github.com/eWizardII/6757364
from PIL import Image
import numpy as np
from PIL import ImageChops
import subprocess
import math
import datetime
from PIL import ImageFont
from PIL import ImageDraw
from collections import deque
def image_entropy(prev, curr, smasumm, values):
im1 = Image.open(prev)
im2 = Image.open(curr)
img = ImageChops.difference(im1, im2)
w, h = img.size
a = np.array(img.convert('RGB')).reshape((w * h, 3))
h, e = np.histogramdd(a, bins=(16,) * 3, range=((0, 256),) * 3)
prob = h / np.sum(h) # normalize
prob = prob[prob > 0] # remove zeros
comp = -np.sum(prob * np.log2(prob))
framsd = SD(values, smasumm)
information = 'ENT: ' + str('{0:.2f}'.format(comp)) + ' SMA: ' + str('{0:.2f}'.format(smasumm)) + ' LB: ' + str(
'{0:.2f}'.format(smasumm - framsd)) + ' UB: ' + str('{0:.2f}'.format(smasumm + framsd))
cimg = Image.open(curr)
draw = ImageDraw.Draw(cimg)
font = ImageFont.truetype("arial.ttf", 24)
draw.text((0, 0), information, (0, 255, 0), font=font)
cimg.save(curr)
return comp
def SD(values, mean):
size = len(values)
sumsd = 0.0
for n in range(0, size):
sumsd += math.sqrt((values[n] - mean) ** 2)
return math.sqrt((1.0 / (size - 1)) * (sumsd / size))
try:
print "Initial Image ..."
time = datetime.datetime.now()
filename = "image_"
subprocess.call(
"raspistill -t 1000 -ex night -awb auto -w 720 -h 480 -o %s" % filename + '1.jpg',
shell=True)
prev = filename + '1.jpg'
i = 1
summ = smasumm = 0.0
period = n = 10
values = deque([0.0] * period)
while True:
time = datetime.datetime.now()
filename = "image_" + str(i) + ".jpg"
subprocess.call(
"raspistill -t 1000 -ex night -awb auto -w 720 -h 480 -o %s" % filename,
shell=True)
i += 1
curr = filename
sma = image_entropy(prev, curr, smasumm, values)
values.append(sma)
summ += sma - values.popleft()
smasumm = summ / n
prev = curr
print(datetime.datetime.now() - time)
except KeyboardInterrupt:
print " Quit"
I believe my biggest bottleneck is in using the subprocess.call in Python but I don't know of any way to improve up such a call - in the long run when I know the program works properly I'll try and transition to Java/C; but this is easier for my immediate application and debugging. Any help or advice would be appreciated thanks in addition to any improvements in the other aspects of the code.
1 Answer 1
I don't know about "more efficient", but here are some hints and tips that will help you clean up the code and make it more readable:
Style remarks
- My style checker asks for at least 2 spaces before an inline comment (lines 20-21). I don't think it's a bad idea.
- According to PEP8, you should keep your lines shorter than 80 characters (lines 24, 25 and 49).
This line is not very clear.
information = 'ENT: ' + str('{0:.2f}'.format(comp)) + ' SMA: ' + str('{0:.2f}'.format(smasumm)) + ' LB: ' + str( '{0:.2f}'.format(smasumm - framsd)) + ' UB: ' + str('{0:.2f}'.format(smasumm + framsd))
It would be a lot clearer to rewrite it like this:
'ENT: {0:.2f} SMA: {0:.2f} LB: {0:.2f} UB: {0:.2f}'.format(
comp, smasumm, smasumm - framsd, smasumm + framsd)
- Avoid one letter variable names (and other cryptic names like smasumm, because they're not descriptive and it's not immediately obvious what they represent.
- The lack of comments makes it difficult to follow what you're trying to do. You should use docstrings to write a small paragraph that provides an explanation of what you're trying to do.
- Again according to PEP8:
Imports should be grouped in the following order:
standard library imports
related third party imports
local application/library specific imports
So you want to replace your imports with this:
from collections import deque
import datetime
import math
import subprocess
import numpy as np
from PIL import Image
from PIL import ImageChops
from PIL import ImageDraw
from PIL import ImageFont
- Why do you alias
numpyasnp? It's not very readable. I'd rather readnumpyin full letters each time.
-
1\$\begingroup\$ Re: aliasing
numpyasnp: this is the standard alias, and is used throughout thenumpysource itself. It's also used byscipy,matplotlib,pandas, etc., pretty much everything on the stack. \$\endgroup\$DSM– DSM2013年09月30日 20:49:46 +00:00Commented Sep 30, 2013 at 20:49