Last active
February 22, 2024 15:31
-
-
Save cgobat/1da61e71074b99f8a47ca0f7ade5ec68 to your computer and use it in GitHub Desktop.
Software for Raspberry Pi to capture and overlay data from an AMG8833 infrared thermal camera with images from the RPi optical camera
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
####################################################### | |
# | |
# Thermal/optical camera overlay (main program) | |
# | |
# by Caden Gobat | |
# PHYS 2152 | The George Washington University | |
# | |
####################################################### | |
from datetime import datetime | |
import numpy as np, time, matplotlib.pyplot as plt | |
from optical_cam import capture_optical | |
from IR_cam import capture_thermal | |
if __name__ == "__main__": | |
px_dim = 256 | |
XX,YY = np.meshgrid(np.arange(0,px_dim,1),np.arange(0,px_dim,1)) | |
# edit these values based on physical positions of the cameras relative to one another | |
x_shift = -30 | |
y_shift = 10 | |
with open("./timeseries/datafile.csv","w+") as file: | |
file.write("ID, Timestamp, Ambient temp") | |
for i in range(3): | |
image_arr = np.rot90(capture_optical(),2,(0,1)) | |
therm,temp = capture_thermal(interp_dim=(px_dim,px_dim), return_ambient=True) | |
fig,ax = plt.subplots(figsize=(10,9),num="Camera overlay") | |
ax.set(xticks=[],yticks=[]) | |
img = ax.imshow(image_arr) | |
tcont = ax.contour(XX+x_shift,YY+y_shift,therm-temp,cmap="hot") | |
#cbar = fig.colorbar(tcont,label="Temperature above/below ambient") | |
ts = datetime.now() | |
fig.savefig(f"./timeseries/ID-{i+1}.png",bbox_inches="tight",dpi=300) | |
np.savetxt(f"./timeseries/ID-{i+1}",therm) | |
print("captured/saved image",i+1) | |
with open("./timeseries/datafile.csv","a") as file: | |
file.write(f"\n{i+1}, {ts}, {temp}") | |
time.sleep(0.5) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
####################################################### | |
# | |
# Thermal camera display for AMG8833 IR camera | |
# | |
# by Caden Gobat | |
# PHYS 2152 | The George Washington University | |
# | |
####################################################### | |
import time, sys | |
import numpy as np | |
import matplotlib.pyplot as plt | |
from scipy import interpolate | |
from amg8833_i2c import AMG8833 | |
# initialize AMG8833 sensor | |
t0 = time.time() | |
sensor = None | |
while (time.time()-t0)<1: # wait 1sec for sensor to start | |
try: | |
sensor = AMG8833(addr=0x68) # start AMG8833 | |
except: | |
sensor = AMG8833(addr=0x69) | |
finally: | |
pass | |
time.sleep(0.1) # wait for sensor to settle | |
if not sensor: | |
print("Thermal camera not found.") | |
sys.exit(); | |
pix_res = (8,8) # sensor pixel resolution | |
xx,yy = (np.linspace(0,pix_res[0],pix_res[0]), | |
np.linspace(0,pix_res[1],pix_res[1])) | |
zz = np.random.random(pix_res) # initialize array | |
# new resolution | |
pix_mult = 6 # multiplier for interpolation | |
interp_res = (int(pix_mult*pix_res[0]),int(pix_mult*pix_res[1])) | |
grid_x,grid_y = (np.linspace(0,pix_res[0],interp_res[0]), | |
np.linspace(0,pix_res[1],interp_res[1])) | |
# interpolation function | |
def interp(z_var,grid=(grid_x,grid_y)): | |
# new resolution will be (8*pix_mult x 8*pix_mult) | |
f = interpolate.interp2d(xx,yy,z_var,kind='cubic') | |
return f(grid[0],grid[1]) | |
grid_z = interp(zz) # interpolated image | |
def capture_thermal(interp_dim=(8,8),return_ambient=False): | |
status,pixels = sensor.read_temp(64) # read all 64 pixels with status | |
if status: # if error in pixel, re-enter loop and try again | |
print(status) | |
return None | |
interp_grid = (np.linspace(0,8,interp_dim[0]), | |
np.linspace(0,8,interp_dim[1])) | |
if return_ambient: | |
T = sensor.read_thermistor() | |
return interp(np.reshape(pixels,(8,8)),grid=interp_grid), T | |
else: | |
return interp(np.reshape(pixels,(8,8)),grid=interp_grid) | |
# real-time sensor reading | |
if __name__ == "__main__": | |
# matplotlib display setup | |
plt.rcParams.update({'font.size':16}) | |
fig_dims = (10,9) # figure size | |
fig,ax = plt.subplots(figsize=fig_dims,num="AMG8833 thermal camera") # start figure | |
ax.set(xticks=[],yticks=[]) | |
im1 = ax.imshow(grid_z,cmap=plt.cm.RdBu_r,vmin=16,vmax=30) # plot image, with temperature bounds | |
cbar = fig.colorbar(im1,fraction=0.0475,pad=0.03) # colorbar for scale | |
cbar.set_label('Temperature [°C]',labelpad=10) | |
fig.canvas.draw() # draw figure | |
ax_bgnd = fig.canvas.copy_from_bbox(ax.bbox) # background for speeding up runs | |
fig.show() # show figure | |
while True: | |
status,pixels = sensor.read_temp(64) # read all 64 pixels with status | |
if status: # if error in pixel, re-enter loop and try again | |
print(status) | |
continue | |
T_thermistor = sensor.read_thermistor() # read thermistor temp (ambient) | |
fig.canvas.restore_region(ax_bgnd) # restore background (speeds up run) | |
new_z = interp(np.reshape(pixels,pix_res)) # interpolated thermal image | |
im1.set_data(new_z) # update image object with new data | |
ax.draw_artist(im1) # redraw image | |
fig.canvas.blit(ax.bbox) # blitting - for speeding up run | |
fig.canvas.flush_events() # for real-time plot |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
####################################################### | |
# | |
# Optical camera display for Raspberry Pi camera | |
# | |
# by Caden Gobat | |
# PHYS 2152 | The George Washington University | |
# | |
####################################################### | |
import time | |
import picamera | |
import numpy as np | |
import matplotlib.pyplot as plt | |
camera = picamera.PiCamera() | |
camera.resolution = (256, 256) | |
camera.framerate = 24 | |
time.sleep(2) | |
output = np.empty((256, 256, 3), dtype=np.uint8) | |
def capture_optical(): | |
output = np.empty((256,256,3), dtype=np.uint8) | |
camera.capture(output,'rgb') | |
return output | |
if __name__ == "__main__": | |
plt.rcParams.update({'font.size':16}) | |
fig,ax = plt.subplots(figsize=(10,9),num="PiCamera") # start figure | |
ax.set(xticks=[],yticks=[]) | |
#plt.set_window_title('PiCamera') | |
im1 = ax.imshow(output) # plot image | |
fig.canvas.draw() # draw figure | |
ax_bgnd = fig.canvas.copy_from_bbox(ax.bbox) # background for speeding up runs | |
fig.show() # show figure | |
while True: | |
camera.capture(output, 'rgb') | |
fig.canvas.restore_region(ax_bgnd) # restore background (speeds up run) | |
im1.set_data(output) # update plot with new interpolated temps | |
ax.draw_artist(im1) # draw image again | |
fig.canvas.blit(ax.bbox) # blitting - for speeding up run | |
fig.canvas.flush_events() # for real-time plot |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment