I run this program on my laptop with Debian Linux (Wheezy) as well as on Raspberry Pis.
I started out with some code posted on the eevblog by cynfab
which merely captured camera data to files and then found an expanded
version on Github which also displayed images. That gave me
the
basics I needed to get running & I expanded it from there. I
thought working with the Python code would be easier than learning about
libusb & displaying images in a GUI, but after many "screaming
moments" with Python & then changing to C/C++n & SDL2 I
wonder...
Because Python runs so slow I do all the pixel math in a C module, which does the following:
calculates image pixel values from image & cal frames
assign zero pixels the value from prior pixel
applies pixel by pixel scale factors from frame of status 10 or a cal file generated by the program
loads image data into an RGB array
A separate module function swaps R & B in the color array so video will be saved properly by cv2
Doing all of that in python slowed video down to 1 frame/3 seconds on a
2.4GHz laptop, maxing out one core. In compiled C it only takes 3% of cpu
time (out of 4 cores) to get 8-9fps.
RevA adds a search for min & max temperature in each frame when auto ranging palette is selected.
RevA also implements bias correction to get cleaner images.
@IwuzBornanerd on eevblog
To use this program you will need to have the following "packages" installed on your system:
python 2.7 (3+ may work)
and pyusb-1.0.0b2; even the version in Raspbian Stretch was not good enough
and python-imaging (PIL) 1.1.6 or better
and python-imaging-tk (python-pil.imagetk in Stretch?)
and python-numpy
and python-scipy
and ImageMagick(? I think that was just for Fry-kun's original code)
ALSO now requires
python-opencv and its openCV 2 dependencies
Rsaspbian Jessie needed to have libgl1-mesa-dri installed
!!!!!Python PIL in Raspbian Stretch uses "Image.frombytes" instead of "Image.fromstring", which makes more sense, BUT
I am leaving it as fromstring in this code since I am still using "Jessie" and maybe others are too.
There are 3 places that you need to search for & change it in the code if you use Stretch (a 4th is commented out).
After installing all the required stuff, change to the directory containing the program files and compile the pixelmath module
by running 2 commands:
python setupA.py build
sudo python setupA.py install
Then run the program with the command: [sudo (if needed)] python Rpi2Seek.py
To avoid needing "sudo", add a file containing the following line:
SUBSYSTEM=="usb", ATTRS{idVendor}=="289d", ATTRS{idProduct}=="0010", GROUP="plugdev"
to the directory /etc/udev/rules.d
My laptop somehow generated this file with the filename 50-seekthermal-usb.rules
In order to get the cleanest images you need to create a "pixelcal.txt"
file for your camera. To do this, run the camera until the value
of pixel 1 is stable (at least 20 minutes), focus the camera on a
surface that is of uniform ambient temperature, then press the "c" key
(or click on the "Cal" button) and the program will generate a file
named "calfile.txt". You can either copy the contents of that file
to the one called "pixelcal.txt" or delete the supplied one
(since it is only good for my camera anyway) and rename your new file to
"pixelcal.txt". The next time you start the program it will read
the new file, but you can also use it immediately by pressing "i" to
toggle between using frameID10 and the pixelcal file. Version A of
the program also saves the hutter frame that is in use during the
calibration for use in correcting for pixel bias changes. This
file is named "newreffile.txt" and should be copied into (or renamed to)
"refframe.txt". Let me know if you would prefer that the
program simply replaced the existing file rather than making a new
one...But you can easily change that in the code by finding the file
name & changing it. :~)
The temperatures WILL be off (about 10 degrees F when cold) until the
camera is
warmed up. This is because the value of pixel 1 which I use to
track temperature appears to represent a temperature that is lower than
the shutter once the camera is warmed up. What I observe is that
the value of pixel 1 with cold camera varies 10 per degree F and at
normal room temperatures the values in the curve in frameID9 change at
10 per degree F also, but when the camera is warming up, the
normalized sensor values change faster and farther than pixel 1, so I am
assuming the shutter is warmer than whatever produces the value in
pixel 1 once the camera is warmed up. I have not come up with a
way to correct for that, but maybe looking at the rate of change of
pixel 1 could help... I did put some code in there to try to track
out the warmup changes, but that is only between cal frames.
If you look at the code & feel like gagging or laughing out loud,
remember I am not a trained programmer so there will be things not done
properly in the view of a trained programmer. :~0
The GUI has buttons for the more necessary functions and there are
keys that perform the same functions as well as some additional
functions. These are screenshots of the "standard" size window and
the widow on a 3.5" LCD display.
 |
 |
The button/key functions are as follows:
- This button steps through the different palettes available as
specified in the config file. The "b" key does the same thing
- This button changes the palette zoom level. The number left
of the button is how many colors (shades) are applied per degree.
When this is the letter "A", the palette autoranges to cover the full
temperature range of the scene. You won't see as much detail when
there is a wide range of temperatures in the scene with this setting,
and will see too much noise with my special palettes and a narrow
temperature range. The colors/degree settings are best used with
my palettes, I think. There is no key for this function.
- Click this button OR press the "s" key to save a still image of
the current scene to a png file (file name includes date & time).
- Click this button OR press the "v" key to turn on & off video
capture. The button will be red while recording. The video
is always same file name and keeps adding to same file until program is
closed.
- Click this button OR press the 9 key to turn off & on the
smoothing function. This averages in the 8 pixels surrounding each
pixel at each pixel to "soften" the noise. This seems to bring
out more detail a lot of the time but the image looks more "crisp" with
it off. The button is green when smoothing is on.
- Click this button to freeze the display on the last frame.
Data is still pulled of the camera but not processed. You can add
markers while frozen and they will be valid for the displayed
image. The save function will save the displayed image.
Video will not be recorded while frozen. There is no key for this
function.
- Click this button OR right-click the mouse to clear the display of
markers. If you are in palette autorange mode with the min/max
marker display on the min/max markers will not turn off. There is
no key for this function.
- Click this button OR press the "k" key to toggle between Fahrenheit & centigrade temperature.
- Click this button OR press the "c" key to perform a
"non-uniformity correction" (I think that's the official term).
FIRST run the camera long enough to get it warmed up & stable
(probably 20 minutes or more). Then aim it at a uniform ambient
temperature surface such as a blank sheet of paper and click on this
button. The program will average a number of image frames
following ONE shutter frame and calculate scaling factors that when
applied will result in uniform temperatures displayed across that
surface. Two files will be saved: "calfile.txt" and
"newreffile.txt". The first file is the scaling factors & the
second file is the shutter frame that was in effect during the
calibration and is used for correcting for the changing pixel
bias. I have the program use different names for these files than
the file names it reads in at startup so that we don't accidentally
replace good files with unintentionally produced files. SO you
need to copy "calfile.txt" into "pixelcal.txt" and "newreffile.txt" into
"refframe.txt" in order to have the new values take effect. If
you want different behavior you can, of course, change those names in
the code.
- Click this button or press the "m" key to cause the center
temperature of the palette to be the temperature of the first marker
WHEN NOT in autoranging palette mode. When in the autoranging mode
this button/key will toggle on/off the display of the min & max
temperature markers. I made this option because those markers can
jump around a lot in some scenes & can be annoying.
- Click this button or press the escape key to close the program.
Also, left-click on a pixel to display the temperature at that pixel; up
to 5 markers can be displayed at once & they keep updating.
Pixel temperature markers will be on saved images & videos.
The following key functions are also available. The letters specified must be lower case only.
-
Press the p key to turn on & off application of the pixel "non-uniformity" correction factors
- Press the l key to save a frame as a text list of pixel values (file name includes frame number)
- Press i to toggle internal (frameID10) vs. "user generated" pixel
scaling factors. You will absolutely need the external file for
newer Seeks because frame 10 changed significantly when they made the
camera less noisy and this code is not updated to accommodate that change.
-
Press t to toggle bias correction on & off using the saved reference
shutter frame. This compensates for the cahnge in individual
pixel bias that is re-figured with each shutter frame
The program runs on my Raspberry Pi 2B running at 900MHz with the following caveats:
It displays real-time images at 8-9fps so long as scaling is no more
than 2x
It will record video at 8-9fps ONLY if scaling is 1.
I sized the GUI so that it will fill the screen at 3x scaling on the 5
inch touchscreen I use with the RPi, but when I set scaling to 3 the Pi
will only run at 3-4fps, but the CPU applet shows no difference in CPU
usage vs 2x scaling and no core is maxed, so I believe the problem is the time it takes to write to the display.
On my Pi Zero with a 3.5" LCD this program runs at only 4 frames/sec.
My goal in making my own palette was to have a uniquely recognizable
color for every degree Fahrenheit. I have not gotten there so I
repeated the colors I have to fill in the 666 degrees. I made a
second palette with slightly less distinct colors & I use that one
for surveillance. I have not added the surveillance function to
this revision since it cannot run 8fps while also displaying the
images. Look for the SDL2 version if you want surveillance.
The config.txt allows "the user" some flexibility and a bit of ability
to change stuff without altering the software. Any line that
begins with # is ignored by the program and parameters must be entered
exactly as they are in the provided file--letters are case-specific and
there must be no spaces between the "=" sign and anything else.
Also there must be no space at the end of a line. The parameters
can be in any order.
The parameters are as follows:
F or C or temperature units used for display; the line should be like:
ForC=F
Ambient temperature at which pixel 1 is the value in next line; can be
floating point or integer, units as specified in the F or C line.
The line is:
ambientT=78
The value of pixel 1 at the ambient temperature given above. This
must be an integer. Obtain this by looking at the pixel 1 value
displayed on the GUI as soon as the program starts. Type it like
this:
pixel1atT=4371
A number indicating what the normalized scene-minus-shutter value should
be for a uniform ambient temperature surface with a camera stabilized
at that ambienttemperature. This is used to calculate the pixel
scaling factors and must be a negative integer, specified as:
diffshouldbe=-400
The above 3 numbers are used to calibrate the camera in order to get
"reasonably accurate" temperature readings. The values in the
provided file work for my camera. Everyone else will need to
determine their own numbers for at least the first 2. Having all 3
numbers in this file should facilitate "massaging" things to get good
temperature readings on your camera. But we won't know until other
people try to use this. The "diffshouldbe" could be used to
change the spread between temperatures; for instance, if room
temperature readings are good but freezing temperatures read high, you
could increase diffshouldbe & make a new pixelcal file which would
cause all "diffs" to be scaled up more thereby increasing the
temperature spread. The other 2 numbers establish a reference
point on the thermistor curve to which the frameID3-frameID1 "diffs" are
referenced. So you could artificially adjust the "pixel1atT"
value to shift all temperature readings up or down. I
already have an offset of 291 in the program for just that
purpose--because the pixel1 value does not change as much as the cal
frame sensor readings as the camera warms up and the reference point
tries to identify the shutter temperature on the thermistor curve as a
function of the pixel1 value.
Default to using frameID10 for pixel gain compensation; yes or no.
As supplied this is now set to "no" because newer Seeks
will not work right with the frame 10 values because Seek changed the
range of data values in frame 10 & I have not updated this program
to
accommodate those values, so you MUST make your own cal file to get
usable images with newer Seeks. Expect the images to look noisy or
downright lousy with the supplied pixelcal file from my camera.
useframe10=no
Image scaling factor for display and still image & video capture.
imgscale=2
The font & path to be used for the markers. Expect this to be different on your system. specify it like this:
font=/usr/share/fonts/truetype/freefont/FreeMonoBold.ttf
Screen size. This is here specifically for the Rpi mobile screens.
0 is anything bigger than 800x480, such as most any laptop or desktop pc
1 is 800x480 5" screen
2 is 480x320 3.5" screen
Specify screen size like this:
Rpiscreen=0
Palette files. These files are ASCII lists of r, g, & b values
0-255, one set of 3 per line with spaces between values. I have
supplied 6 files & the program is set to allow for 10. There
can be up to 1024 sets of r,g,b values in each file.
Specify the file names like this:
palette=graypalette.txt