Fever Cam Calibration
/*
* Copyright (C) 2015-2018 Digital Barriers plc. All rights reserved.
* Contact: http://www.digitalbarriers.com/
*
* This file is part of the Papillon SDK.
*
* You can't use, modify or distribute any part of this file without
* the explicit written agreements of Digital Barriers.
*/
#include <PapillonCore.h>
#include <PImageInternal.h>
#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
USING_NAMESPACE_PAPILLON
const PString SAMPLE_DIR = PPath::Join(PUtils::GetEnv("PAPILLON_INSTALL_DIR"), "Data", "Samples");
// Global variables
PPoint2DfList colorPts, thermPts;
cv::Mat colorImg, thermImg;
cv::Mat colorImgSrc, thermImgSrc;
PImage refColor, refTherm;
// Simple cross drawing function, cross size and width adapts to image height
void drawCross(cv::Mat& io_img, const PPoint2Df& i_pt, const cv::Scalar& i_col)
{
int s = 1 + io_img.rows / 100;
cv::line(io_img, cv::Point(i_pt.GetX() - s, i_pt.GetY() - s), cv::Point(i_pt.GetX() + s, i_pt.GetY() + s), i_col, 1 + s/5);
cv::line(io_img, cv::Point(i_pt.GetX() + s, i_pt.GetY() - s), cv::Point(i_pt.GetX() - s, i_pt.GetY() + s), i_col, 1 + s/5);
}
// Updates display (show crosses where user has clicked)
// computes calibration (and saves it) and displays fused image (if possible)
void updateCalibAndDisplay()
{
colorImgSrc.copyTo(colorImg);
thermImgSrc.copyTo(thermImg);
for(int i = 0; i < colorPts.Size(); ++i)
drawCross(colorImg, colorPts.Get(i), cv::Scalar(0, 0, 255));
for(int i = 0; i < thermPts.Size(); ++i)
drawCross(thermImg, thermPts.Get(i), cv::Scalar(0, 0, 255));
cv::imshow("color", colorImg);
cv::imshow("therm", thermImg);
PResult r = fccalib.UpdateCalibration(colorPts, thermPts);
if (r.Ok())
{
fccalib.SaveToFile(PPath::Join(SAMPLE_DIR, "calibrationMatrix.bin")).LogErrorIfAny("saving calibration");
PImage fused;
fccalib.FuseImages(refColor, refTherm, fused);
fused.DisplayScaled("Fused", 1280, 768);
}
}
// left mouse click callback => calls updateCalibDisplay
void ptSelectionCallBack(int e, int x, int y, int flags, void* udata)
{
if (e == cv::EVENT_LBUTTONUP)
{
PPoint2DfList* l = (PPoint2DfList*)(udata);
l->Add(PPoint2Df(x, y));
updateCalibAndDisplay();
}
}
int main()
{
// Load sample images
PString colorPath = PPath::Join(SAMPLE_DIR, "feverCam_color.png"),
thermPath = PPath::Join(SAMPLE_DIR, "feverCam_therm.png");
refColor.Load(colorPath).LogErrorIfAny("loading color");
refTherm.Load(thermPath).LogErrorIfAny("loading therm");
colorImgSrc = cv::imread(colorPath.c_str());
thermImgSrc = cv::imread(thermPath.c_str());
// Create "color" and "therm" windows and adapt size/callbacks etc as needed
cv::namedWindow("color", cv::WINDOW_NORMAL | cv::WINDOW_KEEPRATIO);
cv::namedWindow("therm", cv::WINDOW_NORMAL | cv::WINDOW_KEEPRATIO);
cv::setMouseCallback("color", ptSelectionCallBack, &colorPts);
cv::setMouseCallback("therm", ptSelectionCallBack, &thermPts);
cv::resizeWindow("color", 1280, 768);
cv::resizeWindow("therm", 1024, 768);
// Show images
cv::imshow("color", colorImgSrc);
cv::imshow("therm", thermImgSrc);
// wait for any key press in one of the color/therm images
cv::waitKey(-1);
return 0;
}