OZ++ Sample: CustomYoloObjectDetector |
/******************************************************************************
*
* Copyright (c) 2019 Antillia.com TOSHIYUKI ARAI. ALL RIGHTS RESERVED.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer.
*
* 2. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*
* CustomYoloObjectDetector.cpp
*
*****************************************************************************/
//2019/06/09
//#define OPENCV
#include <opencv2/stitching.hpp>
#include <oz++/motif/Label.h>
#include <oz++/motif/RowColumn.h>
#include <oz++/motif/LabeledComboBox.h>
#include <oz++/motif/LabeledTrackBar.h>
#include <oz++/motif/DropdownScaler.h>
#include <oz++/opencv/OpenCVMainView.h>
#include <oz++/opencv/OpenCVScrolledImageView.h>
#include <oz++/motif/FileOpenDialog.h>
#include <oz++/motif/ScrolledTableView.h>
#include <oz++/ConfigParser.h>
#include <oz++/yolov3/Detector3.h>
#include <oz++/yolov3/DetectedObjectList.h>
namespace OZ {
class MainView :public OpenCVMainView {
private:
///////////////////////////////////////////////
class DetectedImageView: public OpenCVScrolledImageView {
private:
cv::Mat originalImage;
cv::Mat scaledImage;
virtual void display()
{
show(scaledImage);
}
public:
DetectedImageView(View* parent, const char* name, Args& args)
:OpenCVScrolledImageView(parent, name, args)
{
try {
const char* filename = (const char*)args.get(XmNimageFileName);
int imageLoadingFlag = args.get(XmNimageLoadingFlag);
int scalingRatio = (int)args.get(XmNimageScalingRatio);
loadImage(filename, imageLoadingFlag, scalingRatio);
} catch (OZ::Exception ex) {
caught(ex);
}
}
~DetectedImageView()
{
}
void loadImage(const char* filename,
int imageLoadingFlag= CV_LOAD_IMAGE_COLOR,
int scalingRatio=100)
{
originalImage = readImage(filename, imageLoadingFlag);
scaleImage(originalImage, scaledImage, scalingRatio);
refresh();
}
void setImage(cv::Mat& image, int scalingRatio=100 )
{
originalImage = image;
rescale(scalingRatio);
}
void rescale(int scalingRatio)
{
scaledImage.release();
scaleImage(originalImage, scaledImage, scalingRatio);
}
};
private:
std::string imageFile;
std::string csv_filename;
int imageLoadingFlag = CV_LOAD_IMAGE_COLOR;
int imageScalingRatio =80; //percentage
ConfigParser parser;
SmartPtr<Detector3> detector;
std::string darknet_root;
std::string cfg_filename;
std::string coco_filename;
std::string weight_filename;
SmartPtr<DetectedImageView> detectedImage;
SmartPtr<Form> controlPane;
SmartPtr<DetectedObjectList> objectList;
SmartPtr<RowColumn> topPane;
SmartPtr<Label> label;
SmartPtr<DropdownScaler> scaleComboBox;
SmartPtr<PushButton> reloadButton;
SmartPtr<PushButton> detectButton;
SmartPtr<FileOpenDialog> fileDialog;
public:
void cancel(Action& action)
{
fileDialog->popdown();
}
void fileOpen(Action& action)
{
fileDialog->popup();
}
void scaleChanged(Action& action)
{
int val = scaleComboBox->getScale();
if (val > 0 && imageScalingRatio != val) {
imageScalingRatio = val;
detectedImage -> rescale(imageScalingRatio);
}
}
void updateTitle(const char* filename)
{
std::string appname = getAppName();
std::string title = filename;
title += std::string(" - ");
title += appname;
setTitle(title.c_str());
}
void ok(Action& action)
{
try {
imageFile = fileDialog->getFileName();
const char* filename = (const char*)imageFile.c_str();
printf("filename: %s\n", filename);
fileDialog->popdown();
detectedImage ->loadImage(filename, imageLoadingFlag, imageScalingRatio);
detectedImage->unmap();
detectedImage->map();
csv_filename = createCSVFilename(imageFile);
//resize(width(), height());
updateTitle(filename);
flush();
} catch (OZ::Exception& ex) {
caught(ex);
}
}
void resize(Dimension w, Dimension h)
{
int CP_WIDTH = 330;
int LB_HEIGHT = 30;
int ww = w-CP_WIDTH;
int hh = h - LB_HEIGHT;
if (topPane && detectButton && detectedImage && controlPane ) {
detectButton->get(XmNheight, LB_HEIGHT);
hh = h - LB_HEIGHT -15;
detectedImage -> reshape(0, LB_HEIGHT+5, ww-2, hh-30);
controlPane -> reshape(ww+1, LB_HEIGHT+5, CP_WIDTH-4, hh-30);
}
flush();
}
void reload(Action& event)
{
detectedImage -> loadImage(imageFile.c_str(),
imageLoadingFlag,
imageScalingRatio);
}
std::string createCSVFilename(std::string& filename)
{
std::string csv_fname = filename;
auto pos = filename.rfind("/");
if (pos != std::string::npos) {
std::string nameonly= filename.substr(pos+1);
csv_fname = std::string("./") + nameonly + std::string(".csv");
printf("csv_filename %s\n", csv_fname.c_str());
}
return csv_fname;
}
void detect(Action& event)
{
image timage = detector->detect_image(imageFile.c_str(), csv_filename.c_str());
cv::Mat mat = detector->image_to_mat(timage);
cv::Mat mbgr;
cv::cvtColor(mat, mbgr, cv::COLOR_RGB2BGR);
free_image(timage);
detectedImage->setImage(mbgr, imageScalingRatio);
TableView* tablev = objectList->getTableView();
tablev->removeAllItems();
tablev->readCSVFile(csv_filename);
}
public:
MainView(OpenCVApplication& applet, const char* name, Args& args)
:OpenCVMainView(applet, name, args)
{
imageScalingRatio = 80;
char defaultScale[20] = {0};
sprintf(defaultScale, "%d%%", imageScalingRatio);
printf("%s¥n", defaultScale);
imageLoadingFlag = CV_LOAD_IMAGE_COLOR;
std::string config = "./CustomYoloObjectDetector.ini";
parser.parse(config);
darknet_root = parser.getString("DARKNET_ROOT", "filename");
cfg_filename = parser.getString("CFG_FILE", "filename");
coco_filename = parser.getString("COCO_FILE", "filename");
weight_filename = parser.getString("WEIGHT_FILE", "filename");
BulletinBoard* bboard = getBulletinBoard();
imageFile = "../../images/JRShinjukuStation.2.jpg";
csv_filename = createCSVFilename(imageFile);
// Create a instance oF OZ::Detector3.
detector = new OZ::Detector3(darknet_root, cfg_filename, weight_filename, coco_filename);
try {
Args ar;
ar.set(XmNx, 0);
ar.set(XmNy, 0);
ar.set(XmNmarginHeight, 1);
ar.set(XmNmarginWidth, 1);
ar.set(XmNorientation, XmHORIZONTAL);
ar.set(XmNspacing, 20);
topPane = new RowColumn(bboard, "", ar);
ar.reset();
label = new Label(topPane, "Scale", ar);
ar.reset();
ar.set(XmNdefaultScale, defaultScale);
scaleComboBox = new DropdownScaler(topPane, "", ar);
scaleComboBox->addCallback(XmNselectionCallback, this,
(Callback)&MainView::scaleChanged, NULL);
ar.set(XmNx, 0);
ar.set(XmNy, 0);
ar.set(XmNalignment, XmALIGNMENT_BEGINNING);
reloadButton = new PushButton(topPane, " Reload ", ar);
reloadButton->addCallback(XmNactivateCallback, this,
(Callback)&MainView::reload, NULL);
ar.reset();
ar.set(XmNx, 120);
ar.set(XmNy, 0);
ar.set(XmNalignment, XmALIGNMENT_BEGINNING);
detectButton = new PushButton(topPane, " Detect ", ar);
detectButton->addCallback(XmNactivateCallback, this,
(Callback)&MainView::detect, NULL);
updateTitle((const char*)imageFile.c_str());
ar.reset();
ar.set(XmNimageFileName, imageFile.c_str());
ar.set(XmNimageLoadingFlag, imageLoadingFlag);
ar.set(XmNimageScalingRatio, imageScalingRatio);
detectedImage = new DetectedImageView(bboard, "", ar);
ar.reset();
controlPane = new Form(bboard, "", ar);
ar.reset();
objectList = new DetectedObjectList(controlPane, "objectlist", ar);
ar.reset();
fileDialog = new FileOpenDialog(this, "FileOpenDialog", ar);
fileDialog -> getOkButton()
-> addCallback(XmNactivateCallback, this,
(Callback)&MainView::ok, NULL);
sendConfigureEvent();
} catch(OZ::Exception& ex) {
caught(ex);
}
}
~MainView()
{
}
};
}
//
int main(int argc, char** argv)
{
try {
const char* appclass = argv[0];
OpenCVApplication applet(appclass, argc, argv);
Args args;
args.set(XmNwidth, 1000);
args.set(XmNheight, 480);
MainView view(applet, appclass, args);
view.realize();
applet.run();
} catch (OZ::Exception& ex) {
caught(ex);
}
return 0;
}