Camera mount
As I already mentioned last week I manufactured a camera mount, where the Raspberry Pi camera and the Panasonic Grid-Eye sensor are mounted close together. Here is again the foto of the installation:
The idea was to overlay the image of the camera and the temperature sensor to 1. get an image with temperature information which is very nice to view and to 2. get information how good the sensors are aligned.
Matching the images together
The grid-eye sensor has an viewing angle of 60 degrees in both directions and the Raspberry Pi Camera Module v2 has a field of view of horizontal 62.2 degrees and vertical 48.8 degrees. So horizontal it should match quite well (with little tolerance) but vertical the grid-eye sensor can see more than the camera. The grid-eye sensor has a aspect ration of 1:1 and the camera has one of 4:3. This is no big deal: I will add some black fields at the top and bottom of the camera and the data matches.
Here is an image of the combined output:
Making a video
The next step is to make a video with camera and temperature data to see how the data aligns in the whole sensing area. Making a video with OpenCV is quite simple: you just have to add each image/frame and OpenCV does the rest. First here is my source code (the image above was also made with the same source code):
#include <stdio.h>
#include <stdlib.h>
#include <linux/i2c-dev.h>
#include <fcntl.h>
#include <unistd.h>
#include <opencv2/opencv.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/contrib/contrib.hpp>
int main(void)
{
int file;
int addr=0x68; // adress of AMG88xx
int x,y; // variables to got through the array
char register_address=0; // register address of each sensor pixel
signed short int internal_temp;
signed short int pixel_temp;
int end=1; // variable to end program
printf("Pi Chef Stove Assistant Demo with AMG88xx\n"); // print start message
if((file=open("/dev/i2c-1",O_RDWR))<0) // open i2c-bus
{
perror("cannot open i2c-1");
exit(1);
}
if(ioctl(file, I2C_SLAVE, addr)<0) // open slave
{
perror("cannot open slave address");
exit(1);
}
internal_temp=(signed short)(i2c_smbus_read_word_data(file, 0x0e)<<4); // read internal temperature from sensor
internal_temp=internal_temp/16; // recalculate correct value
printf("Internal Temp: %f C (0x%04X = %i)\n",(float)internal_temp*0.0625,internal_temp,internal_temp); // print internal temperature
cv::Mat cameraImage; // create opencv mat for camera
cv::Mat cameraImageGray; // create opencv mat for grayscale camera image
cv::Mat cameraImageBig(320,320,CV_8UC3); // create opencv mat for camera with final resolution
cv::VideoCapture cap; // create camera input
cap.open(0); // open camera
cap.set(CV_CAP_PROP_FRAME_WIDTH, 320); // change camera width to 320 - we do not need more
cap.set(CV_CAP_PROP_FRAME_HEIGHT, 240); // change camera height to 240
cv::VideoWriter outputVideo; // create video output
outputVideo.open("output.avi", CV_FOURCC('M','J','P','G'), 10, cv::Size(320,320), true); // set video output to 10 fps and MJPG
if (!outputVideo.isOpened()) // check if generation of video output was successful
{
perror("Could not open the output video for write\n");
exit(1);
}
cv::Mat outSmall(8,8,CV_8UC1); // create opencv mat for sensor data
cv::Mat outSmallnorm(8,8,CV_8UC1); // create opencv mat for normalized data
cv::Mat outColor; // create opencv mat for color output
cv::Mat combined; // create opencv mat for combined output
while(end==1) // check end variable
{
for(x=0;x<8;x++)
{
for(y=0;y<8;y++)
{
register_address=0x80+2*((x*8)+y);
pixel_temp=(signed short)(i2c_smbus_read_word_data(file, register_address)<<4); // read pixel_temp and cast to signed short
pixel_temp=pixel_temp/16; // set pixel_temp to original value
outSmall.at(7-x,7-y)=pixel_temp; // save data to opencv mat and rotate it
}
}
cv::normalize(outSmall,outSmallnorm,255,0,cv::NORM_MINMAX); // normalize Mat to values between 0 and 255
cv::resize(outSmallnorm,outSmallnorm,cv::Size(320,320)); // resize Mat to 320 x 320 pixel
cv::applyColorMap(outSmallnorm,outColor,cv::COLORMAP_JET); // generate colored output with colormap
cap >> cameraImage; // copy camera input to opencv mat
cv::cvtColor(cameraImage,cameraImageGray,CV_RGB2GRAY); // convert camera image to grayscale
cv::cvtColor(cameraImageGray,cameraImageGray,CV_GRAY2RGB); // make cameraImage 3 channels again
cameraImageGray.copyTo(cameraImageBig(cv::Rect(0,40,320,240)));// copy camera ingae to mat with same resolution as temperature mat
cv::addWeighted(cameraImageBig,0.5,outColor,0.5,0.0,combined); // combine camera mat and temperature mat into one single image
cv::imshow("combined",combined); // display mat on screen
outputVideo << combined; // add frame to video
char key = cv::waitKey(1); // check keys for input
if(key=='e') end=0; // end if e was pressed
}
printf("ended regularly!\n"); // print end message
close(file);
return 0;
}
This code led to the following video:
Unfortunatelly OpenCV and the video input buffer always add a little delay to the video stream. So there is a little delay between the temperature data and the video. One solution would be to handle the video input in a second thread. But this is more complex so I have to live with this little delay for now.
What's next?
In the next days I will mount the sensor combination atop of my cook top and do some test measurements.


Top Comments