Skip to content

Instantly share code, notes, and snippets.

@cgobat
Last active February 22, 2024 15:31
Show Gist options
  • Save cgobat/1da61e71074b99f8a47ca0f7ade5ec68 to your computer and use it in GitHub Desktop.
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
#######################################################
#
# 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)
#######################################################
#
# 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
#######################################################
#
# 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