Commit 986207ab564ab268f5985445c9e8e8d3847d70bc
1 parent
ec4f9012
Addressed comments
Cosmetics, used QProcess instead of system, used File::contains and File::get, eliminated RectToString()
Showing
1 changed file
with
52 additions
and
65 deletions
openbr/plugins/cascade.cpp
| ... | ... | @@ -19,7 +19,7 @@ |
| 19 | 19 | #include "openbr_internal.h" |
| 20 | 20 | #include "openbr/core/opencvutils.h" |
| 21 | 21 | #include "openbr/core/resource.h" |
| 22 | -#include <stdlib.h> | |
| 22 | +#include <QProcess> | |
| 23 | 23 | |
| 24 | 24 | using namespace cv; |
| 25 | 25 | |
| ... | ... | @@ -31,8 +31,8 @@ struct TrainParams |
| 31 | 31 | QString info; // Description file of source images. Either this or img is REQUIRED |
| 32 | 32 | QString bg; // REQUIRED: Filepath to background list file |
| 33 | 33 | int num; // Number of samples to generate |
| 34 | - int bgcolor; // Background color supplied image (via img) | |
| 35 | - int bgthresh; // Threshold to determine bgcolor match | |
| 34 | + int bgcolor; // Background color supplied image (via img) | |
| 35 | + int bgthresh; // Threshold to determine bgcolor match | |
| 36 | 36 | bool inv; // Invert colors |
| 37 | 37 | bool randinv; // Randomly invert colors |
| 38 | 38 | int maxidev; // Max intensity deviation of foreground pixels |
| ... | ... | @@ -87,15 +87,15 @@ struct TrainParams |
| 87 | 87 | } |
| 88 | 88 | }; |
| 89 | 89 | |
| 90 | -QString buildTrainingArgs(TrainParams params) | |
| 90 | +QString buildTrainingArgs(const TrainParams params) | |
| 91 | 91 | { |
| 92 | 92 | QString args = ""; |
| 93 | 93 | if (params.data != "") args += "-data " + params.data + " "; |
| 94 | - else return ""; | |
| 94 | + else qFatal("Must specify storage location for cascade"); | |
| 95 | 95 | if (params.vec != "") args += "-vec " + params.vec + " "; |
| 96 | - else return ""; | |
| 96 | + else qFatal("Must specify location of positive vector"); | |
| 97 | 97 | if (params.bg != "") args += "-bg " + params.bg + " "; |
| 98 | - else return ""; | |
| 98 | + else qFatal("Must specify negative images"); | |
| 99 | 99 | if (params.numPos >= 0) args += "-numPos " + QString::number(params.numPos) + " "; |
| 100 | 100 | if (params.numNeg >= 0) args += "-numNeg " + QString::number(params.numNeg) + " "; |
| 101 | 101 | if (params.numStages >= 0) args += "-numStages " + QString::number(params.numStages) + " "; |
| ... | ... | @@ -105,9 +105,9 @@ QString buildTrainingArgs(TrainParams params) |
| 105 | 105 | if (params.stageType != "") args += "-stageType " + params.stageType + " "; |
| 106 | 106 | if (params.featureType != "") args += "-featureType " + params.featureType + " "; |
| 107 | 107 | if (params.w >= 0) args += "-w " + QString::number(params.w) + " "; |
| 108 | - else return ""; | |
| 108 | + else qFatal("Must specify width"); | |
| 109 | 109 | if (params.h >= 0) args += "-h " + QString::number(params.h) + " "; |
| 110 | - else return ""; | |
| 110 | + else qFatal("Must specify height"); | |
| 111 | 111 | if (params.bt != "") args += "-bt " + params.bt + " "; |
| 112 | 112 | if (params.minHitRate >= 0) args += "-minHitRate " + QString::number(params.minHitRate) + " "; |
| 113 | 113 | if (params.maxFalseAlarmRate >= 0) args += "-maxFalseAlarmRate " + QString::number(params.maxFalseAlarmRate) + " "; |
| ... | ... | @@ -118,15 +118,14 @@ QString buildTrainingArgs(TrainParams params) |
| 118 | 118 | return args; |
| 119 | 119 | } |
| 120 | 120 | |
| 121 | - | |
| 122 | -QString buildSampleArgs(TrainParams params) | |
| 121 | +QString buildSampleArgs(const TrainParams params) | |
| 123 | 122 | { |
| 124 | 123 | QString args = ""; |
| 125 | 124 | if (params.vec != "") args += "-vec "+params.vec+" "; |
| 126 | - else return ""; | |
| 125 | + else qFatal("Must specify location of positive vector"); | |
| 127 | 126 | if (params.img != "") args += "-img " + params.img + " "; |
| 128 | 127 | else if (params.info != "") args += "-info " + params.info + " "; |
| 129 | - else return ""; | |
| 128 | + else qFatal("Must specify positive images"); | |
| 130 | 129 | if (params.bg != "") args += "-bg " + params.bg + " "; |
| 131 | 130 | if (params.num > 0) args += "-num " + QString::number(params.num) + " "; |
| 132 | 131 | if (params.bgcolor >=0 ) args += "-bgcolor " + QString::number(params.bgcolor) + " "; |
| ... | ... | @@ -149,31 +148,24 @@ void execCommand(QString cmd, QString args) |
| 149 | 148 | cmd += ".exe"; |
| 150 | 149 | #endif |
| 151 | 150 | cmd += " " + args; |
| 152 | - system(cmd.toLocal8Bit().data()); | |
| 151 | + QProcess::execute(cmd); | |
| 153 | 152 | } |
| 154 | 153 | |
| 155 | -void genSamples(TrainParams params, QString argStr = "") | |
| 154 | +void genSamples(const TrainParams params, const QString argStr = "") | |
| 156 | 155 | { |
| 157 | 156 | QString cmdArgs = buildSampleArgs(params); |
| 158 | 157 | if (argStr != "") cmdArgs += " " + argStr; |
| 159 | 158 | execCommand("opencv_createsamples",cmdArgs); |
| 160 | 159 | } |
| 161 | 160 | |
| 162 | - | |
| 163 | -void trainCascade(TrainParams params,QString argStr = "") | |
| 161 | +void trainCascade(const TrainParams params, const QString argStr = "") | |
| 164 | 162 | { |
| 165 | 163 | QString cmdArgs = buildTrainingArgs(params); |
| 166 | 164 | if (argStr != "") cmdArgs += " " + argStr; |
| 167 | 165 | |
| 168 | 166 | execCommand("opencv_traincascade", cmdArgs); |
| 169 | 167 | } |
| 170 | - | |
| 171 | -QString rectToString(QRectF r) | |
| 172 | -{ | |
| 173 | - QString out = " " + QString::number(r.x()) + " " + QString::number(r.y()) + " " + QString::number(r.width()) + " "+ QString::number(r.height()); | |
| 174 | - return out; | |
| 175 | -} | |
| 176 | - | |
| 168 | + | |
| 177 | 169 | namespace br |
| 178 | 170 | { |
| 179 | 171 | |
| ... | ... | @@ -215,11 +207,11 @@ private: |
| 215 | 207 | } |
| 216 | 208 | }; |
| 217 | 209 | |
| 218 | - | |
| 219 | 210 | /*! |
| 220 | 211 | * \ingroup transforms |
| 221 | 212 | * \brief Wraps OpenCV cascade classifier |
| 222 | 213 | * \author Josh Klontz \cite jklontz |
| 214 | + * \author David Crouse \cite dgcrouse | |
| 223 | 215 | */ |
| 224 | 216 | class CascadeTransform : public MetaTransform |
| 225 | 217 | { |
| ... | ... | @@ -248,33 +240,31 @@ class CascadeTransform : public MetaTransform |
| 248 | 240 | Q_PROPERTY(bool show READ get_show WRITE set_show RESET reset_show STORED false) |
| 249 | 241 | Q_PROPERTY(bool baseFormatSave READ get_baseFormatSave WRITE set_baseFormatSave RESET reset_baseFormatSave STORED false) |
| 250 | 242 | Q_PROPERTY(bool overwrite READ get_overwrite WRITE set_overwrite RESET reset_overwrite STORED false) |
| 251 | - | |
| 252 | - | |
| 243 | + | |
| 253 | 244 | BR_PROPERTY(QString, model, "FrontalFace") |
| 254 | 245 | BR_PROPERTY(int, minSize, 64) |
| 255 | 246 | BR_PROPERTY(bool, ROCMode, false) |
| 256 | 247 | |
| 257 | - // Training parameters - Default values provided trigger OpenCV defaults | |
| 248 | + // Training parameters - Default values provided trigger OpenCV defaults | |
| 258 | 249 | BR_PROPERTY(int, numStages, -1) |
| 259 | - BR_PROPERTY(int,w,-1) | |
| 260 | - BR_PROPERTY(int,h,-1) | |
| 261 | - BR_PROPERTY(int,numPos,-1) | |
| 262 | - BR_PROPERTY(int,numNeg,-1) | |
| 263 | - BR_PROPERTY(int,precalcValBufSize,-1) | |
| 264 | - BR_PROPERTY(int,precalcIdxBufSize,-1) | |
| 265 | - BR_PROPERTY(double,minHitRate,-1) | |
| 266 | - BR_PROPERTY(double,maxFalseAlarmRate,-1) | |
| 267 | - BR_PROPERTY(double,weightTrimRate,-1) | |
| 268 | - BR_PROPERTY(int,maxDepth,-1) | |
| 269 | - BR_PROPERTY(int,maxWeakCount,-1) | |
| 270 | - BR_PROPERTY(QString,stageType,"") | |
| 271 | - BR_PROPERTY(QString,featureType,"") | |
| 272 | - BR_PROPERTY(QString,bt,"") | |
| 273 | - BR_PROPERTY(QString,mode,"") | |
| 274 | - BR_PROPERTY(bool,show,false) | |
| 275 | - BR_PROPERTY(bool,baseFormatSave,false) | |
| 276 | - BR_PROPERTY(bool,overwrite,false) | |
| 277 | - | |
| 250 | + BR_PROPERTY(int, w, -1) | |
| 251 | + BR_PROPERTY(int, h, -1) | |
| 252 | + BR_PROPERTY(int, numPos, -1) | |
| 253 | + BR_PROPERTY(int, numNeg, -1) | |
| 254 | + BR_PROPERTY(int, precalcValBufSize, -1) | |
| 255 | + BR_PROPERTY(int, precalcIdxBufSize, -1) | |
| 256 | + BR_PROPERTY(double, minHitRate, -1) | |
| 257 | + BR_PROPERTY(double, maxFalseAlarmRate, -1) | |
| 258 | + BR_PROPERTY(double, weightTrimRate, -1) | |
| 259 | + BR_PROPERTY(int, maxDepth, -1) | |
| 260 | + BR_PROPERTY(int, maxWeakCount, -1) | |
| 261 | + BR_PROPERTY(QString, stageType, "") | |
| 262 | + BR_PROPERTY(QString, featureType, "") | |
| 263 | + BR_PROPERTY(QString, bt, "") | |
| 264 | + BR_PROPERTY(QString, mode, "") | |
| 265 | + BR_PROPERTY(bool, show, false) | |
| 266 | + BR_PROPERTY(bool, baseFormatSave, false) | |
| 267 | + BR_PROPERTY(bool, overwrite, false) | |
| 278 | 268 | |
| 279 | 269 | Resource<CascadeClassifier> cascadeResource; |
| 280 | 270 | |
| ... | ... | @@ -295,8 +285,7 @@ class CascadeTransform : public MetaTransform |
| 295 | 285 | } |
| 296 | 286 | |
| 297 | 287 | FileList files = data.files(); |
| 298 | - | |
| 299 | - | |
| 288 | + | |
| 300 | 289 | // Open positive and negative list files |
| 301 | 290 | QString posFName = "pos.txt"; |
| 302 | 291 | QString negFName = "neg.txt"; |
| ... | ... | @@ -307,13 +296,12 @@ class CascadeTransform : public MetaTransform |
| 307 | 296 | QTextStream posStream(&posFile); |
| 308 | 297 | QTextStream negStream(&negFile); |
| 309 | 298 | |
| 310 | - | |
| 311 | 299 | const QString endln = "\r\n"; |
| 312 | 300 | |
| 313 | 301 | int posCount = 0; |
| 314 | 302 | int negCount = 0; |
| 315 | 303 | |
| 316 | - bool buildPos = false; // If true, build positive vector from single image | |
| 304 | + bool buildPos = false; // If true, build positive vector from single image | |
| 317 | 305 | |
| 318 | 306 | TrainParams params; |
| 319 | 307 | |
| ... | ... | @@ -341,8 +329,8 @@ class CascadeTransform : public MetaTransform |
| 341 | 329 | |
| 342 | 330 | for (int i = 0; i < files.length(); i++){ |
| 343 | 331 | File f = files[i]; |
| 344 | - if (f.localKeys().contains("training-set")){ | |
| 345 | - QString tset = f.localMetadata()["training-set"].toString().toLower(); | |
| 332 | + if (f.contains("training-set")){ | |
| 333 | + QString tset = f.get<QString>("training-set",QString()).toLower(); | |
| 346 | 334 | |
| 347 | 335 | // Negative samples |
| 348 | 336 | if (tset == "neg"){ |
| ... | ... | @@ -358,7 +346,8 @@ class CascadeTransform : public MetaTransform |
| 358 | 346 | |
| 359 | 347 | // Extract rectangles |
| 360 | 348 | for (int j = 0; j < f.rects().length(); j++){ |
| 361 | - rects += rectToString(f.rects()[j]); | |
| 349 | + QRectF r = f.rects()[j]; | |
| 350 | + rects += " " + QString::number(r.x()) + " " + QString::number(r.y()) + " " + QString::number(r.width()) + " "+ QString::number(r.height()); | |
| 362 | 351 | posCount++; |
| 363 | 352 | } |
| 364 | 353 | if (f.rects().length() > 0) |
| ... | ... | @@ -371,15 +360,15 @@ class CascadeTransform : public MetaTransform |
| 371 | 360 | params.img = f.path() + QDir::separator() + f.fileName(); |
| 372 | 361 | |
| 373 | 362 | // Parse settings (unique to this one tag) |
| 374 | - if (f.localKeys().contains("num")) params.num = f.localMetadata()["num"].toInt(); | |
| 375 | - if (f.localKeys().contains("bgcolor")) params.bgcolor = f.localMetadata()["bgcolor"].toInt(); | |
| 376 | - if (f.localKeys().contains("bgthresh")) params.bgthresh = f.localMetadata()["bgthresh"].toInt(); | |
| 377 | - if (f.localKeys().contains("inv")) params.inv = f.localMetadata()["inv"].toBool(); | |
| 378 | - if (f.localKeys().contains("randinv")) params.randinv = f.localMetadata()["randinv"].toBool(); | |
| 379 | - if (f.localKeys().contains("maxidev")) params.maxidev = f.localMetadata()["maxidev"].toInt(); | |
| 380 | - if (f.localKeys().contains("maxxangle")) params.maxxangle = f.localMetadata()["maxxangle"].toDouble(); | |
| 381 | - if (f.localKeys().contains("maxyangle")) params.maxyangle = f.localMetadata()["maxyangle"].toDouble(); | |
| 382 | - if (f.localKeys().contains("maxzangle")) params.maxzangle = f.localMetadata()["maxzangle"].toDouble(); | |
| 363 | + if (f.contains("num")) params.num = f.get<int>("num",0); | |
| 364 | + if (f.contains("bgcolor")) params.bgcolor = f.get<int>("bgcolor",0); | |
| 365 | + if (f.contains("bgthresh")) params.bgthresh =f.get<int>("bgthresh",0); | |
| 366 | + if (f.contains("inv")) params.inv = f.get<bool>("inv",false); | |
| 367 | + if (f.contains("randinv")) params.randinv = f.get<bool>("randinv",false); | |
| 368 | + if (f.contains("maxidev")) params.maxidev = f.get<int>("maxidev",0); | |
| 369 | + if (f.contains("maxxangle")) params.maxxangle = f.get<double>("maxxangle",0); | |
| 370 | + if (f.contains("maxyangle")) params.maxyangle = f.get<double>("maxyangle",0); | |
| 371 | + if (f.contains("maxzangle")) params.maxzangle = f.get<double>("maxzangle",0); | |
| 383 | 372 | } |
| 384 | 373 | } |
| 385 | 374 | } |
| ... | ... | @@ -408,13 +397,11 @@ class CascadeTransform : public MetaTransform |
| 408 | 397 | params.numNeg = negCount*10; |
| 409 | 398 | } |
| 410 | 399 | |
| 411 | - | |
| 412 | 400 | genSamples(params); |
| 413 | 401 | trainCascade(params); |
| 414 | 402 | if (posFile.exists()) posFile.remove(); |
| 415 | 403 | negFile.remove(); |
| 416 | 404 | } |
| 417 | - | |
| 418 | 405 | |
| 419 | 406 | void project(const Template &src, Template &dst) const |
| 420 | 407 | { | ... | ... |