diff --git a/openbr/core/eval.cpp b/openbr/core/eval.cpp index c2ffb52..0f22840 100755 --- a/openbr/core/eval.cpp +++ b/openbr/core/eval.cpp @@ -1179,6 +1179,8 @@ void EvalEER(const QString &predictedXML, QString gt_property, QString distribut QHash gtLabels; QHash > scores; for (int i=0; i(gt_property); if (gtLabel == 1) @@ -1225,10 +1227,9 @@ void EvalEER(const QString &predictedXML, QString gt_property, QString distribut thres += stepSize; } - qDebug() <<"Class 0 Templates:" << classOneTemplateCount << "Class 1 Templates:" - << numTemplates - classOneTemplateCount << "Total Templates:" << numTemplates; + qDebug() <<"Class 0 Templates:" << numTemplates - classOneTemplateCount << "Class 1 Templates:" + << classOneTemplateCount << "Total Templates:" << numTemplates; qDebug("EER: %.3f @ Threshold %.3f", EER*100, EERThres); - } diff --git a/openbr/plugins/imgproc/roi.cpp b/openbr/plugins/imgproc/roi.cpp index d1e492d..40fb92d 100644 --- a/openbr/plugins/imgproc/roi.cpp +++ b/openbr/plugins/imgproc/roi.cpp @@ -36,7 +36,7 @@ class ROITransform : public UntrainableTransform Q_PROPERTY(bool copyOnCrop READ get_copyOnCrop WRITE set_copyOnCrop RESET reset_copyOnCrop STORED false) Q_PROPERTY(int shiftPoints READ get_shiftPoints WRITE set_shiftPoints RESET reset_shiftPoints STORED false) BR_PROPERTY(QString, propName, "") - BR_PROPERTY(bool, copyOnCrop, false) + BR_PROPERTY(bool, copyOnCrop, true) BR_PROPERTY(int, shiftPoints, -1) void project(const Template &src, Template &dst) const diff --git a/openbr/plugins/imgproc/rotate.cpp b/openbr/plugins/imgproc/rotate.cpp new file mode 100644 index 0000000..d51a415 --- /dev/null +++ b/openbr/plugins/imgproc/rotate.cpp @@ -0,0 +1,45 @@ +#include +#include + +using namespace cv; + +namespace br +{ + +/*! + * \ingroup transforms + * \brief Rotates an image in 90 degree intervals. + * \author Keyur Patel \cite patel + */ +class RotateTransform : public UntrainableTransform +{ + Q_OBJECT + + Q_PROPERTY(int angle READ get_angle WRITE set_angle RESET reset_angle STORED false) + BR_PROPERTY(int, angle, -90) + + void project(const Template &src, Template &dst) const { + + if(angle == 270 || angle == -90){ + // Rotate clockwise 270 degrees + cv::transpose(src, dst); + cv::flip(dst, dst, 0); + }else if(angle == 180 || angle == -180){ + // Rotate clockwise 180 degrees + cv::flip(src, dst, -1); + }else if(angle == 90 || angle == -270){ + // Rotate clockwise 90 degrees + cv::transpose(src, dst); + cv::flip(dst, dst, 1); + }else { + dst = src; + } + } +}; + +BR_REGISTER(Transform, RotateTransform) + +} // namespace br + +#include "imgproc/rotate.moc" + diff --git a/openbr/plugins/metadata/extractvaluefromlist.cpp b/openbr/plugins/metadata/extractvaluefromlist.cpp new file mode 100644 index 0000000..4c396fa --- /dev/null +++ b/openbr/plugins/metadata/extractvaluefromlist.cpp @@ -0,0 +1,60 @@ + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright 2015 Rank One Computing Corporation * + * * + * Licensed under the Apache License, Version 2.0 (the "License"); * + * you may not use this file except in compliance with the License. * + * You may obtain a copy of the License at * + * * + * http://www.apache.org/licenses/LICENSE-2.0 * + * * + * Unless required by applicable law or agreed to in writing, software * + * distributed under the License is distributed on an "AS IS" BASIS, * + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * + * See the License for the specific language governing permissions and * + * limitations under the License. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include + +namespace br +{ + +/*! + * \ingroup transforms + * \brief Extracts a single value from a list and sets the specified key to that value. + * \br_property QString key The meta-data key that contains a list of values + * \br_property int index The index of the value of interest (0 offset) + * \br_property QString outputKey The output metadata key which stores the value of interest + * \author Keyur Patel \cite kpatel + */ +class ExtractValueFromListTransform : public UntrainableMetadataTransform +{ + Q_OBJECT + Q_PROPERTY(QString key READ get_key WRITE set_key RESET reset_key STORED false) + Q_PROPERTY(int index READ get_index WRITE set_index RESET reset_index STORED false) + Q_PROPERTY(QString outputKey READ get_outputKey WRITE set_outputKey RESET reset_outputKey STORED false) + + BR_PROPERTY(QString, key, "") + BR_PROPERTY(int, index, 0) + BR_PROPERTY(QString, outputKey, "ExtractedValue") + + void projectMetadata(const File &src, File &dst) const + { + dst = src; + + if (src.contains(key)){ + QList values = src.getList(key); + if (values.size() -1 >= index && index >= 0) + dst.set(outputKey,values[index]); + } + } + +}; + +BR_REGISTER(Transform, ExtractValueFromListTransform) + +} // namespace br + +#include "metadata/extractvaluefromlist.moc" + diff --git a/openbr/plugins/metadata/majorityvoting.cpp b/openbr/plugins/metadata/majorityvoting.cpp new file mode 100644 index 0000000..8e80633 --- /dev/null +++ b/openbr/plugins/metadata/majorityvoting.cpp @@ -0,0 +1,109 @@ + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright 2015 Rank One Computing Corporation * + * * + * Licensed under the Apache License, Version 2.0 (the "License"); * + * you may not use this file except in compliance with the License. * + * You may obtain a copy of the License at * + * * + * http://www.apache.org/licenses/LICENSE-2.0 * + * * + * Unless required by applicable law or agreed to in writing, software * + * distributed under the License is distributed on an "AS IS" BASIS, * + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * + * See the License for the specific language governing permissions and * + * limitations under the License. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include + +namespace br +{ + +/*! + * \ingroup transforms + * \brief Performs majority voting from a single metadata key or multiple keys and sets the result in the specified key. + * \br_property QString keys The meta-data key(s) used for Majority Voting. + * \br_property int numClasses The number of possible classes. + * \br_property QString outputKey The output metadata key which stores the a list with the index of the winning class set to 1. + * \br_property float thresh Allows users to specify a threshold for the first class, if exceeded the first class wins else class 2 wins. + * \author Keyur Patel \cite kpatel + */ +class MajorityVotingTransform : public UntrainableMetadataTransform +{ + Q_OBJECT + Q_PROPERTY(QList keys READ get_keys WRITE set_keys RESET reset_keys STORED false) + Q_PROPERTY(int numClasses READ get_numClasses WRITE set_numClasses RESET reset_numClasses STORED false) + Q_PROPERTY(QString outputKey READ get_outputKey WRITE set_outputKey RESET reset_outputKey STORED false) + Q_PROPERTY(float thresh READ get_thresh WRITE set_thresh RESET reset_thresh STORED false) + + BR_PROPERTY(QList, keys, QList()) + BR_PROPERTY(int, numClasses, 2) + BR_PROPERTY(QString, outputKey, "MajorityVoting") + BR_PROPERTY(float, thresh, -1) + + + void projectMetadata(const File &src, File &dst) const + { + dst = src; + + QList scores = QList(); + foreach (QString key, keys){ + if (src.contains(key)){ + QList templateScores = src.getList(key); + scores.append(templateScores); + } else { + dst.fte = true; + return; + } + } + int classCount[numClasses]; //= {0}; + for (int i = 0; i < numClasses; i++){ + classCount[i] = 0; + } + for (int c = 0; c < scores.size(); c+= numClasses){ + if(numClasses == 2 and thresh != -1){ + if (scores[c] > thresh) + classCount[0]++; + else + classCount[1]++; + } else { + int highestScoringClass = 0; + float highestScore = scores[c]; + for (int b = 1; b < numClasses; b++){ + if (scores[c+b] > highestScore){ + highestScore = scores[c+b]; + highestScoringClass = b; + } + } + classCount[highestScoringClass]++; + } + } + int largestIndex = getIndexOfLargestElement(classCount,numClasses); + + QList output = QList(); + for(int i=0; i +#include + +using namespace cv; + +namespace br +{ + +/*! + * \ingroup transforms + * \brief Fuses together scores from a single metadata key or multiple keys and sets the computed values in the specified key. + * \br_property QString keys The meta-data key(s) to fuse on. + * \br_property QString outputKey The output metadata key. + * \br_property bool listOfList Flag that tells the program how to parse the metadata key that contains the score values. + * \author Keyur Patel \cite kpatel + */ +class ScoreLevelFusionTransform : public UntrainableMetadataTransform +{ + Q_OBJECT + Q_PROPERTY(QList keys READ get_keys WRITE set_keys RESET reset_keys STORED false) + Q_PROPERTY(int numClasses READ get_numClasses WRITE set_numClasses RESET reset_numClasses STORED false) + Q_PROPERTY(QString outputKey READ get_outputKey WRITE set_outputKey RESET reset_outputKey STORED false) + Q_PROPERTY(bool listOfList READ get_listOfList WRITE set_listOfList RESET reset_listOfList STORED false) + + BR_PROPERTY(QList, keys, QList()) + BR_PROPERTY(int, numClasses, 2) + BR_PROPERTY(QString, outputKey, "ScoreLevelFusion") + BR_PROPERTY(bool, listOfList, false) + + void projectMetadata(const File &src, File &dst) const + { + dst = src; + QList > scoresList = QList >(); + if (listOfList){ //format [[.8,.2],[.45,.55],[.3,.7]] + foreach (QString key, keys){ + if (src.contains(key)){ + QList keyScoresList = src.getList(key); + for (int d = 0; d < keyScoresList.size(); d++){ + QList tmpList = keyScoresList[d].split(","); + QList tmpScoreList = QList(); + for (int f = 0; f < tmpList.size(); f++){ + tmpScoreList.append(tmpList[f].remove('"').remove("]").remove("[").toFloat()); + } + scoresList.append(tmpScoreList); + } + } else{ + dst.fte = true; + return; + } + } + } else { //format = [.8,.2,.45,.55,.3.,7] + QList scores = QList(); + foreach (QString key, keys){ + if (src.contains(key)){ + QList templateScores = src.getList(key); + scores.append(templateScores); + } else{ + dst.fte = true; + return; + } + } + for (int i = 0; i < scores.size(); i+=numClasses){ + QList tmpList = QList(); + for (int b = 0; b < numClasses; b++){ + tmpList.append(scores[i+b]); + } + scoresList.append(tmpList); + } + } + Mat m = toMat(scoresList); + Mat avgDist; + cv::reduce(m, avgDist, 0, 1); + dst.setList(outputKey,matrixToVector(avgDist)); + } + + cv::Mat toMat(const QList > &src) const + { + cv::Mat dst(src.size(), src[0].size(), CV_32F); + for (int i=0; i(i, j) = src[i][j]; + return dst; + } + + QList matrixToVector(const cv::Mat &m) const + { + QList results; + for (int i=0; i(0, i)); + return results; + } + +}; + +BR_REGISTER(Transform, ScoreLevelFusionTransform) + +} // namespace br + +#include "metadata/scorelevelfusion.moc" +