Skip to content

Commit

Permalink
putText
Browse files Browse the repository at this point in the history
  • Loading branch information
firepick1 committed Apr 12, 2014
1 parent a2325ba commit b7a60f7
Show file tree
Hide file tree
Showing 11 changed files with 208 additions and 184 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ link_directories( ${BUILD_TARGET_DIR} /usr/local/lib )

file(GLOB FIRESIGHT_LIB_FILES
bgSub.cpp
calcOffset.cpp
calcHist.cpp
dft.cpp
FireLog.cpp
Expand Down
4 changes: 3 additions & 1 deletion FireSight.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,9 @@ bool parseArgs(int argc, char *argv[],
}

for (int i = 1; i < argc; i++) {
if (strcmp("-p",argv[i]) == 0) {
if (argv[i][0] == 0) {
// empty argument
} else if (strcmp("-p",argv[i]) == 0) {
if (i+1>=argc) {
LOGERROR("expected pipeline path after -p");
exit(-1);
Expand Down
9 changes: 5 additions & 4 deletions Pipeline.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ bool Pipeline::stageOK(const char *fmt, const char *errMsg, json_t *pStage, json
char *pStageJson = json_dumps(pStage, JSON_COMPACT|JSON_PRESERVE_ORDER);
LOGERROR2(fmt, pStageJson, errMsg);
free(pStageJson);
json_object_set(pStageModel, "error", json_string(errMsg));
return false;
}

Expand Down Expand Up @@ -92,16 +93,16 @@ bool Pipeline::apply_warpAffine(json_t *pStage, json_t *pStageModel, Model &mode

bool Pipeline::apply_putText(json_t *pStage, json_t *pStageModel, Model &model) {
validateImage(model.image);
string text = jo_string(pStage, "text", "FireSight");
string text = jo_string(pStage, "text", "FireSight", model.argMap);
Scalar color = jo_Scalar(pStage, "color", Scalar(0,255,0), model.argMap);
string fontFaceName = jo_string(pStage, "fontFace", "FONT_HERSHEY_PLAIN", model.argMap);
int thickness = jo_int(pStage, "thickness", 1, model.argMap);
int fontFace = FONT_HERSHEY_PLAIN;
bool italic = jo_bool(pStage, "italic", false, model.argMap);
double fontScale = jo_double(pStage, "fontScale", 1);
Point org = jo_Point(pStage, "org", Point(5,-6));
double fontScale = jo_double(pStage, "fontScale", 1, model.argMap);
Point org = jo_Point(pStage, "org", Point(5,-6), model.argMap);
if (org.y < 0) {
org.y = model.image.rows - org.y;
org.y = model.image.rows + org.y;
}
const char *errMsg = NULL;

Expand Down
168 changes: 168 additions & 0 deletions calcOffset.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
#include <string.h>
#include <math.h>
#include "FireLog.h"
#include "FireSight.hpp"
#include "opencv2/features2d/features2d.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "jansson.h"
#include "jo_util.hpp"
#include "MatUtil.hpp"

using namespace cv;
using namespace std;
using namespace firesight;

bool Pipeline::apply_calcOffset(json_t *pStage, json_t *pStageModel, Model &model) {
validateImage(model.image);
string tmpltPath = jo_string(pStage, "template", "", model.argMap);
int xtol = jo_int(pStage, "xtol", 32, model.argMap);
int ytol = jo_int(pStage, "ytol", 32, model.argMap);
vector<int> channels = jo_vectori(pStage, "channels", vector<int>(), model.argMap);
assert(model.image.cols > 2*xtol);
assert(model.image.rows > 2*ytol);
Rect roi= jo_Rect(pStage, "roi", Rect(xtol, ytol, model.image.cols-2*xtol, model.image.rows-2*ytol), model.argMap);
Rect roiScan = Rect(roi.x-xtol, roi.y-ytol, roi.width+2*xtol, roi.height+2*ytol);
float minval = jo_float(pStage, "minval", 0.7f, model.argMap);
float corr = jo_float(pStage, "corr", 0.99f);
string outputStr = jo_string(pStage, "output", "current", model.argMap);
const char *errMsg = NULL;
int flags = INTER_LINEAR;
int method = CV_TM_CCOEFF_NORMED;
Mat tmplt;
int borderMode = BORDER_REPLICATE;

if (tmpltPath.empty()) {
errMsg = "Expected template path for imread";
} else {
if (model.image.channels() == 1) {
tmplt = imread(tmpltPath.c_str(), CV_LOAD_IMAGE_GRAYSCALE);
} else {
tmplt = imread(tmpltPath.c_str(), CV_LOAD_IMAGE_COLOR);
}
if (tmplt.data) {
LOGTRACE2("apply_calcOffset(%s) %s", tmpltPath.c_str(), matInfo(tmplt).c_str());
if (model.image.rows<tmplt.rows || model.image.cols<tmplt.cols) {
errMsg = "Expected template smaller than image to match";
}
} else {
errMsg = "imread failed";
}
}
if (!errMsg) {
if (model.image.channels() > 3) {
errMsg = "Expected at most 3 channels for pipeline image";
} else if (tmplt.channels() != model.image.channels()) {
errMsg = "Template and pipeline image must have same number of channels";
} else {
for (int iChannel = 0; iChannel < channels.size(); iChannel++) {
if (channels[iChannel] < 0 || model.image.channels() <= channels[iChannel]) {
errMsg = "Referenced channel is not in image";
}
}
}
}

if (!errMsg) {
Mat result;
Mat imagePlanes[] = { Mat(), Mat(), Mat() };
Mat tmpltPlanes[] = { Mat(), Mat(), Mat() };
if (channels.size() == 0) {
channels.push_back(0);
if (model.image.channels() == 1) {
imagePlanes[0] = model.image;
tmpltPlanes[0] = tmplt;
} else {
cvtColor(model.image, imagePlanes[0], CV_BGR2GRAY);
cvtColor(tmplt, tmpltPlanes[0], CV_BGR2GRAY);
}
} else if (model.image.channels() == 1) {
imagePlanes[0] = model.image;
tmpltPlanes[0] = tmplt;
} else {
split(model.image, imagePlanes);
split(tmplt, tmpltPlanes);
}

json_t *pChannels = json_object();
json_object_set(pStageModel, "channels", pChannels);
for (int iChannel=0; iChannel<channels.size(); iChannel++) {
int channel = channels[iChannel];
Mat imageSource(imagePlanes[channel], roiScan);
Mat tmpltSource(tmpltPlanes[channel], roi);

matchTemplate(imageSource, tmpltSource, result, method);
LOGTRACE4("apply_calcOffset() matchTemplate(%s,%s,%s,CV_TM_CCOEFF_NORMED) channel:%d",
matInfo(imageSource).c_str(), matInfo(tmpltSource).c_str(), matInfo(result).c_str(), channel);

vector<Point> matches;
float maxVal = *max_element(result.begin<float>(),result.end<float>());
float rangeMin = corr * maxVal;
float rangeMax = maxVal;
matMaxima(result, matches, rangeMin, rangeMax);

if (logLevel >= FIRELOG_TRACE) {
for (size_t iMatch=0; iMatch<matches.size(); iMatch++) {
int mx = matches[iMatch].x;
int my = matches[iMatch].y;
float val = result.at<float>(my,mx);
if (val < minval) {
LOGTRACE4("apply_calcOffset() ignoring (%d,%d) val:%g corr:%g", mx, my, val, val/maxVal);
} else {
LOGTRACE4("apply_calcOffset() matched (%d,%d) val:%g corr:%g", mx, my, val, val/maxVal);
}
}
}
json_t *pMatches = json_object();
char key[10];
snprintf(key, sizeof(key), "%d", channel);
json_object_set(pChannels, key, pMatches);
if (matches.size() == 1) {
int mx = matches[0].x;
int my = matches[0].y;
float val = result.at<float>(my,mx);
if (minval <= val) {
int dx = xtol - mx;
int dy = ytol - my;
json_object_set(pMatches, "dx", json_integer(dx));
json_object_set(pMatches, "dy", json_integer(dy));
json_object_set(pMatches, "match", json_float(val));
}
}
}

json_t *pRects = json_array();
json_object_set(pStageModel, "rects", pRects);
json_t *pRect = json_object();
json_array_append(pRects, pRect);
json_object_set(pRect, "x", json_integer(roi.x+roi.width/2));
json_object_set(pRect, "y", json_integer(roi.y+roi.height/2));
json_object_set(pRect, "width", json_integer(roi.width));
json_object_set(pRect, "height", json_integer(roi.height));
json_object_set(pRect, "angle", json_integer(0));
pRect = json_object();
json_array_append(pRects, pRect);
json_object_set(pRect, "x", json_integer(roiScan.x+roiScan.width/2));
json_object_set(pRect, "y", json_integer(roiScan.y+roiScan.height/2));
json_object_set(pRect, "width", json_integer(roiScan.width));
json_object_set(pRect, "height", json_integer(roiScan.height));
json_object_set(pRect, "angle", json_integer(0));

normalize(result, result, 0, 255, NORM_MINMAX);
result.convertTo(result, CV_8U);
Mat corrInset = model.image.colRange(0,result.cols).rowRange(0,result.rows);
switch (model.image.channels()) {
case 3:
cvtColor(result, corrInset, CV_GRAY2BGR);
break;
case 4:
cvtColor(result, corrInset, CV_GRAY2BGRA);
break;
default:
result.copyTo(corrInset);
break;
}
}

return stageOK("apply_calcOffset(%s) %s", errMsg, pStage, pStageModel);
}
154 changes: 0 additions & 154 deletions dft.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -204,160 +204,6 @@ bool Pipeline::apply_matchTemplate(json_t *pStage, json_t *pStageModel, Model &m
return stageOK("apply_matchTemplate(%s) %s", errMsg, pStage, pStageModel);
}

bool Pipeline::apply_calcOffset(json_t *pStage, json_t *pStageModel, Model &model) {
validateImage(model.image);
string tmpltPath = jo_string(pStage, "template", "", model.argMap);
int xtol = jo_int(pStage, "xtol", 32, model.argMap);
int ytol = jo_int(pStage, "ytol", 32, model.argMap);
vector<int> channels = jo_vectori(pStage, "channels", vector<int>(), model.argMap);
assert(model.image.cols > 2*xtol);
assert(model.image.rows > 2*ytol);
Rect roi= jo_Rect(pStage, "roi", Rect(xtol, ytol, model.image.cols-2*xtol, model.image.rows-2*ytol), model.argMap);
Rect roiScan = Rect(roi.x-xtol, roi.y-ytol, roi.width+2*xtol, roi.height+2*ytol);
float minval = jo_float(pStage, "minval", 0.7f, model.argMap);
float corr = jo_float(pStage, "corr", 0.99f);
string outputStr = jo_string(pStage, "output", "current", model.argMap);
const char *errMsg = NULL;
int flags = INTER_LINEAR;
int method = CV_TM_CCOEFF_NORMED;
Mat tmplt;
int borderMode = BORDER_REPLICATE;

if (tmpltPath.empty()) {
errMsg = "Expected template path for imread";
} else {
if (model.image.channels() == 1) {
tmplt = imread(tmpltPath.c_str(), CV_LOAD_IMAGE_GRAYSCALE);
} else {
tmplt = imread(tmpltPath.c_str(), CV_LOAD_IMAGE_COLOR);
}
if (tmplt.data) {
LOGTRACE2("apply_calcOffset(%s) %s", tmpltPath.c_str(), matInfo(tmplt).c_str());
if (model.image.rows<tmplt.rows || model.image.cols<tmplt.cols) {
errMsg = "Expected template smaller than image to match";
}
} else {
errMsg = "imread failed";
}
}
if (!errMsg) {
if (model.image.channels() > 3) {
errMsg = "Expected at most 3 channels for pipeline image";
} else if (tmplt.channels() != model.image.channels()) {
errMsg = "Template and pipeline image must have same number of channels";
} else {
for (int iChannel = 0; iChannel < channels.size(); iChannel++) {
if (channels[iChannel] < 0 || model.image.channels() <= channels[iChannel]) {
errMsg = "Referenced channel is not in image";
}
}
}
}

if (!errMsg) {
Mat result;
Mat imagePlanes[] = { Mat(), Mat(), Mat() };
Mat tmpltPlanes[] = { Mat(), Mat(), Mat() };
if (channels.size() == 0) {
channels.push_back(0);
if (model.image.channels() == 1) {
imagePlanes[0] = model.image;
tmpltPlanes[0] = tmplt;
} else {
cvtColor(model.image, imagePlanes[0], CV_BGR2GRAY);
cvtColor(tmplt, tmpltPlanes[0], CV_BGR2GRAY);
}
} else if (model.image.channels() == 1) {
imagePlanes[0] = model.image;
tmpltPlanes[0] = tmplt;
} else {
split(model.image, imagePlanes);
split(tmplt, tmpltPlanes);
}

json_t *pChannels = json_object();
json_object_set(pStageModel, "channels", pChannels);
for (int iChannel=0; iChannel<channels.size(); iChannel++) {
int channel = channels[iChannel];
Mat imageSource(imagePlanes[channel], roiScan);
Mat tmpltSource(tmpltPlanes[channel], roi);

matchTemplate(imageSource, tmpltSource, result, method);
LOGTRACE4("apply_calcOffset() matchTemplate(%s,%s,%s,CV_TM_CCOEFF_NORMED) channel:%d",
matInfo(imageSource).c_str(), matInfo(tmpltSource).c_str(), matInfo(result).c_str(), channel);

vector<Point> matches;
float maxVal = *max_element(result.begin<float>(),result.end<float>());
float rangeMin = corr * maxVal;
float rangeMax = maxVal;
matMaxima(result, matches, rangeMin, rangeMax);

if (logLevel >= FIRELOG_TRACE) {
for (size_t iMatch=0; iMatch<matches.size(); iMatch++) {
int mx = matches[iMatch].x;
int my = matches[iMatch].y;
float val = result.at<float>(my,mx);
if (val < minval) {
LOGTRACE4("apply_calcOffset() ignoring (%d,%d) val:%g corr:%g", mx, my, val, val/maxVal);
} else {
LOGTRACE4("apply_calcOffset() matched (%d,%d) val:%g corr:%g", mx, my, val, val/maxVal);
}
}
}
json_t *pMatches = json_object();
char key[10];
snprintf(key, sizeof(key), "%d", channel);
json_object_set(pChannels, key, pMatches);
if (matches.size() == 1) {
int mx = matches[0].x;
int my = matches[0].y;
float val = result.at<float>(my,mx);
if (minval <= val) {
int dx = xtol - mx;
int dy = ytol - my;
json_object_set(pMatches, "dx", json_integer(dx));
json_object_set(pMatches, "dy", json_integer(dy));
json_object_set(pMatches, "match", json_float(val));
}
}
}

json_t *pRects = json_array();
json_object_set(pStageModel, "rects", pRects);
json_t *pRect = json_object();
json_array_append(pRects, pRect);
json_object_set(pRect, "x", json_integer(roi.x+roi.width/2));
json_object_set(pRect, "y", json_integer(roi.y+roi.height/2));
json_object_set(pRect, "width", json_integer(roi.width));
json_object_set(pRect, "height", json_integer(roi.height));
json_object_set(pRect, "angle", json_integer(0));
pRect = json_object();
json_array_append(pRects, pRect);
json_object_set(pRect, "x", json_integer(roiScan.x+roiScan.width/2));
json_object_set(pRect, "y", json_integer(roiScan.y+roiScan.height/2));
json_object_set(pRect, "width", json_integer(roiScan.width));
json_object_set(pRect, "height", json_integer(roiScan.height));
json_object_set(pRect, "angle", json_integer(0));

normalize(result, result, 0, 255, NORM_MINMAX);
result.convertTo(result, CV_8U);
Mat corrInset = model.image.colRange(0,result.cols).rowRange(0,result.rows);
switch (model.image.channels()) {
case 3:
cvtColor(result, corrInset, CV_GRAY2BGR);
break;
case 4:
cvtColor(result, corrInset, CV_GRAY2BGRA);
break;
default:
result.copyTo(corrInset);
break;
}
}

return stageOK("apply_calcOffset(%s) %s", errMsg, pStage, pStageModel);
}

bool Pipeline::apply_dftSpectrum(json_t *pStage, json_t *pStageModel, Model &model) {
validateImage(model.image);
int delta = jo_int(pStage, "delta", 1, model.argMap);
Expand Down
Binary file added img/putText.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit b7a60f7

Please sign in to comment.