DGM library has a rich set of tools for visualizing the data, intermediate and final results, as well as for interaction with created figures. It also provides tools for analyzing the classification accuracy. In this example we took the Demo Train tutorial, simplified the training sections and expanded the visulaization part. First we estimate the quality of classification with confusion matrix, then we visualize the feature distributions for defined classes in the training dataset as well as the node and edge potentials. For user interaction capacity we define additional functions for handling the mouse clicks over the figures.
#include "DGM.h"
#include "VIS.h"
typedef struct {
int imgWidth;
} USER_DATA;
int main(int argv, char *argc[])
{
const CvSize imgSize = cvSize(400, 400);
const int width = imgSize.width;
const int height = imgSize.height;
const unsigned int nStates = 6;
const unsigned int nFeatures = 3;
if (argv != 4) {
print_help();
return 0;
}
Mat img = imread(argc[1], 1); resize(img, img, imgSize, 0, 0, INTER_LANCZOS4);
Mat fv = imread(argc[2], 1); resize(fv, fv, imgSize, 0, 0, INTER_LANCZOS4);
Mat gt = imread(argc[3], 0); resize(gt, gt, imgSize, 0, 0, INTER_NEAREST);
float params[] = { 400, 0.001f };
size_t params_len = 2;
palette.push_back(std::make_pair(CV_RGB(64, 64, 64), "road"));
palette.push_back(std::make_pair(CV_RGB(0, 255, 255), "tr. island"));
palette.push_back(std::make_pair(CV_RGB(0, 255, 0), "grass"));
palette.push_back(std::make_pair(CV_RGB(200, 135, 70), "agricult."));
palette.push_back(std::make_pair(CV_RGB(64, 128, 0), "tree"));
palette.push_back(std::make_pair(CV_RGB(255, 0, 0), "car"));
vec_string_t featureNames = {"NDVI", "Var. Int.", "Saturation"};
printf("Building the Graph... ");
int64 ticks = getTickCount();
for (int y = 0; y < height; y++)
for (int x = 0; x < width; x++) {
if (x > 0) graph->
addArc(idx, idx - 1);
if (y > 0) graph->
addArc(idx, idx - width);
}
ticks = getTickCount() - ticks;
printf("Done! (%fms)\n", ticks * 1000 / getTickFrequency());
printf("Training... ");
ticks = getTickCount();
ticks = getTickCount() - ticks;
printf("Done! (%fms)\n", ticks * 1000 / getTickFrequency());
printf("Filling the Graph... ");
ticks = getTickCount();
Mat featureVector1(nFeatures, 1, CV_8UC1);
Mat featureVector2(nFeatures, 1, CV_8UC1);
Mat nodePot, edgePot;
for (int y = 0, idx = 0; y < height; y++) {
byte *pFv1 = fv.ptr<byte>(y);
byte *pFv2 = (y > 0) ? fv.ptr<byte>(y - 1) : NULL;
for (int x = 0; x < width; x++, idx++) {
for (word f = 0; f < nFeatures; f++) featureVector1.at<byte>(f, 0) = pFv1[nFeatures * x + f];
if (x > 0) {
for (word f = 0; f < nFeatures; f++) featureVector2.at<byte>(f, 0) = pFv1[nFeatures * (x - 1) + f];
edgePot = edgeTrainer->
getEdgePotentials(featureVector1, featureVector2, params, params_len);
graph->
setArc(idx, idx - 1, edgePot);
}
if (y > 0) {
for (word f = 0; f < nFeatures; f++) featureVector2.at<byte>(f, 0) = pFv2[nFeatures * x + f];
edgePot = edgeTrainer->
getEdgePotentials(featureVector1, featureVector2, params, params_len);
graph->
setArc(idx, idx - width, edgePot);
}
}
}
ticks = getTickCount() - ticks;
printf("Done! (%fms)\n", ticks * 1000 / getTickFrequency());
printf("Decoding... ");
ticks = getTickCount();
std::vector<byte> optimalDecoding = decoder->
decode(10);
ticks = getTickCount() - ticks;
printf("Done! (%fms)\n", ticks * 1000 / getTickFrequency());
Mat solution(imgSize, CV_8UC1, optimalDecoding.data());
char str[255];
sprintf(str,
"Accuracy = %.2f%%", confMat->
getAccuracy());
printf("%s\n", str);
rectangle(img, Point(width - 160, height- 18), Point(width, height), CV_RGB(0,0,0), -1);
putText(img, str, Point(width - 155, height - 5), FONT_HERSHEY_SIMPLEX, 0.45, CV_RGB(225, 240, 255), 1, CV_AA);
imshow("Solution", img);
imshow("Confusion Matrix", cMatImg);
USER_DATA userData;
userData.pGraph = graph;
userData.pMarker = marker;
userData.imgWidth = width;
cvSetMouseCallback("Solution", solutiontWindowMouseHandler, &userData);
cvWaitKey();
return 0;
}
void solutiontWindowMouseHandler(int Event, int x, int y, int flags, void *param)
{
USER_DATA * pUserData = static_cast<USER_DATA *>(param);
if (Event == CV_EVENT_LBUTTONDOWN) {
Mat pot, potImg;
size_t node_id = pUserData->imgWidth * y + x;
pUserData->pGraph->getNode(node_id, pot);
potImg = pUserData->pMarker->drawPotentials(pot, MARK_BW);
imshow("Node Potential", potImg);
vec_size_t child_nodes;
pUserData->pGraph->getChildNodes(node_id, child_nodes);
if (child_nodes.size() > 0) {
pUserData->pGraph->getEdge(node_id, child_nodes.at(0), pot);
potImg = pUserData->pMarker->drawPotentials(pot, MARK_BW);
imshow("Edge Potential", potImg);
}
pot.release();
potImg.release();
}
}