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

Manipulate colormap, contrast, brightness & window position #47

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all 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
30 changes: 30 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -149,3 +149,33 @@ seek_viewer -t seek -F seek_ffc.png
seek_test_pro seekpro_ffc.png
seek_viewer -t seekpro -F seekpro_ffc.png
```
## Added functionality
### Color map selecting
Cycle through all 12 color maps by pressing 'c'. Black and white is not a standard "colormap" but it is preseved at the 0th position, for a total of 13 possible maps.

### Rotating
Pressing 'r' will change the orientation (4 possible)

### Brightness & contrast
By providing the '-n 1' command line switch, brightness and contrast are no longer adjusted dynamically.

'w' will increase the contast

's' will decrease the contrast

'a' will decrease the brightness

'd' will increase the brightness

This function provides quite granular control, but this also means brightness has to be tweaked to match for each adjustment to contrast.
It is useful for having the field of vision not suddendly change in appearance completely when a hot or cold object is viewed.

### Scaling
One can also adjust the size of the output (scaling value) by pressing + or -.
Note that in this case, "+" means Shift + "=" and "-" is just the normal "-" key. The Numpad "+" and "-" return different scan codes so don't work at this time.

### Window position
At least on Ubuntu (will check Debian later) the arrow keys allow moving the window position. Scancodes are different for each platform (supposedly for different renderers even), so this may not work on your environment.
Copy link
Contributor

@Bostwickenator Bostwickenator Aug 25, 2020

Choose a reason for hiding this comment

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

We don't want functionality to be tied to one OS. Could you investigate further if these can be made stable across multiple systems


## Feedback
Copy link
Contributor

Choose a reason for hiding this comment

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

Remove this section

I've started a thread about this updated version on EEVBlog, please comment for questions / issues: https://www.eevblog.com/forum/thermal-imaging/slightly-updated-libseek-thermal-(keyboard-interface)/
82 changes: 69 additions & 13 deletions examples/seek_viewer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,13 @@ void handle_sig(int sig) {
}

// Function to process a raw (corrected) seek frame
void process_frame(Mat &inframe, Mat &outframe, float scale, int colormap, int rotate) {
void process_frame(Mat &inframe, Mat &outframe, float scale, int colormap, int rotate, int cont, int bright) {
Copy link
Contributor

Choose a reason for hiding this comment

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

cont is normalize elsewhere. Likewise bright should be brightness

Mat frame_g8, frame_g16; // Transient Mat containers for processing

if(cont == 0){
Copy link
Contributor

Choose a reason for hiding this comment

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

Incorrect spacing, all the changes need to go through formatting to bring them in line with the established style

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

} else{
frame_g16=(inframe*cont)-bright;
}
// Convert seek CV_16UC1 to CV_8UC1
frame_g16.convertTo(frame_g8, CV_8UC1, 1.0/256.0 );

Expand All @@ -47,16 +49,17 @@ void process_frame(Mat &inframe, Mat &outframe, float scale, int colormap, int r
resize(frame_g8, frame_g8, Size(), scale, scale, INTER_LINEAR);

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

int main(int argc, char** argv)
{
// Setup arguments for parser

// Setup arguments for parser
args::ArgumentParser parser("Seek Thermal Viewer");
args::HelpFlag help(parser, "help", "Display this help menu", {'h', "help"});
args::ValueFlag<std::string> _output(parser, "output", "Output Stream - name of the video file to write", {'o', "output"});
Expand All @@ -66,7 +69,12 @@ int main(int argc, char** argv)
args::ValueFlag<int> _colormap(parser, "colormap", "Color Map - number between 0 and 12", {'c', "colormap"});
args::ValueFlag<int> _rotate(parser, "rotate", "Rotation - 0, 90, 180 or 270 (default) degrees", {'r', "rotate"});
args::ValueFlag<std::string> _camtype(parser, "camtype", "Seek Thermal Camera Model - seek or seekpro", {'t', "camtype"});

args::ValueFlag<int> _normalize(parser, "normalize", "0 for normal normalization, 1-50 (ish) for custom contrast", {'n',"normalize"});
Copy link
Contributor

Choose a reason for hiding this comment

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

normal normalization -> automatic normalization

int colormap=0;
int brightness=0;
int normalize=0;
int x=100;
int y=100;
// Parse arguments
try
{
Expand Down Expand Up @@ -104,13 +112,24 @@ int main(int argc, char** argv)
if (_fps)
fps = args::get(_fps);
// Colormap int corresponding to enum: http://docs.opencv.org/3.2.0/d3/d50/group__imgproc__colormap.html
int colormap = -1;
// int colormap = -1;
Copy link
Contributor

Choose a reason for hiding this comment

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

remove commented code

if (_colormap)
colormap = args::get(_colormap);
// Rotate default is landscape view to match camera logo/markings
//Constant contrast or auto-adjust
if(_normalize){
if(_ffc) {
brightness=620000;
Copy link
Contributor

Choose a reason for hiding this comment

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

tabs

normalize=40;
} else{
brightness=590000;
normalize=40;
}
}
int rotate = 270;
if (_rotate)
rotate = args::get(_rotate);


// Register signals
signal(SIGINT, handle_sig);
Expand Down Expand Up @@ -140,7 +159,7 @@ int main(int argc, char** argv)
return -1;
}

process_frame(seekframe, outframe, scale, colormap, rotate);
process_frame(seekframe, outframe, scale, colormap, rotate, normalize, brightness);

// Create an output object, if output specified then setup the pipeline unless output is set to 'window'
VideoWriter writer;
Expand All @@ -164,17 +183,54 @@ 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, normalize, brightness);

if (output == "window") {
imshow("SeekThermal", outframe);
char c = waitKey(10);
if (c == 's') {
namedWindow("SeekThermal");
moveWindow("SeekThermal", x,y);
Copy link
Contributor

Choose a reason for hiding this comment

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

This blocks the user from moving the window using their window manager. That doesn't seem reasonable.

int c = waitKeyEx(5);
//std::cout << (int)c << std::endl;
if (c == 112) {
Copy link
Contributor

Choose a reason for hiding this comment

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

The keycodes should be defined as constants (no magic numbers)

Copy link
Contributor

Choose a reason for hiding this comment

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

Processing these events should be handled in a dedicated function to separate out those concerns.

waitKey(0);
}
} else {
else if (c ==119 && _normalize){
normalize++;
} else if (c ==115 && _normalize){
normalize--;
} else if (c == 100 && _normalize){ // normally 100
brightness-=5000;
}else if (c == 97 && _normalize){ //normally 97
brightness+=5000;
}else if(c == 99){
if(colormap<12){
colormap++;
}else{
colormap=0;
}
}else if(c==114){
if(rotate==270){
rotate=0;
}
else{
rotate+=90;
}
}else if(c==65579){
scale +=0.05;
}else if(c==45){
scale -=0.05;
}else if(c==65362){
y-=10;
}else if(c==65364){
y+=10;
}else if(c==65363){
x+=10;
}else if(c==65361){
x-=10;
}else {
writer << outframe;
}
}
}

std::cout << "Break signal detected, exiting" << std::endl;
Expand Down