Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Temp info getting #23

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added calculations.ods
Binary file not shown.
117 changes: 106 additions & 11 deletions examples/seek_viewer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <iostream>
#include <string>
#include <signal.h>
#include <math.h>
#include <memory>
#include "args.h"

Expand All @@ -21,37 +22,129 @@ void handle_sig(int sig) {
sigflag = 1;
}

double device_sensor_to_k(double sensor) {
// formula from http://aterlux.ru/article/ntcresistor-en
double ref_temp = 297.0; // 23C from table
double ref_sensor = 6616.0; // ref value from table
double beta = 200; // best beta coef we've found
double part3 = log(sensor) - log(ref_sensor);
double parte = part3 / beta + 1.0 / ref_temp;
return 1.0 / parte;
}

double temp_from_raw(int x, double device_k) {
// Constants below are taken from linear trend line in Excel.
// -273 is translation of Kelvin to Celsius
// 330 is max temperature supported by Seek device
// 16384 is full 14 bits value, max possible ()
double base = x * 330 / 16384.0;
double lin_k = -1.5276; // derived from Excel linear model
double lin_offset= -470.8979; // same Excel model
return base - device_k * lin_k + lin_offset - 273.0;
}

void overlay_values(Mat &outframe, Point coord, Scalar color) {
int gap=2;
int arrLen=7;
int weight=1;
line(outframe, coord-Point(-arrLen, -arrLen), coord-Point(-gap, -gap), color, weight);
line(outframe, coord-Point(arrLen, arrLen), coord-Point(gap, gap), color, weight);
line(outframe, coord-Point(-arrLen, arrLen), coord-Point(-gap, gap), color, weight);
line(outframe, coord-Point(arrLen, -arrLen), coord-Point(gap, -gap), color, weight);
}

void draw_temp(Mat &outframe, double temp, Point coord, Scalar color) {
char txt [64];
sprintf(txt, "%5.1f", temp);
putText(outframe, txt, coord-Point(20, -20), FONT_HERSHEY_COMPLEX_SMALL, 0.75, color, 1, CV_AA);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Prefer FONT_HERSHEY_PLAIN, screen interfaces should use san-serif fonts.

}

// Function to process a raw (corrected) seek frame
void process_frame(Mat &inframe, Mat &outframe, float scale, int colormap, int rotate) {
Mat frame_g8, frame_g16; // Transient Mat containers for processing
void process_frame(Mat &inframe, Mat &outframe, float scale, int colormap, int rotate, int device_temp_sensor) {
Mat frame_g8_nograd, frame_g16; // Transient Mat containers for processing

// get raw max/min/central values
double min, max, central;
minMaxIdx(inframe, &min, &max);
Scalar valat=inframe.at<uint16_t>(Point(inframe.cols/2.0, inframe.rows/2.0));
central=valat[0];

double device_k=device_sensor_to_k(device_temp_sensor);

double mintemp=temp_from_raw(min, device_k);
double maxtemp=temp_from_raw(max, device_k);
double centraltemp=temp_from_raw(central, device_k);

printf("rmin,rmax,central,devtempsns: %d %d %d %d\t", (int)min, (int)max, (int)central, (int)device_temp_sensor);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to be pushing two lines to stdout for every frame? If these need to stay can you control their output with a command line parameter.

printf("min-max-center-device: %.1f %.1f %.1f %.1f\n", mintemp, maxtemp, centraltemp, device_k-273.0);

normalize(inframe, frame_g16, 0, 65535, NORM_MINMAX);

// Convert seek CV_16UC1 to CV_8UC1
frame_g16.convertTo(frame_g8, CV_8UC1, 1.0/256.0 );
frame_g16.convertTo(frame_g8_nograd, CV_8UC1, 1.0/256.0 );

// Rotate image
if (rotate == 90) {
transpose(frame_g8, frame_g8);
flip(frame_g8, frame_g8, 1);
transpose(frame_g8_nograd, frame_g8_nograd);
flip(frame_g8_nograd, frame_g8_nograd, 1);
} else if (rotate == 180) {
flip(frame_g8, frame_g8, -1);
flip(frame_g8_nograd, frame_g8_nograd, -1);
} else if (rotate == 270) {
transpose(frame_g8, frame_g8);
flip(frame_g8, frame_g8, 0);
transpose(frame_g8_nograd, frame_g8_nograd);
flip(frame_g8_nograd, frame_g8_nograd, 0);
}

Point minp, maxp, centralp;
minMaxLoc(frame_g8_nograd, NULL, NULL, &minp, &maxp); // doing it here, so we take rotation into account
centralp=Point(frame_g8_nograd.cols/2.0, frame_g8_nograd.rows/2.0);
minp*=scale;
maxp*=scale;
centralp*=scale;

// Resize image: http://docs.opencv.org/3.2.0/da/d54/group__imgproc__transform.html#ga5bb5a1fea74ea38e1a5445ca803ff121
// Note this is expensive computationally, only do if option set != 1
if (scale != 1.0)
resize(frame_g8, frame_g8, Size(), scale, scale, INTER_LINEAR);
resize(frame_g8_nograd, frame_g8_nograd, Size(), scale, scale, INTER_LINEAR);

// add gradient
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you consider extending the image frame do that you don't end up overdrawing the thermal data so much?

Mat frame_g8(Size(frame_g8_nograd.cols+20, frame_g8_nograd.rows), CV_8U, Scalar(128));
for (int r = 0; r < frame_g8.rows-1; r++)
{
frame_g8.row(r).setTo(255.0*(frame_g8.rows-r)/((float)frame_g8.rows));
}
frame_g8_nograd.copyTo(frame_g8(Rect(0,0,frame_g8_nograd.cols, frame_g8_nograd.rows)));

// Apply colormap: http://docs.opencv.org/3.2.0/d3/d50/group__imgproc__colormap.html#ga9a805d8262bcbe273f16be9ea2055a65
if (colormap != -1) {
applyColorMap(frame_g8, outframe, colormap);
} else {
cv::cvtColor(frame_g8, outframe, cv::COLOR_GRAY2BGR);
}

// overlay marks
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All of these overlays need to be controlled by a command line option defaulting to false.

draw_temp(outframe, mintemp, Point(outframe.cols-49, outframe.rows-29), Scalar(255, 255, 255));
draw_temp(outframe, mintemp, Point(outframe.cols-51, outframe.rows-31), Scalar(0, 0, 0));
draw_temp(outframe, mintemp, Point(outframe.cols-50, outframe.rows-30), Scalar(255, 0, 0));

draw_temp(outframe, maxtemp, Point(outframe.cols-49, 0), Scalar(255, 255, 255));
draw_temp(outframe, maxtemp, Point(outframe.cols-51, 2), Scalar(0, 0, 0));
draw_temp(outframe, maxtemp, Point(outframe.cols-50, 1), Scalar(0, 0, 255));

draw_temp(outframe, centraltemp, centralp+Point(-1, -1), Scalar(255, 255, 255));
draw_temp(outframe, centraltemp, centralp+Point(1, 1), Scalar(0, 0, 0));
draw_temp(outframe, centraltemp, centralp+Point(0, 0), Scalar(128, 128, 128));

overlay_values(outframe, centralp+Point(-1,-1), Scalar(0,0,0));
overlay_values(outframe, centralp+Point(1,1), Scalar(255,255,255));
overlay_values(outframe, centralp, Scalar(128,128,128));

overlay_values(outframe, minp+Point(-1,-1), Scalar(0,0,0));
overlay_values(outframe, minp+Point(1,1), Scalar(255,255,255));
overlay_values(outframe, minp, Scalar(255,0,0));

overlay_values(outframe, maxp+Point(-1,-1), Scalar(0,0,0));
overlay_values(outframe, maxp+Point(1,1), Scalar(255,255,255));
overlay_values(outframe, maxp, Scalar(0,0,255));
}

int main(int argc, char** argv)
Expand Down Expand Up @@ -140,7 +233,9 @@ int main(int argc, char** argv)
return -1;
}

process_frame(seekframe, outframe, scale, colormap, rotate);
printf("WxH: %d %d\n", seekframe.cols, seekframe.rows);

process_frame(seekframe, outframe, scale, colormap, rotate, seek->device_temp_sensor());

// Create an output object, if output specified then setup the pipeline unless output is set to 'window'
VideoWriter writer;
Expand All @@ -164,7 +259,7 @@ int main(int argc, char** argv)
}

// Retrieve frame from seek and process
process_frame(seekframe, outframe, scale, colormap, rotate);
process_frame(seekframe, outframe, scale, colormap, rotate, seek->device_temp_sensor());

if (output == "window") {
imshow("SeekThermal", outframe);
Expand Down
12 changes: 12 additions & 0 deletions src/SeekCam.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,15 @@ bool SeekCam::open_cam()
return false;
}

void save_frame_img(cv::Mat &frame, int frameId) {
cv::Mat dst;
dst.create(frame.rows, frame.cols, frame.type());
//normalize(frame, dst, 0, 65535, cv::NORM_MINMAX);
char outfile[256];
sprintf(outfile, "frame-%d.png", frameId);
cv::imwrite(outfile, dst);
}

bool SeekCam::get_frame()
{
/* request new frame */
Expand All @@ -197,6 +206,8 @@ bool SeekCam::get_frame()
if (!m_dev.fetch_frame(m_raw_data, m_raw_data_size))
return false;

// save_frame_img(m_raw_frame, frame_id());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left over debugging code?


return true;
}

Expand Down Expand Up @@ -265,6 +276,7 @@ void SeekCam::create_dead_pixel_list(cv::Mat frame, cv::Mat& dead_pixel_mask,
}
}
} while (has_unlisted_pixels);
printf("Found %lu dead pixels\n", dead_pixel_list.size());
}

void SeekCam::apply_dead_pixel_filter(cv::Mat& src, cv::Mat& dst)
Expand Down
5 changes: 5 additions & 0 deletions src/SeekCam.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,11 @@ class SeekCam
*/
virtual int frame_counter() = 0;

/*
* Get device onboard temperature sensor value
*/
virtual uint16_t device_temp_sensor() = 0;

protected:

SeekCam(int vendor_id, int product_id, uint16_t* buffer, size_t raw_height, size_t raw_width, cv::Rect roi, std::string ffc_filename);
Expand Down
61 changes: 32 additions & 29 deletions src/SeekDevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,43 +17,46 @@ namespace LibSeek {

struct DeviceCommand {
enum Enum {
BEGIN_MEMORY_WRITE = 82,
COMPLETE_MEMORY_WRITE = 81,
GET_BIT_DATA = 59,
GET_CURRENT_COMMAND_ARRAY = 68,
GET_DATA_PAGE = 65,
GET_DEFAULT_COMMAND_ARRAY = 71,
GET_ERROR_CODE = 53,
GET_FACTORY_SETTINGS = 88,
GET_FIRMWARE_INFO = 78,
GET_IMAGE_PROCESSING_MODE = 63,
GET_OPERATION_MODE = 61,
GET_RDAC_ARRAY = 77,
GET_SHUTTER_POLARITY = 57,
GET_VDAC_ARRAY = 74,
READ_CHIP_ID = 54,
RESET_DEVICE = 89,
TOGGLE_SHUTTER = 55,
SET_SHUTTER_POLARITY = 56,
GET_SHUTTER_POLARITY = 57,
SET_BIT_DATA_OFFSET = 58,
SET_CURRENT_COMMAND_ARRAY = 67,
SET_CURRENT_COMMAND_ARRAY_SIZE = 66,
GET_BIT_DATA = 59,

SET_OPERATION_MODE = 60,
GET_OPERATION_MODE = 61,
SET_IMAGE_PROCESSING_MODE = 62,
GET_IMAGE_PROCESSING_MODE = 63,
SET_DATA_PAGE = 64,
SET_DEFAULT_COMMAND_ARRAY = 70,
GET_DATA_PAGE = 65,
SET_CURRENT_COMMAND_ARRAY_SIZE = 66,
SET_CURRENT_COMMAND_ARRAY = 67,
GET_CURRENT_COMMAND_ARRAY = 68,
SET_DEFAULT_COMMAND_ARRAY_SIZE = 69,
SET_FACTORY_SETTINGS = 87,
SET_FACTORY_SETTINGS_FEATURES = 86,
SET_FIRMWARE_INFO_FEATURES = 85,
SET_IMAGE_PROCESSING_MODE = 62,
SET_OPERATION_MODE = 60,
SET_RDAC_ARRAY = 76,
SET_RDAC_ARRAY_OFFSET_AND_ITEMS = 75,
SET_SHUTTER_POLARITY = 56,
SET_VDAC_ARRAY = 73,

SET_DEFAULT_COMMAND_ARRAY = 70,
GET_DEFAULT_COMMAND_ARRAY = 71,
SET_VDAC_ARRAY_OFFSET_AND_ITEMS = 72,
START_GET_IMAGE_TRANSFER = 83,
TARGET_PLATFORM = 84,
TOGGLE_SHUTTER = 55,
SET_VDAC_ARRAY = 73,
GET_VDAC_ARRAY = 74,
SET_RDAC_ARRAY_OFFSET_AND_ITEMS = 75,
SET_RDAC_ARRAY = 76,
GET_RDAC_ARRAY = 77,
GET_FIRMWARE_INFO = 78,
UPLOAD_FIRMWARE_ROW_SIZE = 79,

WRITE_MEMORY_DATA = 80,
COMPLETE_MEMORY_WRITE = 81,
BEGIN_MEMORY_WRITE = 82,
START_GET_IMAGE_TRANSFER = 83,
TARGET_PLATFORM = 84,
SET_FIRMWARE_INFO_FEATURES = 85,
SET_FACTORY_SETTINGS_FEATURES = 86,
SET_FACTORY_SETTINGS = 87,
GET_FACTORY_SETTINGS = 88,
RESET_DEVICE = 89,
};
};

Expand Down
5 changes: 5 additions & 0 deletions src/SeekThermal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -131,3 +131,8 @@ int SeekThermal::frame_counter()
{
return m_raw_data[40];
}

uint16_t SeekThermal::device_temp_sensor()
{
return m_raw_data[1];
}
1 change: 1 addition & 0 deletions src/SeekThermal.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ class SeekThermal: public SeekCam
virtual bool init_cam();
virtual int frame_id();
virtual int frame_counter();
virtual uint16_t device_temp_sensor();

private:
uint16_t m_buffer[THERMAL_RAW_SIZE];
Expand Down
4 changes: 4 additions & 0 deletions src/SeekThermalPro.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -145,3 +145,7 @@ int SeekThermalPro::frame_counter()
return m_raw_data[1];
}

uint16_t SeekThermalPro::device_temp_sensor()
{
return m_raw_data[5];
}
1 change: 1 addition & 0 deletions src/SeekThermalPro.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ class SeekThermalPro: public SeekCam
virtual bool init_cam();
virtual int frame_id();
virtual int frame_counter();
virtual uint16_t device_temp_sensor();

private:
uint16_t m_buffer[THERMAL_PRO_RAW_SIZE];
Expand Down