void pairwiseCompare(File targetGallery, File queryGallery, File output) { qDebug("Pairwise comparing %s and %s%s", qPrintable(targetGallery.flat()), qPrintable(queryGallery.flat()), output.isNull() ? "" : qPrintable(" to " + output.flat())); if (distance.isNull()) qFatal("Null distance."); if (queryGallery == ".") queryGallery = targetGallery; QScopedPointer<Gallery> t, q; FileList targetFiles, queryFiles; retrieveOrEnroll(targetGallery, t, targetFiles); retrieveOrEnroll(queryGallery, q, queryFiles); if (t->files().length() != q->files().length() ) qFatal("Dimension mismatch in pairwise compare"); TemplateList queries = q->read(); TemplateList targets = t->read(); // Use a single file for one of the dimensions so that the output makes the right size file FileList dummyTarget; dummyTarget.append(targets[0]); QScopedPointer<Output> realOutput(Output::make(output, dummyTarget, queryFiles)); realOutput->set_blockRows(INT_MAX); realOutput->set_blockCols(INT_MAX); realOutput->setBlock(0,0); for (int i=0; i < queries.length(); i++) { float res = distance->compare(queries[i], targets[i]); realOutput->setRelative(res, 0,i); } }
void project(const TemplateList &src, TemplateList &dst) const { CascadeClassifier *cascade = cascadeResource.acquire(); foreach (const Template &t, src) { // As a special case, skip detection if the appropriate metadata already exists if (t.file.contains(model)) { Template u = t; u.file.setRects(QList<QRectF>() << t.file.get<QRectF>(model)); u.file.set("Confidence", t.file.get<float>("Confidence", 1)); dst.append(u); continue; } const bool enrollAll = t.file.getBool("enrollAll"); // Mirror the behavior of ExpandTransform in the special case // of an empty template. if (t.empty() && !enrollAll) { dst.append(t); continue; } for (int i=0; i<t.size(); i++) { const int maxDetections = t.file.get<int>("MaxDetections", std::numeric_limits<int>::max()); const int minSize = t.file.get<int>("MinSize", this->minSize); const int flags = (enrollAll && (maxDetections != 1)) ? 0 : CASCADE_FIND_BIGGEST_OBJECT; Mat m; OpenCVUtils::cvtUChar(t[i], m); std::vector<Rect> rects; std::vector<int> rejectLevels; std::vector<double> levelWeights; if (ROCMode) cascade->detectMultiScale(m, rects, rejectLevels, levelWeights, 1.2, minNeighbors, flags | CASCADE_SCALE_IMAGE, Size(minSize, minSize), Size(), true); else cascade->detectMultiScale(m, rects, 1.2, minNeighbors, flags, Size(minSize, minSize)); bool empty = false; if (!enrollAll && rects.empty()) { empty = true; rects.push_back(Rect(0, 0, m.cols, m.rows)); } const size_t detections = std::min(size_t(maxDetections), rects.size()); for (size_t j=0; j<detections; j++) { Template u(t.file, m); if (empty) { u.file.set("Confidence",-std::numeric_limits<float>::max()); } else if (rejectLevels.size() > j) u.file.set("Confidence", rejectLevels[j]*levelWeights[j]); else u.file.set("Confidence", rects[j].area()); const QRectF rect = OpenCVUtils::fromRect(rects[j]); u.file.appendRect(rect); u.file.set(model, rect); dst.append(u); } } } cascadeResource.release(cascade); }
void projectUpdate(const TemplateList &src, TemplateList &dst) { dst.reserve(src.size()); foreach (const Template &t, src) { dst.append(Template()); projectUpdate(t, dst.last()); }
/*! */ ApiProxyResult CommandTemplateSet::execute(const TemplateList& template_configurations) { std::auto_ptr<CDataWrapper> message(new CDataWrapper()); for(TemplateListConstIterator it = template_configurations.begin(); it != template_configurations.end(); it++) { std::auto_ptr<CDataWrapper> template_element(new CDataWrapper()); template_element->addStringValue("template_name", (*it)->template_name); template_element->addStringValue(BatchCommandAndParameterDescriptionkey::BC_UNIQUE_ID, (*it)->command_unique_id); //! scan all parameter configuration for(ParameterSetterListIterator it_param = (*it)->parameter_value_list.begin(); it_param != (*it)->parameter_value_list.end(); it_param++){ (*it_param)->setTo(*template_element); } template_element->addInt32Value(BatchCommandSubmissionKey::SUBMISSION_RULE_UI32, (*it)->submission_rule); template_element->addInt32Value(BatchCommandSubmissionKey::SUBMISSION_PRIORITY_UI32, (*it)->submission_priority); template_element->addInt64Value(BatchCommandSubmissionKey::SCHEDULER_STEP_TIME_INTERVALL_UI64, (*it)->schedule_step_delay); template_element->addInt32Value(BatchCommandSubmissionKey::SUBMISSION_RETRY_DELAY_UI32, (*it)->submission_retry_delay); template_element->addInt32Value(BatchCommandSubmissionKey::COMMAND_EXECUTION_CHANNEL, (*it)->execution_channel); message->appendCDataWrapperToArray(*template_element); } message->finalizeArrayForKey("template_list"); //call api return callApi(message.release()); }
void train(const TemplateList &data) { Mat m; OpenCVUtils::toMat(data.data()).convertTo(m, CV_64F); const QList<int> labels = data.indexProperty(inputVariable); const int dims = m.cols; std::vector<Mat> mv, av, bv; split(m, mv); for (size_t c = 0; c < mv.size(); c++) { av.push_back(Mat(1, dims, CV_64FC1)); bv.push_back(Mat(1, dims, CV_64FC1)); } QFutureSynchronizer<void> futures; for (size_t c = 0; c < mv.size(); c++) { for (int i=0; i<dims; i++) futures.addFuture(QtConcurrent::run(_train, method, mv[c].col(i), labels, &av[c].at<double>(0, i), &bv[c].at<double>(0, i))); av[c] = av[c].reshape(1, data.first().m().rows); bv[c] = bv[c].reshape(1, data.first().m().rows); } futures.waitForFinished(); merge(av, a); merge(bv, b); a.convertTo(a, data.first().m().type()); b.convertTo(b, data.first().m().type()); OpenCVUtils::saveImage(a, Globals->property("CENTER_TRAIN_A").toString()); OpenCVUtils::saveImage(b, Globals->property("CENTER_TRAIN_B").toString()); }
TemplateList readBlock(bool *done) { TemplateList templates; *done = true; // Enrolling a null file is used as an idiom to initialize an algorithm if (file.isNull()) return templates; // Add immediate subfolders QDir dir(file); QList< QFuture<TemplateList> > futures; foreach (const QString &folder, QtUtils::naturalSort(dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot))) { const QDir subdir = dir.absoluteFilePath(folder); futures.append(QtConcurrent::run(&EmptyGallery::getTemplates, subdir)); } foreach (const QFuture<TemplateList> &future, futures) templates.append(future.result()); // Add root folder foreach (const QString &fileName, QtUtils::getFiles(file.name, false)) templates.append(File(fileName, dir.dirName())); if (!regexp.isEmpty()) { QRegExp re(regexp); re.setPatternSyntax(QRegExp::Wildcard); for (int i=templates.size()-1; i>=0; i--) { if (!re.exactMatch(templates[i].file.fileName())) { templates.removeAt(i); } } } return templates; }
void train(const TemplateList &cudaTrainingSet) { cublasStatus_t cublasStatus; cudaError_t cudaError; // put all the data into a single matrix to perform PCA const int instances = cudaTrainingSet.size(); const int dimsIn = *(int*)cudaTrainingSet.first().m().ptr<void*>()[1] * *(int*)cudaTrainingSet.first().m().ptr<void*>()[2]; // copy the data over double* cudaDataPtr; CUDA_SAFE_MALLOC(&cudaDataPtr, instances*dimsIn*sizeof(cudaDataPtr[0]), &cudaError); for (int i=0; i < instances; i++) { br::cuda::pca::castFloatToDouble( (float*)(cudaTrainingSet[i].m().ptr<void*>()[0]), 1, cudaDataPtr+i*dimsIn, 1, dimsIn ); } trainCore(cudaDataPtr, dimsIn, instances); CUDA_SAFE_FREE(cudaDataPtr, &cudaError); }
static TemplateList Simplified(const TemplateList &templates) { TemplateList simplified; foreach (const Template &t, templates) { if (t.isEmpty()) { if (!t.file.getBool("enrollAll")) simplified.append(t); continue; } const bool fte = t.file.getBool("FTE"); QList<QPointF> landmarks = t.file.landmarks(); QList<QRectF> ROIs = t.file.ROIs(); if (landmarks.size() % t.size() != 0) qFatal("TemplateList::simplified uneven landmark count."); if (ROIs.size() % t.size() != 0) qFatal("TemplateList::simplified uneven ROI count."); const int landmarkStep = landmarks.size() / t.size(); const int ROIStep = ROIs.size() / t.size(); for (int i=0; i<t.size(); i++) { if (!fte || !t.file.getBool("enrollAll")) { simplified.append(Template(t.file, t[i])); simplified.last().file.setROIs(ROIs.mid(i*ROIStep, ROIStep)); simplified.last().file.setLandmarks(landmarks.mid(i*landmarkStep, landmarkStep)); } } } return simplified; }
int32_t SdkEstimator::estimate_gender(const ONEFACE &input_face, int8_t &gender, double &mf) { TemplateList templates; templates.append(templateFromONEFACE(input_face)); templates >> *frvt2012_gender_transform.data(); mf = gender = templates.first().file.label(); return templates.first().file.failed() ? 4 : 0; }
int32_t SdkEstimator::estimate_age(const ONEFACE &input_face, int32_t &age) { TemplateList templates; templates.append(templateFromONEFACE(input_face)); templates >> *frvt2012_age_transform.data(); age = templates.first().file.label(); return templates.first().file.failed() ? 4 : 0; }
static TemplateList getTemplates(const QDir &dir) { const QStringList files = QtUtils::getFiles(dir, true); TemplateList templates; templates.reserve(files.size()); foreach (const QString &file, files) templates.append(File(file, dir.dirName())); return templates; }
void project(const TemplateList &src, TemplateList &dst) const { TemplateList partitioned = src.partition(inputVariable); for (int i=0; i<partitioned.size(); i++) { int partition = partitioned[i].file.get<int>("Partition", 0); transforms[partition]->project(partitioned, dst); } }
TemplateList Manager::getTemplates(KileDocument::Type type) const { if(type == KileDocument::Undefined) { return getAllTemplates(); } TemplateList toReturn; for (KileTemplate::TemplateListConstIterator i = m_TemplateList.constBegin(); i != m_TemplateList.constEnd(); ++i) { KileTemplate::Info info = *i; if(info.type == type) { toReturn.push_back(info); } } return toReturn; }
void train(const TemplateList &trainingSet) { if (trainingSet.first().m().type() != CV_32FC1) qFatal("PCA::train requires single channel 32-bit floating point matrices."); originalRows = trainingSet.first().m().rows; int dimsIn = trainingSet.first().m().rows * trainingSet.first().m().cols; const int instances = trainingSet.size(); // Map into 64-bit Eigen matrix Eigen::MatrixXd data(dimsIn, instances); for (int i=0; i<instances; i++) data.col(i) = Eigen::Map<const Eigen::MatrixXf>(trainingSet[i].m().ptr<float>(), dimsIn, 1).cast<double>(); train(data); }
static void enroll_utemplate(br_const_utemplate utemplate, br_callback_context) { if (utemplate->algorithmID != 3) qFatal("Expected an encoded image."); TemplateList templates; templates.append(Template(imdecode(Mat(1, utemplate->size, CV_8UC1, (void*) utemplate->data), IMREAD_UNCHANGED))); templates >> *algorithm; foreach (const Template &t, templates) { const Mat &m = t.m(); const uint32_t size = m.rows * m.cols * m.elemSize(); const QByteArray templateID = QCryptographicHash::hash(QByteArray((const char*) m.data, size), QCryptographicHash::Md5); br_append_utemplate_contents(stdout, utemplate->imageID, (const int8_t*) templateID.data(), -1, size, m.data); } }
void project(const TemplateList &src, TemplateList &dst) const { CascadeClassifier *cascade = cascadeResource.acquire(); foreach (const Template &t, src) { const bool enrollAll = t.file.getBool("enrollAll"); for (int i=0; i<t.size(); i++) { const Mat &m = t[i]; std::vector<Rect> rects; std::vector<int> rejectLevels; std::vector<double> levelWeights; if (ROCMode) cascade->detectMultiScale(m, rects, rejectLevels, levelWeights, 1.2, 5, (enrollAll ? 0 : CASCADE_FIND_BIGGEST_OBJECT) | CASCADE_SCALE_IMAGE, Size(minSize, minSize), Size(), true); else cascade->detectMultiScale(m, rects, 1.2, 5, enrollAll ? 0 : CASCADE_FIND_BIGGEST_OBJECT, Size(minSize, minSize)); if (!enrollAll && rects.empty()) rects.push_back(Rect(0, 0, m.cols, m.rows)); for (size_t j=0; j<rects.size(); j++) { Template u(t.file, m); if (rejectLevels.size() > j) u.file.set("Confidence", rejectLevels[j]*levelWeights[j]); else u.file.set("Confidence", 1); const QRectF rect = OpenCVUtils::fromRect(rects[j]); u.file.appendRect(rect); u.file.set(model, rect); dst.append(u); } } } cascadeResource.release(cascade); }
void train(const TemplateList &_data) { Mat data = OpenCVUtils::toMat(_data.data()); Mat lab; // If we are doing regression, the input variable should have float // values if (type == EPS_SVR || type == NU_SVR) { lab = OpenCVUtils::toMat(File::get<float>(_data, inputVariable)); } // If we are doing classification, we should be dealing with discrete // values. Map them and store the mapping data else { QList<int> dataLabels = _data.indexProperty(inputVariable, labelMap, reverseLookup); lab = OpenCVUtils::toMat(dataLabels); } trainSVM(svm, data, lab, kernel, type, C, gamma); }
int32_t convert_multiface_to_verification_template(const MULTIFACE &input_faces, uint32_t &template_size, uint8_t* proprietary_template, uint8_t &quality) { // Enroll templates TemplateList templates; templates.reserve(input_faces.size()); foreach (const ONEFACE &oneface, input_faces) templates.append(templateFromONEFACE(oneface)); templates >> *frvt2012_transform.data(); // Compute template size template_size = templates.size() * frvt2012_template_size; // Create proprietary template for (int i=0; i<templates.size(); i++) memcpy(&proprietary_template[i*frvt2012_template_size], templates[i].m().data, frvt2012_template_size); quality = 100; return 0; }
bool DialUpView::SaveSettings(BMessage *settings, BMessage *profile, bool saveTemporary) { if(!fCurrentItem || !settings || !profile) return false; DialUpAddon *addon; TemplateList<DialUpAddon*> addons; for(int32 index = 0; fAddons.FindPointer(DUN_TAB_ADDON_TYPE, index, reinterpret_cast<void**>(&addon)) == B_OK; index++) { if(!addon) continue; int32 insertIndex = 0; for(; insertIndex < addons.CountItems(); insertIndex++) if(addons.ItemAt(insertIndex)->Priority() <= addon->Priority()) break; addons.AddItem(addon, insertIndex); } settings->AddInt32("Interface", static_cast<int32>(fWatching)); if(fCurrentItem) settings->AddString("InterfaceName", fCurrentItem->Label()); for(int32 index = 0; index < addons.CountItems(); index++) if(!addons.ItemAt(index)->SaveSettings(settings, profile, saveTemporary)) return false; return true; }
static void enroll_utemplate(br_const_utemplate utemplate, br_callback_context) { if (utemplate->algorithmID != 3) qFatal("Expected an encoded image."); TemplateList templates; templates.append(Template(imdecode(Mat(1, utemplate->size, CV_8UC1, (void*) utemplate->data), IMREAD_UNCHANGED))); templates >> *algorithm; foreach (const Template &t, templates) { const Mat &m = t.m(); QByteArray data((const char*) m.data, m.rows * m.cols * m.elemSize()); const QRectF frontalFace = t.file.get<QRectF>("FrontalFace"); const QPointF firstEye = t.file.get<QPointF>("First_Eye"); const QPointF secondEye = t.file.get<QPointF>("Second_Eye"); const float x = frontalFace.x(); const float y = frontalFace.y(); const float width = frontalFace.width(); const float height = frontalFace.height(); const float rightEyeX = firstEye.x(); const float rightEyeY = firstEye.y(); const float leftEyeX = secondEye.x(); const float leftEyeY = secondEye.y(); data.append((const char*)&x , sizeof(float)); data.append((const char*)&y , sizeof(float)); data.append((const char*)&width , sizeof(float)); data.append((const char*)&height , sizeof(float)); data.append((const char*)&rightEyeX, sizeof(float)); data.append((const char*)&rightEyeY, sizeof(float)); data.append((const char*)&leftEyeX , sizeof(float)); data.append((const char*)&leftEyeY , sizeof(float)); const QByteArray templateID = QCryptographicHash::hash(data, QCryptographicHash::Md5); br_append_utemplate_contents(stdout, utemplate->imageID, (const unsigned char*) templateID.data(), -1, data.size(), (const unsigned char*) data.data()); } }
void finalize(TemplateList &out) { if (transforms.empty()) return; transforms[0]->finalize(out); for (int i=1; i < transforms.size(); i++) { TemplateList temp; transforms[i]->finalize(temp); for (int j=0; j < out.size(); j++) out[j].append(temp[j]); } }
void DialUpView::CreateTabs() { // create tabs for all registered and valid tab add-ons DialUpAddon *addon; BView *target; float width, height; TemplateList<DialUpAddon*> addons; for(int32 index = 0; fAddons.FindPointer(DUN_TAB_ADDON_TYPE, index, reinterpret_cast<void**>(&addon)) == B_OK; index++) { if(!addon || addon->Position() < 0) continue; int32 insertIndex = 0; for(; insertIndex < addons.CountItems(); insertIndex++) if(addons.ItemAt(insertIndex)->Position() > addon->Position()) break; addons.AddItem(addon, insertIndex); } for(int32 index = 0; index < addons.CountItems(); index++) { addon = addons.ItemAt(index); if(!addon->GetPreferredSize(&width, &height)) continue; target = addon->CreateView(BPoint(0, 0)); if(!target) continue; fTabView->AddTab(target, NULL); } }
void train(const TemplateList &_data) { Mat data = OpenCVUtils::toMat(_data.data()); Mat lab = OpenCVUtils::toMat(_data.labels<float>()); trainSVM(svm, data, lab, kernel, type, C, gamma); }
void project(const TemplateList &src, TemplateList &dst) const { foreach (const Template &t, src) { // As a special case, skip detection if the appropriate metadata already exists if (t.file.contains("Face")) { Template u = t; u.file.setRects(QList<QRectF>() << t.file.get<QRectF>("Face")); u.file.set("Confidence", t.file.get<float>("Confidence", 1)); dst.append(u); continue; } const bool enrollAll = t.file.getBool("enrollAll"); // Mirror the behavior of ExpandTransform in the special case // of an empty template. if (t.empty() && !enrollAll) { dst.append(t); continue; } const int minSize = t.file.get<int>("MinSize", this->minSize); Size minObjectSize(minSize, minSize); Size maxObjectSize; for (int i=0; i<t.size(); i++) { Mat m; OpenCVUtils::cvtUChar(t[i], m); QList<Rect> rects; QList<float> confidences; if (maxObjectSize.height == 0 || maxObjectSize.width == 0) maxObjectSize = m.size(); Mat imageBuffer(m.rows + 1, m.cols + 1, CV_8U); for (double factor = 1; ; factor *= scaleFactor) { int dx, dy; Size originalWindowSize = classifier->windowSize(&dx, &dy); Size windowSize(cvRound(originalWindowSize.width*factor), cvRound(originalWindowSize.height*factor) ); Size scaledImageSize(cvRound(m.cols/factor ), cvRound(m.rows/factor)); Size processingRectSize(scaledImageSize.width - originalWindowSize.width, scaledImageSize.height - originalWindowSize.height); if (processingRectSize.width <= 0 || processingRectSize.height <= 0) break; if (windowSize.width > maxObjectSize.width || windowSize.height > maxObjectSize.height) break; if (windowSize.width < minObjectSize.width || windowSize.height < minObjectSize.height) continue; Mat scaledImage(scaledImageSize, CV_8U, imageBuffer.data); resize(m, scaledImage, scaledImageSize, 0, 0, CV_INTER_LINEAR); Template repImage(t.file, scaledImage); repImage = classifier->preprocess(repImage); int step = factor > 2. ? 1 : 2; for (int y = 0; y < processingRectSize.height; y += step) { for (int x = 0; x < processingRectSize.width; x += step) { Mat window = repImage.m()(Rect(Point(x, y), Size(originalWindowSize.width + dx, originalWindowSize.height + dy))).clone(); Template t(window); float confidence = 0; int result = classifier->classify(t, false, &confidence); if (result == 1) { rects.append(Rect(cvRound(x*factor), cvRound(y*factor), windowSize.width, windowSize.height)); confidences.append(confidence); } // TODO: Add non ROC mode if (result == 0) x += step; } } } OpenCVUtils::group(rects, confidences, confidenceThreshold, minNeighbors, eps); if (!enrollAll && rects.empty()) { rects.append(Rect(0, 0, m.cols, m.rows)); confidences.append(-std::numeric_limits<float>::max()); } for (int j=0; j<rects.size(); j++) { Template u(t.file, m); u.file.set("Confidence", confidences[j]); const QRectF rect = OpenCVUtils::fromRect(rects[j]); u.file.appendRect(rect); u.file.set("Face", rect); dst.append(u); } } } }
void train(const TemplateList &data) { Mat samples = OpenCVUtils::toMat(data.data()); Mat labels = OpenCVUtils::toMat(File::get<float>(data, inputVariable)); problem prob; prob.n = samples.cols; prob.l = samples.rows; prob.bias = -1; prob.y = new double[prob.l]; for (int i=0; i<prob.l; i++) prob.y[i] = labels.at<float>(i,0); // Allocate enough memory for l feature_nodes pointers prob.x = new feature_node*[prob.l]; feature_node *x_space = new feature_node[(prob.n+1)*prob.l]; int k = 0; for (int i=0; i<prob.l; i++) { prob.x[i] = &x_space[k]; for (int j=0; j<prob.n; j++) { x_space[k].index = j+1; x_space[k].value = samples.at<float>(i,j); k++; } x_space[k++].index = -1; } parameter param; // TODO: Support grid search param.C = C; param.p = 1; param.eps = FLT_EPSILON; param.solver_type = solver; if (weight) { param.nr_weight = 2; param.weight_label = new int[2]; param.weight = new double[2]; param.weight_label[0] = 0; param.weight_label[1] = 1; int nonZero = countNonZero(labels); param.weight[0] = 1; param.weight[1] = (double)(prob.l-nonZero)/nonZero; qDebug() << param.weight[0] << param.weight[1]; } else { param.nr_weight = 0; param.weight_label = NULL; param.weight = NULL; } //m = *train_svm(&prob, ¶m); delete[] param.weight; delete[] param.weight_label; delete[] prob.y; delete[] prob.x; delete[] x_space; }
void project(const TemplateList &src, TemplateList &dst) const { foreach (const Template &t, src) { // As a special case, skip detection if the appropriate metadata already exists if (t.file.contains("Face")) { Template u = t; u.file.setRects(QList<QRectF>() << t.file.get<QRectF>("Face")); u.file.set("Confidence", t.file.get<float>("Confidence", 1)); dst.append(u); continue; } const bool enrollAll = t.file.getBool("enrollAll"); // Mirror the behavior of ExpandTransform in the special case // of an empty template. if (t.empty() && !enrollAll) { dst.append(t); continue; } // SlidingWindow assumes that all matricies in a template represent // different channels of the same image! const Size imageSize = t.m().size(); const int minSize = t.file.get<int>("MinSize", this->minSize); QList<Rect> rects; QList<float> confidences; int dx, dy; const Size classifierSize = classifier->windowSize(&dx, &dy); for (double factor = 1; ; factor *= scaleFactor) { // TODO: This should support non-square sizes // Compute the size of the window in which we will detect faces const Size detectionSize(cvRound(minSize*factor),cvRound(minSize*factor)); // Stop if detection size is bigger than the image itself if (detectionSize.width > imageSize.width || detectionSize.height > imageSize.height) break; const float widthScale = (float)classifierSize.width/detectionSize.width; const float heightScale = (float)classifierSize.height/detectionSize.height; // Scale the image such that the detection size within the image corresponds to the respresentation size const Size scaledImageSize(cvRound(imageSize.width*widthScale), cvRound(imageSize.height*heightScale)); Template rep(t.file); foreach (const Mat &m, t) { Mat scaledImage; resize(m, scaledImage, scaledImageSize, 0, 0, CV_INTER_AREA); rep.append(scaledImage); } rep = classifier->preprocess(rep); // Pre-allocate the window to avoid constructing this every iteration Template window(t.file); for (int i=0; i<rep.size(); i++) window.append(Mat()); const int step = factor > 2.0 ? shrinkingFactor : shrinkingFactor*2; for (int y = 0; y < scaledImageSize.height-classifierSize.height; y += step) { for (int x = 0; x < scaledImageSize.width-classifierSize.width; x += step) { for (int i=0; i<rep.size(); i++) { if (clone) window[i] = rep[i](Rect(Point(x, y), Size(classifierSize.width+dx, classifierSize.height+dy))).clone(); else window[i] = rep[i](Rect(Point(x, y), Size(classifierSize.width+dx, classifierSize.height+dy))); } float confidence = 0; int result = classifier->classify(window, false, &confidence); if (result == 1) { rects.append(Rect(cvRound(x/widthScale), cvRound(y/heightScale), detectionSize.width, detectionSize.height)); confidences.append(confidence); } // TODO: Add non ROC mode if (result == 0) x += step; } } } if (group) OpenCVUtils::group(rects, confidences, confidenceThreshold, minNeighbors, eps); if (!enrollAll && rects.empty()) { rects.append(Rect(0, 0, imageSize.width, imageSize.height)); confidences.append(-std::numeric_limits<float>::max()); } for (int j=0; j<rects.size(); j++) { Template u = t; u.file.set("Confidence", confidences[j]); const QRectF rect = OpenCVUtils::fromRect(rects[j]); u.file.appendRect(rect); u.file.set("Face", rect); dst.append(u); } }
void compare(File targetGallery, File queryGallery, File output) { qDebug("Comparing %s and %s%s", qPrintable(targetGallery.flat()), qPrintable(queryGallery.flat()), output.isNull() ? "" : qPrintable(" to " + output.flat())); if (output.exists() && output.get<bool>("cache", false)) return; if (queryGallery == ".") queryGallery = targetGallery; QScopedPointer<Gallery> t, q; FileList targetFiles, queryFiles; retrieveOrEnroll(targetGallery, t, targetFiles); retrieveOrEnroll(queryGallery, q, queryFiles); QList<int> partitionSizes; QList<File> outputFiles; if (output.contains("split")) { if (!output.fileName().contains("%1")) qFatal("Output file name missing split number place marker (%%1)"); partitionSizes = output.getList<int>("split"); for (int i=0; i<partitionSizes.size(); i++) { File splitOutputFile = output.name.arg(i); outputFiles.append(splitOutputFile); } } else outputFiles.append(output); QList<Output*> outputs; foreach (const File &outputFile, outputFiles) outputs.append(Output::make(outputFile, targetFiles, queryFiles)); if (distance.isNull()) qFatal("Null distance."); Globals->currentStep = 0; Globals->totalSteps = double(targetFiles.size()) * double(queryFiles.size()); Globals->startTime.start(); int queryBlock = -1; bool queryDone = false; while (!queryDone) { queryBlock++; TemplateList queries = q->readBlock(&queryDone); QList<TemplateList> queryPartitions; if (!partitionSizes.empty()) queryPartitions = queries.partition(partitionSizes); else queryPartitions.append(queries); for (int i=0; i<queryPartitions.size(); i++) { int targetBlock = -1; bool targetDone = false; while (!targetDone) { targetBlock++; TemplateList targets = t->readBlock(&targetDone); QList<TemplateList> targetPartitions; if (!partitionSizes.empty()) targetPartitions = targets.partition(partitionSizes); else targetPartitions.append(targets); outputs[i]->setBlock(queryBlock, targetBlock); distance->compare(targetPartitions[i], queryPartitions[i], outputs[i]); Globals->currentStep += double(targets.size()) * double(queries.size()); Globals->printStatus(); } } } qDeleteAll(outputs); const float speed = 1000 * Globals->totalSteps / Globals->startTime.elapsed() / std::max(1, abs(Globals->parallelism)); if (!Globals->quiet && (Globals->totalSteps > 1)) fprintf(stderr, "\rSPEED=%.1e \n", speed); Globals->totalSteps = 0; }
void compare(File targetGallery, File queryGallery, File output) { qDebug("Comparing %s and %s%s", qPrintable(targetGallery.flat()), qPrintable(queryGallery.flat()), output.isNull() ? "" : qPrintable(" to " + output.flat())); // Escape hatch for distances that need to operate directly on the gallery files if (distance->compare(targetGallery, queryGallery, output)) return; // Are we comparing the same gallery against itself? bool selfCompare = targetGallery == queryGallery; // Should we use multiple processes to do enrollment/comparison? If not, we just do multi-threading. bool multiProcess = Globals->file.getBool("multiProcess", false); // In comparing two galleries, we will keep the smaller one in memory, and load the larger one // incrementally. If the gallery set is larger than the probe set, we operate in transpose mode // i.e. we must transpose our output, to still write the output matrix in row-major order. bool transposeMode = false; // Is the larger gallery already enrolled? If not, we will enroll those images in-line with their // comparison against the smaller gallery (which will be enrolled, and stored in memory). bool needEnrollRows = false; if (output.exists() && output.get<bool>("cache", false)) return; if (queryGallery == ".") queryGallery = targetGallery; // To decide which gallery is larger, we need to read both, but at this point we just want the // metadata, and don't need the enrolled matrices. FileList targetMetadata; FileList queryMetadata; // Emptyread reads a gallery, and discards any matrices present, keeping only the metadata. targetMetadata = FileList::fromGallery(targetGallery, true); queryMetadata = FileList::fromGallery(queryGallery, true); // Is the target or query set larger? We will use the larger as the rows of our comparison matrix (and transpose the output if necessary) transposeMode = targetMetadata.size() > queryMetadata.size(); File rowGallery = queryGallery; File colGallery = targetGallery; qint64 rowSize; Gallery * temp; if (transposeMode) { rowGallery = targetGallery; colGallery = queryGallery; temp = Gallery::make(targetGallery); } else { temp = Gallery::make(queryGallery); } rowSize = temp->totalSize(); delete temp; // Is the column gallery already enrolled? We keep the enrolled column gallery in memory, and in multi-process // mode, every worker process retains a copy of this gallery in memory. When not in multi-process mode, we can // simple make sure the enrolled data is stored in a memGallery, but in multi-process mode we save the enrolled // data to disk (as a .gal file) so that each worker process can read it without re-doing enrollment. File colEnrolledGallery = colGallery; QString targetExtension = multiProcess ? "gal" : "mem"; // If the column gallery is not already of the appropriate type, we need to do something if (colGallery.suffix() != targetExtension) { // Build the name of a gallery containing the enrolled data, of the appropriate type. colEnrolledGallery = colGallery.baseName() + colGallery.hash() + (multiProcess ? ".gal" : ".mem"); // Check if we have to do real enrollment, and not just convert the gallery's type. if (!(QStringList() << "gal" << "template" << "mem").contains(colGallery.suffix())) { enroll(colGallery, colEnrolledGallery); } // If the gallery does have enrolled templates, but is not the right type, we do a simple // type conversion for it. else { QScopedPointer<Gallery> readColGallery(Gallery::make(colGallery)); TemplateList templates = readColGallery->read(); QScopedPointer<Gallery> enrolledColOutput(Gallery::make(colEnrolledGallery)); enrolledColOutput->writeBlock(templates); } } // We have handled the column gallery, now decide whehter or not we have to enroll the row gallery. if (selfCompare) { // For self-comparisons, we just use the already enrolled column set. rowGallery = colEnrolledGallery; } // Otherwise, we will need to enroll the row set. Since the actual comparison is defined via a transform // which compares incoming templates against a gallery, we will handle enrollment of the row set by simply // building a transform that does enrollment (using the current algorithm), then does the comparison in one // step. This way, we don't have to retain the complete enrolled row gallery in memory, or on disk. else if(!(QStringList() << "gal" << "mem" << "template").contains(rowGallery.suffix())) { needEnrollRows = true; } // At this point, we have decided how we will structure the comparison (either in transpose mode, or not), // and have the column gallery enrolled, and have decided whether or not we need to enroll the row gallery. // From this point, we will build a single algorithm that (optionally) does enrollment, then does comparisons // and output, optionally using ProcessWrapper to do the enrollment and comparison in separate processes. // // There are two main components to this algorithm. The first is the (optional) enrollment and then the // comparison step (built from a GalleryCompare transform), and the second is the sequential matrix output and // progress counting step. // After the base algorithm is built, the whole thing will be run in a stream, so that I/O can be handled sequentially. // The actual comparison step is done by a GalleryCompare transform, which has a Distance, and a gallery as data. // Incoming templates are compared against the templates in the gallery, and the output is the resulting score // vector. QString compareRegionDesc = "Pipe([GalleryCompare("+Globals->algorithm + "," + colEnrolledGallery.flat() + ")])"; QScopedPointer<Transform> compareRegion; // If we need to enroll the row set, we add the current algorithm's enrollment transform before the // GalleryCompare in a pipe. if (needEnrollRows) { if (!multiProcess) { compareRegionDesc = compareRegionDesc; compareRegion.reset(Transform::make(compareRegionDesc,NULL)); CompositeTransform * downcast = dynamic_cast<CompositeTransform *> (compareRegion.data()); if (downcast == NULL) qFatal("Pipe downcast failed in compare"); downcast->transforms.prepend(this->transform.data()); downcast->init(); } else { compareRegionDesc = "ProcessWrapper(" + this->transformString + "+" + compareRegionDesc + ")"; compareRegion.reset(Transform::make(compareRegionDesc, NULL)); } } else { if (multiProcess) compareRegionDesc = "ProcessWrapper(" + compareRegionDesc + ")"; compareRegion.reset(Transform::make(compareRegionDesc,NULL)); } // At this point, compareRegion is a transform, which optionally does enrollment, then compares the row // set against the column set. If in multi-process mode, the enrollment and comparison are wrapped in a // ProcessWrapper transform, and will be transparently run in multiple processes. compareRegion->init(); // We also need to add Output and progress counting to the algorithm we are building, so we will assign them to // two stages of a pipe. QString joinDesc = "Pipe()"; QScopedPointer<Transform> join(Transform::make(joinDesc, NULL)); // The output transform takes the metadata memGalleries we set up previously as input, along with the // output specification we were passed. Gallery metadata is necessary for some Outputs to function correctly. QString outputString = output.flat().isEmpty() ? "Empty" : output.flat(); QString outputRegionDesc = "Output("+ outputString +"," + targetGallery.flat() +"," + queryGallery.flat() + ","+ QString::number(transposeMode ? 1 : 0) + ")"; // The ProgressCounter transform will simply provide a display about the number of rows completed. outputRegionDesc += "+ProgressCounter("+QString::number(rowSize)+")+Discard"; QScopedPointer<Transform> outputTform(Transform::make(outputRegionDesc, NULL)); // Assign the comparison transform we previously built, and the output transform we just built to // two stages of a pipe. CompositeTransform * downcast = dynamic_cast<CompositeTransform *> (join.data()); downcast->transforms.append(compareRegion.data()); downcast->transforms.append(outputTform.data()); // With this, we have set up a transform which (optionally) enrolls templates, compares them // against a gallery, and outputs them. join->init(); // Now, we will give that base transform to a stream, which will incrementally read the row gallery // and pass the transforms it reads through the base algorithm. QString streamDesc = "Stream(readMode=StreamGallery)"; QScopedPointer<Transform> streamBase(Transform::make(streamDesc, NULL)); WrapperTransform * streamWrapper = dynamic_cast<WrapperTransform *> (streamBase.data()); streamWrapper->transform = join.data(); // The transform we will use is now complete. streamWrapper->init(); // We set up a template containing the rowGallery we want to compare. TemplateList rowGalleryTemplate; rowGalleryTemplate.append(Template(rowGallery)); TemplateList outputGallery; // Set up progress counting variables Globals->currentStep = 0; Globals->totalSteps = rowSize; Globals->startTime.start(); // Do the actual comparisons streamWrapper->projectUpdate(rowGalleryTemplate, outputGallery); }