Commit d240b48a3fa0cc4583b3fe8b36ec9e208746138e
1 parent
9e3e99a4
More updates for procrustes and delaunay
Showing
5 changed files
with
60 additions
and
30 deletions
openbr/core/core.cpp
| ... | ... | @@ -167,7 +167,6 @@ struct AlgorithmCore |
| 167 | 167 | } |
| 168 | 168 | |
| 169 | 169 | const float speed = 1000 * Globals->totalSteps / Globals->startTime.elapsed() / std::max(1, abs(Globals->parallelism)); |
| 170 | - qDebug() << Globals->startTime.elapsed(); | |
| 171 | 170 | if (!Globals->quiet && (Globals->totalSteps > 1)) |
| 172 | 171 | fprintf(stderr, "\rSPEED=%.1e SIZE=%.4g FAILURES=%d/%d \n", |
| 173 | 172 | speed, totalBytes/totalCount, failureCount, totalCount); | ... | ... |
openbr/core/plot.cpp
| ... | ... | @@ -247,8 +247,8 @@ float Evaluate(const Mat &simmat, const Mat &mask, const QString &csv) |
| 247 | 247 | } |
| 248 | 248 | |
| 249 | 249 | // Write FAR/TAR Bar Chart (BC) |
| 250 | - lines.append(qPrintable(QString("BC,0.001,%1").arg(QString::number(result = getTAR(operatingPoints, 0.001), 'f', 3)))); | |
| 251 | - lines.append(qPrintable(QString("BC,0.01,%1").arg(QString::number(getTAR(operatingPoints, 0.01), 'f', 3)))); | |
| 250 | + lines.append(qPrintable(QString("BC,0.001,%1").arg(QString::number(getTAR(operatingPoints, 0.001), 'f', 3)))); | |
| 251 | + lines.append(qPrintable(QString("BC,0.01,%1").arg(QString::number(result = getTAR(operatingPoints, 0.01), 'f', 3)))); | |
| 252 | 252 | |
| 253 | 253 | // Write SD & KDE |
| 254 | 254 | points = qMin(qMin(Max_Points, genuines.size()), impostors.size()); |
| ... | ... | @@ -287,7 +287,7 @@ float Evaluate(const Mat &simmat, const Mat &mask, const QString &csv) |
| 287 | 287 | } |
| 288 | 288 | |
| 289 | 289 | if (!csv.isEmpty()) QtUtils::writeFile(csv, lines); |
| 290 | - qDebug("TAR @ FAR = 0.001: %.3f\nRetrieval Rate @ Rank = %d: %.3f", result, Report_Retrieval, reportRetrievalRate); | |
| 290 | + qDebug("TAR @ FAR = 0.01: %.3f\nRetrieval Rate @ Rank = %d: %.3f", result, Report_Retrieval, reportRetrievalRate); | |
| 291 | 291 | return result; |
| 292 | 292 | } |
| 293 | 293 | ... | ... |
openbr/plugins/format.cpp
| ... | ... | @@ -659,8 +659,8 @@ class xmlFormat : public Format |
| 659 | 659 | QDomDocument doc(fileName); |
| 660 | 660 | QFile f(fileName); |
| 661 | 661 | |
| 662 | - if (!f.open(QIODevice::ReadOnly)) qFatal("Unable to open %s for reading.", qPrintable(file.flat())); | |
| 663 | - if (!doc.setContent(&f)) qFatal("Unable to parse %s.", qPrintable(file.flat())); | |
| 662 | + if (!f.open(QIODevice::ReadOnly)) qWarning("Unable to open %s for reading.", qPrintable(file.flat())); | |
| 663 | + if (!doc.setContent(&f)) qWarning("Unable to parse %s.", qPrintable(file.flat())); | |
| 664 | 664 | f.close(); |
| 665 | 665 | |
| 666 | 666 | QDomElement docElem = doc.documentElement(); | ... | ... |
openbr/plugins/landmarks.cpp
| ... | ... | @@ -81,6 +81,12 @@ class ProcrustesTransform : public Transform |
| 81 | 81 | QList<QPointF> points = src.file.points(); |
| 82 | 82 | QList<QRectF> rects = src.file.rects(); |
| 83 | 83 | |
| 84 | + if (points.empty() || rects.empty()) { | |
| 85 | + dst = src; | |
| 86 | + qWarning("Points/rects are empty."); | |
| 87 | + return; | |
| 88 | + } | |
| 89 | + | |
| 84 | 90 | if (rects.size() > 1) qWarning("More than one rect in training data templates."); |
| 85 | 91 | |
| 86 | 92 | points.append(rects[0].topLeft()); |
| ... | ... | @@ -95,8 +101,8 @@ class ProcrustesTransform : public Transform |
| 95 | 101 | Eigen::MatrixXf srcPoints(points.size(), 2); |
| 96 | 102 | |
| 97 | 103 | for (int i = 0; i < points.size(); i++) { |
| 98 | - srcPoints(i,0) = points[i].x()/(norm/150.)+50; | |
| 99 | - srcPoints(i,1) = points[i].y()/(norm/150.)+50; | |
| 104 | + srcPoints(i,0) = points[i].x()/(norm/100.)+50; | |
| 105 | + srcPoints(i,1) = points[i].y()/(norm/100.)+50; | |
| 100 | 106 | } |
| 101 | 107 | |
| 102 | 108 | Eigen::JacobiSVD<Eigen::MatrixXf> svd(srcPoints.transpose()*meanShape, Eigen::ComputeThinU | Eigen::ComputeThinV); |
| ... | ... | @@ -140,11 +146,18 @@ class DelaunayTransform : public UntrainableTransform |
| 140 | 146 | |
| 141 | 147 | void project(const Template &src, Template &dst) const |
| 142 | 148 | { |
| 149 | + | |
| 143 | 150 | Subdiv2D subdiv(Rect(0,0,src.m().cols,src.m().rows)); |
| 144 | 151 | |
| 145 | 152 | QList<cv::Point2f> points = OpenCVUtils::toPoints(src.file.points()); |
| 146 | 153 | QList<QRectF> rects = src.file.rects(); |
| 147 | 154 | |
| 155 | + if (points.empty() || rects.empty()) { | |
| 156 | + dst = src; | |
| 157 | + qWarning("Points/rects are empty."); | |
| 158 | + return; | |
| 159 | + } | |
| 160 | + | |
| 148 | 161 | if (rects.size() > 1) qWarning("More than one rect in training data templates."); |
| 149 | 162 | |
| 150 | 163 | points.append(OpenCVUtils::toPoint(rects[0].topLeft())); |
| ... | ... | @@ -176,7 +189,6 @@ class DelaunayTransform : public UntrainableTransform |
| 176 | 189 | |
| 177 | 190 | if (inside) { |
| 178 | 191 | count++; |
| 179 | - qDebug() << count << pt[0] << pt[1] << pt[2] << "Area" << contourArea(pt); | |
| 180 | 192 | |
| 181 | 193 | QList<Point> triangleBuffer; |
| 182 | 194 | |
| ... | ... | @@ -209,38 +221,36 @@ class DelaunayTransform : public UntrainableTransform |
| 209 | 221 | mean[0] = src.file.get<float>("Procrustes_mean_0"); |
| 210 | 222 | mean[1] = src.file.get<float>("Procrustes_mean_1"); |
| 211 | 223 | |
| 212 | - qDebug() << mean[0] << mean[1]; | |
| 213 | - | |
| 214 | 224 | float norm = src.file.get<float>("Procrustes_norm"); |
| 215 | 225 | |
| 216 | - qDebug() << norm; | |
| 217 | - | |
| 218 | 226 | dst.m() = Mat::zeros(src.m().rows,src.m().cols,src.m().type()); |
| 219 | 227 | |
| 220 | - foreach(const QList<Point> &triangle, validTriangles) { | |
| 221 | - Eigen::MatrixXf srcPoints(triangle.size(), 2); | |
| 228 | + QList<Point2f> mappedPoints; | |
| 222 | 229 | |
| 223 | - for (int j = 0; j < triangle.size(); j++) { | |
| 224 | - srcPoints(j,0) = (triangle[j].x-mean[0])/(norm/150.)+50; | |
| 225 | - srcPoints(j,1) = (triangle[j].y-mean[1])/(norm/150.)+50; | |
| 230 | + for (int i = 0; i < validTriangles.size(); i++) { | |
| 231 | + Eigen::MatrixXf srcMat(validTriangles[i].size(), 2); | |
| 232 | + | |
| 233 | + for (int j = 0; j < validTriangles[i].size(); j++) { | |
| 234 | + srcMat(j,0) = (validTriangles[i][j].x-mean[0])/(norm/100.)+50; | |
| 235 | + srcMat(j,1) = (validTriangles[i][j].y-mean[1])/(norm/100.)+50; | |
| 226 | 236 | } |
| 227 | 237 | |
| 228 | - Eigen::MatrixXf dstMat = srcPoints*R; | |
| 238 | + Eigen::MatrixXf dstMat = srcMat*R; | |
| 239 | + | |
| 240 | + Point2f srcPoints[3]; | |
| 241 | + for (int j = 0; j < 3; j++) srcPoints[j] = validTriangles[i][j]; | |
| 229 | 242 | |
| 230 | - Point2f test[3]; | |
| 231 | - test[0] = triangle[0]; | |
| 232 | - test[1] = triangle[1]; | |
| 233 | - test[2] = triangle[2]; | |
| 234 | 243 | Point2f dstPoints[3]; |
| 235 | - dstPoints[0] = Point2f(dstMat(0,0),dstMat(0,1)); | |
| 236 | - dstPoints[1] = Point2f(dstMat(1,0),dstMat(1,1)); | |
| 237 | - dstPoints[2] = Point2f(dstMat(2,0),dstMat(2,1)); | |
| 244 | + for (int j = 0; j < 3; j++) { | |
| 245 | + dstPoints[j] = Point2f(dstMat(j,0),dstMat(j,1)); | |
| 246 | + mappedPoints.append(dstPoints[j]); | |
| 247 | + } | |
| 238 | 248 | |
| 239 | 249 | Mat buffer(src.m().rows,src.m().cols,src.m().type()); |
| 240 | 250 | |
| 241 | - warpAffine(src.m(), buffer, getAffineTransform(test, dstPoints), Size(src.m().cols,src.m().rows)); | |
| 251 | + warpAffine(src.m(), buffer, getAffineTransform(srcPoints, dstPoints), Size(src.m().cols,src.m().rows)); | |
| 242 | 252 | |
| 243 | - Mat mask = Mat::zeros(src.m().rows, src.m().cols, CV_8U); | |
| 253 | + Mat mask = Mat::zeros(src.m().rows, src.m().cols, CV_8UC1); | |
| 244 | 254 | Point maskPoints[1][3]; |
| 245 | 255 | maskPoints[0][0] = dstPoints[0]; |
| 246 | 256 | maskPoints[0][1] = dstPoints[1]; |
| ... | ... | @@ -251,10 +261,31 @@ class DelaunayTransform : public UntrainableTransform |
| 251 | 261 | |
| 252 | 262 | Mat output(src.m().rows,src.m().cols,src.m().type()); |
| 253 | 263 | |
| 264 | + // Optimize | |
| 265 | + if (i > 0) { | |
| 266 | + Mat overlap; | |
| 267 | + bitwise_and(dst.m(),mask,overlap); | |
| 268 | + for (int j = 0; j < overlap.rows; j++) { | |
| 269 | + for (int k = 0; k < overlap.cols; k++) { | |
| 270 | + if (overlap.at<uchar>(k,j) != 0) { | |
| 271 | + mask.at<uchar>(k,j) = 0; | |
| 272 | + } | |
| 273 | + } | |
| 274 | + } | |
| 275 | + } | |
| 276 | + | |
| 254 | 277 | bitwise_and(buffer,mask,output); |
| 255 | 278 | |
| 256 | - dst.m() += output; | |
| 279 | + dst.m() += output; // Need to xor stuff out | |
| 257 | 280 | } |
| 281 | + | |
| 282 | + Rect boundingBox = boundingRect(mappedPoints.toVector().toStdVector()); | |
| 283 | + boundingBox.x += boundingBox.width * .025; | |
| 284 | + boundingBox.y += boundingBox.height * .025; // 0.025 for nose, .05 for mouth, .10 for brow | |
| 285 | + boundingBox.width *= .975; | |
| 286 | + boundingBox.height *= .975; // .975 for nose, .95 for mouth, .925 for brow | |
| 287 | + | |
| 288 | + dst.m() = Mat(dst.m(), boundingBox); | |
| 258 | 289 | } |
| 259 | 290 | } |
| 260 | 291 | ... | ... |
openbr/plugins/stasm4.cpp
| ... | ... | @@ -39,7 +39,7 @@ class StasmInitializer : public Initializer |
| 39 | 39 | Globals->abbreviations.insert("RectFromStasmEyes","RectFromPoints([29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47],0.125,6.0)+Resize(44,164)"); |
| 40 | 40 | Globals->abbreviations.insert("RectFromStasmBrow","RectFromPoints([17, 18, 19, 20, 21, 22, 23, 24],0.15,6)+Resize(28,132)"); |
| 41 | 41 | Globals->abbreviations.insert("RectFromStasmNose","RectFromPoints([48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58],0.15,1.25)"); |
| 42 | - Globals->abbreviations.insert("RectFromStasmMouth","RectFromPoints([59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76],0.3,3.0)+Resize(28,68)"); | |
| 42 | + Globals->abbreviations.insert("RectFromStasmMouth","RectFromPoints([59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76],0.3,2.5)"); | |
| 43 | 43 | } |
| 44 | 44 | }; |
| 45 | 45 | ... | ... |