forked from geeksville/hummingbot
/
hummingbot.py
executable file
·94 lines (75 loc) · 3.36 KB
/
hummingbot.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
#!/usr/bin/env python3
"""Hummingbot
A simple twitterbot that tweets Google AIY-Vision machine vision
photos when it thinks it sees a hummingbird.
"""
import tweeter
import datetime
from aiy.vision.inference import CameraInference
from aiy.vision.models import image_classification
from picamera import PiCamera
# For debugging purposes we track what types of things we have seen (and how many)
oldclasses = set()
# if true we don't actually upload to twitter
testing = False
# a date in the far past
lasttime = datetime.datetime.min
# we only tweet once every 30 mins max
maxdelta = datetime.timedelta(minutes = 30)
# "obelisk",
# "apiary", "mosquito", "shovel", "altar", "ladle", "banana",
interesting = [ "humming", "finch", "macaw", "hornbill" ]
def classes_info(classes, count):
return ', '.join('%s (%.2f)' % pair for pair in classes)
# 0.02 was too low, 0.03 pretty good
threshold = 0.05
def removeold(pair):
"""given a list of google vision match pairs, return true if we think this frame is interesting"""
global oldclasses, threshold
hasbird = list(filter(lambda canidate: (canidate in pair[0]), interesting))
if pair[0] not in oldclasses and float(pair[1]) > threshold:
if not hasbird:
oldclasses.add(pair[0])
return True
else:
return False
def main():
global count
global lasttime
global testing
num_frames = None
num_objects = 8 # just for debug printing
# Forced sensor mode, 1640x1232, full FoV. use mode 4, was using frame rate of 10
# https://picamera.readthedocs.io/en/release-1.13/fov.html#sensor-modes
# kevinh 3280x2464 is mode 3 (but that is too large for twitter)
with PiCamera(sensor_mode=4, framerate=3) as camera:
camera.awb_mode = 'sunlight'
camera.exposure_mode = 'sports'
# if out of memory err occurs see https://stackoverflow.com/questions/39251815/python-not-taking-picture-at-highest-resolution-from-raspberry-pi-camera
camera.resolution = (1920, 1080)
with CameraInference(image_classification.model(image_classification.MOBILENET)) as inference:
for result in inference.run(num_frames):
classes = image_classification.get_classes(result)
newclasses = list(filter(removeold, classes))
if newclasses:
print(classes_info(newclasses, num_objects))
name = newclasses[0][0]
filename = name.replace("/","_").replace(" ", ".")
hasbird = list(filter(lambda canidate: (canidate in name), interesting))
filename += ".jpg"
# print('writing', filename)
if hasbird:
camera.capture(filename) # the twitter client only reads from disk (for now FIXME)
now = datetime.datetime.now()
deltat = now - lasttime
if deltat > maxdelta:
lasttime = now
if not testing:
tweeter.tweet(filename, 'I just saw a hummingbird! tweet tweet!')
print('tweet a bird')
else:
print('test a bird')
else:
print('ignore a bird')
if __name__ == '__main__':
main()