SOL9 Sample: YoloObjectDetector
|
1 Screenshot
2 Source code
/*
* YoloObjectDetector.cpp
* Copyright (c) 2019 Antillia.com TOSHIYUKI ARAI. ALL RIGHTS RESERVED.
*/
//2019/05/22
//Simple example to use Detector class of yolo_v2_class.hpp
/*
struct bbox_t {
unsigned int x, y, w, h; // (x,y) - top-left corner, (w, h) - width & height of bounded box
float prob; // confidence - probability that the object was found correctly
unsigned int obj_id; // class of object - from range [0, classes-1]
unsigned int track_id; // tracking id for video (0 - untracked, 1 - inf - tracked object)
unsigned int frames_counter; // counter of frames on which the object was detected
float x_3d, y_3d, z_3d; // center of object (in Meters) if ZED 3D Camera is used
};
struct image_t {
int h; // height
int w; // width
int c; // number of chanels (3 - for RGB)
float *data; // pointer to the image data
};
*/
#define _CONSOLE_
#include <sol/ModuleFileName.h>
#include <sol/DropFiles.h>
#include <sol/ListView.h>
#include <sol/StringList.h>
#include <sol/Profile.h>
#include <sol/StringT.h>
#include <sol/opencv/OpenCVObject.h>
#include <sol/opencv/OpenCVApplicationView.h>
#include <sol/opencv/OpenCVNamedWindow.h>
#include <sol/PushButton.h>
#include <sol/FileDialog.h>
#include <vector>
#include <yolo_v2_class.hpp>
#include "Resource.h"
namespace SOL {
class MainView :public OpenCVApplicationView {
private:
////////////////////////////////////////////////////////////////////////////////////////
//Inner class starts.
class SimpleView :public OpenCVNamedWindow {
private:
StringT<char> filePath;
int loadFlag;
cv::Mat image;
void display()
{
show(image);
}
public:
SimpleView(View* parent, const char* name, Args& args)
:OpenCVNamedWindow(parent, name, args)
{
try {
const char* filename = (const char*)args.get(XmNimageFileName);
int imageLoadingFlag = (int)args.get(XmNimageLoadingFlag);
loadImage(filename, imageLoadingFlag); //"..\\images\\WafukuMannequin.png");
} catch (Exception& ex) {
caught(ex);
}
}
~SimpleView()
{
}
void loadImage(const char* filename, int flag=CV_LOAD_IMAGE_COLOR)
{
try {
filePath = filename;
loadFlag = flag;
image = readImage(filename, flag);
refresh();
} catch (Exception& ex) {
caught(ex);
}
}
void reload()
{
try {
image = readImage((const char*)filePath, loadFlag);
refresh();
} catch (Exception& ex) {
caught(ex);
}
}
void draw_named_rectangles(std::vector<bbox_t>& boxes, std::vector<std::string>& class_names)
{
try {
for (int i = 0; i < boxes.size(); i++){
unsigned int id = boxes[i].obj_id;
std::string name= class_names[id];
char number[10];
sprintf(number, "%d", i);
Scalar color(0, 0, 255);
//Sorry, the following shows a very ugly number string.
//putText(image, number, Point(boxes[i].x, boxes[i].y), FONT_HERSHEY_COMPLEX_SMALL, 0.6, color, 0.2, LINE_AA);
putText(image, number, Point(boxes[i].x, boxes[i].y), FONT_HERSHEY_SCRIPT_SIMPLEX, 0.5, color, 0.1, LINE_AA);
rectangle(image, Point(boxes[i].x, boxes[i].y),
Point (boxes[i].x + boxes[i].w, boxes[i].y + boxes[i].h),
color, 1);
}
refresh();
} catch (Exception& ex) {
caught(ex);
}
}
void writeImage(const char* filename)
{
OpenCVNamedWindow::writeImage(filename, image);
}
};
//Inner class endss
////////////////////////////////////////////////////////////////////////////////////////
StringT<char> imageFile;
StringT<char> savedImageFile;
SmartPtr<Detector> detector;
SmartPtr<SimpleView> view;
SmartPtr<ListView> listv;
SmartPtr<PushButton> reloadButton;
SmartPtr<PushButton> detectButton;
String selectedFolder;
std::string cfg_filename;
std::string coco_filename;
std::string weight_filename;
std::vector<std::string> class_names;
FileDialog filedlg;
Profile profile;
void updateCaption()
{
char caption[MAX_PATH];
sprintf_s(caption, CountOf(caption), "%s - %s",
(const char*)imageFile,
getAppName());
setText(caption);
}
void resize(int w, int h)
{
if (view && listv && detectButton && reloadButton) {
view -> reshape( 0, 40, w-310, h-45);
reloadButton -> reshape(10, 4, 80, 28);
detectButton -> reshape(100 + 10, 4, 80, 28);
listv -> reshape(w-305, 40, 300, h-45);
}
}
void open(Action& action)
{
Args ar;
char dir[MAX_PATH] = {0};
//Restore previously select folder from a registry(profile of this application) for fileDialog
if (profile.getFileFolder(dir, CountOf(dir))) {
ar.set(XmNdirectory, dir);
filedlg.setValues(ar);
}
try {
if(filedlg.open()) {
const char* filename = filedlg.getFileName();
saveFileFolder(filename);
openFile(filename);
}
} catch (Exception& ex) {
caught(ex);
}
}
void reload(Action& action)
{
if (view) {
view ->reload();
}
}
void detect(Action& action)
{
std::string filename((const char*)imageFile);
printf("filename %s\n", (const char*)imageFile);
std::vector<bbox_t> boxes = detector->detect(filename);
size_t len = boxes.size();
listv->clear();
std::string csv_filename = filename + ".csv";
for (size_t i = 0; i<len; i++) {
view->draw_named_rectangles(boxes, class_names);
unsigned int obj_id = boxes[i].obj_id;
std::string name= class_names[obj_id];
char index[10], score[10];
sprintf(index, "%d", i);
sprintf(score, "%.2f", boxes[i].prob);
char x[10], y[10], w[10], h[10];
sprintf(x, "%3d", boxes[i].x);
sprintf(y, "%3d", boxes[i].y);
sprintf(w, "%3d", boxes[i].w);
sprintf(h, "%3d", boxes[i].h);
StringList item;
item.add(index);
item.add(name.c_str());
item.add(score);
item.add(x);
item.add(y);
item.add(w);
item.add(h);
listv->insertLine(i, &item);
}
}
void openFile(const char* filename)
{
try {
listv-> clear();
view -> loadImage(filename, CV_LOAD_IMAGE_COLOR);
imageFile = filename;
const char* fname = strrchr(filename, '\\');
if (fname) {
fname++;
}
imageFile = fname;
updateCaption();
savedImageFile = "";
} catch (Exception& ex) {
caught(ex);
}
}
void dropFiles(Action& action)
{
char fileName[MAX_PATH] = { 0 };
DropFiles drop((HDROP)action.getWParam());
int num = drop.queryFile(0, fileName, CountOf(fileName));
if(num > 0) {
if (filedlg.isImageFileName(fileName)) {
openFile(fileName);
bringUp();
} else {
bringUp(); //Activate and raise this view
showErrorDialog("Invalid image filename", fileName, MB_OK);
}
}
}
void confirm(Action& action)
{
int rc = MessageBox(NULL, "Are you sure to close this window?", "Confirmation",
MB_OKCANCEL|MB_ICONEXCLAMATION);
if (rc == IDOK) {
exit(action);
}
}
void load_class_names(std::string& filename)
{
FILE* fp = fopen(filename.c_str(), "r");
if (fp) {
char buffer[256] = {0};
while( fgets(buffer, sizeof(buffer), fp) != NULL ){
buffer[strlen(buffer)-1] = '\0';
//printf("%s\n", buffer);
std::string class_name(buffer);
class_names.push_back(class_name);
}
fclose(fp);
}
}
const char** getListViewHeader(int& number)
{
static const char* LISTVIEW_HEADER[] = {"id ", "object ", "score", " x ", " y ", " w ", " h "};
number = CountOf(LISTVIEW_HEADER);
return LISTVIEW_HEADER;
}
void readIniFile()
{
// Read some configuration file names from ini file.
char buffer[256] = { 0 };
imageFile = "..\\..\\images\\PoliceCar.jpg";
const char* inifile = ".\\YoloObjectDetector.ini";
GetPrivateProfileString("CFG_FILE", "filename", "", buffer, sizeof(buffer), inifile);
cfg_filename = buffer;
printf("CFG_FILE:%s\n", buffer);
GetPrivateProfileString("WEIGHT_FILE", "filename", "", buffer, sizeof(buffer), inifile);
weight_filename = buffer;
printf("WEIGHT_FILE:%s\n", buffer);
GetPrivateProfileString("COCO_FILE", "filename", "", buffer, sizeof(buffer), inifile);
coco_filename = buffer;
printf("COCO_FILE:%s\n", buffer);
}
public:
MainView(OpenCVApplication& applet, const char* name, Args& args)
:OpenCVApplicationView(applet, name, args)
{
try {
readIniFile();
detector = new Detector(cfg_filename, weight_filename);
load_class_names(coco_filename);
Args ar;
ar.reset();
ar.set(XmNimageFileName, imageFile);
ar.set(XmNimageLoadingFlag, CV_LOAD_IMAGE_COLOR);
view = new SimpleView(this, "cvwindow", ar);
view -> addCallback(XmNdropCallback, this,
(Callback)&MainView::dropFiles, NULL);
ar.reset();
ar.set(XmNexStyle, (LONG_PTR)WS_EX_CLIENTEDGE);
ar.set(XmNstyle, (LONG_PTR)LVS_REPORT);
listv = new ListView(this, "objects", ar);
StringList header;
int number = 0;
const char** strings = getListViewHeader(number);
for (int i = 0; i<number; i++) {
header.add(strings[i]);
}
listv->clear();
listv->setColumn(&header);
ar.reset();
reloadButton = new PushButton(this, "Reload", ar);
reloadButton -> addCallback(XmNactivateCallback, this,
(Callback)&MainView::reload, NULL);
ar.reset();
detectButton = new PushButton(this, "Detect", ar);
detectButton -> addCallback(XmNactivateCallback, this,
(Callback)&MainView::detect, NULL);
ar.reset();
ar.set(XmNfilter, FileDialog::getImageFilesFilter());
filedlg.create(this, "OpenFile", ar);
addCallback(XmNmenuCallback, IDM_OPEN, this,
(Callback)&MainView::open, NULL);
addCallback(XmNmenuCallback, IDM_EXIT, this,
(Callback)&MainView::confirm, NULL);
updateCaption();
} catch (Exception& ex) {
caught(ex);
}
}
~MainView()
{
}
void save(Action& action)
{
try {
if (!savedImageFile.isEmpty()) {
//Write detected image into the filename.
view->writeImage(savedImageFile);
} else {
saveAs(action);
}
} catch (Exception& ex) {
caught(ex);
}
}
//2017/12/01
void saveAs(Action& action)
{
Args ar;
char dir[MAX_PATH] = { 0 };
if (restoreFileFolder(dir, CountOf(dir))) {
ar.set(XmNdirectory, dir);
filedlg.setValues(ar);
}
try {
if(filedlg.save()) {
const char* filename = filedlg.getFileName();
saveFileFolder(filename);
//Write detected image into the filename.
view->writeImage(filename);
savedImageFile = filename;
}
} catch (Exception& ex) {
caught(ex);
}
}
};
}
//
void main(int argc, char** argv)
{
try {
ModuleFileName module(argv[0]);
const char* name = module.getAppName();
OpenCVApplication applet(name, argc, argv);
Args args;
args.set(XmNwidth, 1000);
args.set(XmNheight, 500);
MainView view(applet, name, args);
view.realize();
applet.run();
} catch (SOL::Exception& ex) {
caught(ex);
}
}
Last modified: 22 May 2019
Copyright (c) 2019 Antillia.com ALL RIGHTS RESERVED.