void OutputTask::Run() { set_thread_name("OutputTask"); MatchList ml; bool first_matchlist_printed = false; std::stringstream sstrm; while(m_input_queue.wait_pull(std::move(ml)) != queue_op_status::closed) { if(first_matchlist_printed && m_output_is_tty) { // Print a blank line between the match lists (i.e. the groups of matches in one file). std::cout << "\n"; } ml.Print(sstrm, m_output_is_tty, m_enable_color, m_print_column); std::cout << sstrm.str(); std::cout.flush(); sstrm.str(std::string()); sstrm.clear(); first_matchlist_printed = true; // Count up the total number of matches. m_total_matched_lines += ml.GetNumberOfMatchedLines(); } }
MatchList::const_iterator filterOutBestMatch(const MatchList &input) { MatchList::const_iterator result = input.begin(); if (input.size() > 1) warning("Multiple entries found for id %d/%s", (*result)->first, getIdString((*result)->first)); for (MatchList::const_iterator i = input.begin(); i != input.end(); ++i) { // Reduce all entries to one single entry. // // We use the following rules for this (in this order): // - Prefer the entry with the higest size // - Prefer the entry, which starts at the smallest offest // // TODO: These rules might not be safe for all games, but hopefully // they will work fine. If there are any problems it should be rather // easy to identify them, since we print out a warning for multiple // entries found. if ((*result)->second.desc.hint.size <= (*i)->second.desc.hint.size) { if ((*result)->second.offset >= (*i)->second.offset) result = i; } } return result; }
upSimpleReport MatchResultList::regenerateReport() { // collect the numbers of all match groups in this round MatchMngr mm{db}; MatchGroupList mgl = mm.getMatchGroupsForCat(cat, round); if (mgl.size() > 1) { std::sort(mgl.begin(), mgl.end(), [](MatchGroup& mg1, MatchGroup& mg2){ if (mg1.getGroupNumber() < mg2.getGroupNumber()) return true; return false; }); } // prepare a subheader if we are in KO-rounds QString subHeader = QString(); if ((mgl.size() == 1) && (mgl.at(0).getGroupNumber() > 0)) { subHeader = GuiHelpers::groupNumToLongString(mgl.at(0).getGroupNumber()); } upSimpleReport result = createEmptyReport_Portrait(); QString repName = cat.getName() + tr(" -- Results of Round ") + QString::number(round); setHeaderAndHeadline(result.get(), repName, subHeader); // print a warning if the round is incomplete CatRoundStatus crs = cat.getRoundStatus(); if (round > crs.getFinishedRoundsCount()) { result->writeLine(tr("Note: the round is not finished yet; results are incomplete."), "", 1.0); } // print the results of each match group for (MatchGroup mg : mgl) { int grpNum = mg.getGroupNumber(); // print a header if we are in round-robin rounds if (grpNum > 0) { printIntermediateHeader(result, GuiHelpers::groupNumToLongString(grpNum)); } // print each finished match MatchList ml = mg.getMatches(); std::sort(ml.begin(), ml.end(), [](Match& m1, Match& m2){ return (m1.getMatchNumber() < m2.getMatchNumber()); }); printMatchList(result, ml, PlayerPairList(), GuiHelpers::groupNumToLongString(grpNum) + tr(" (cont.)"), true, false); result->skip(3.0); } // set header and footer setHeaderAndFooter(result, repName); return result; }
void HammingMatchBatch::getResult(MatchList &good) const{ good.clear(); cv::DMatch _mtch; for ( int _i = 0; _i < this->result.rows; ++_i){ _mtch.queryIdx = this->result.at<int>(_i, 0); _mtch.trainIdx = this->result.at<int>(_i, 1); _mtch.distance = this->result.at<int>(_i, 2); if ( _mtch.queryIdx != -1 ) good.push_back(_mtch); } }
MatchList filterLanguageMatches(const int lang, const MatchList &input) { std::list<ExtractMap::const_iterator> result; for (MatchList::const_iterator i = input.begin(); i != input.end(); ++i) { if ((*i)->second.desc.lang == lang) result.push_back(*i); } return result; }
upSimpleReport MatchResultList_ByGroup::regenerateReport() { // collect the match groups with the requested match group number and // search in all rounds MatchMngr mm{db}; MatchGroupList mgl = mm.getMatchGroupsForCat(cat); MatchGroupList filteredList; for (MatchGroup mg: mgl) { if (mg.getGroupNumber() == grpNum) filteredList.push_back(mg); } // sort match groups by round number if (filteredList.size() > 1) { std::sort(filteredList.begin(), filteredList.end(), [](MatchGroup& mg1, MatchGroup& mg2){ if (mg1.getRound() < mg2.getRound()) return true; return false; }); } upSimpleReport result = createEmptyReport_Portrait(); QString repName = cat.getName() + tr(" -- Results of Group ") + QString::number(grpNum); setHeaderAndHeadline(result.get(), repName); for (MatchGroup mg : filteredList) { int round = mg.getRound(); printIntermediateHeader(result, tr("Round ") + QString::number(round)); MatchList maList = mg.getMatches(); std::sort(maList.begin(), maList.end(), [](Match& ma1, Match& ma2) { return ma1.getMatchNumber() < ma2.getMatchNumber(); }); printMatchList(result, maList, PlayerPairList(), tr("Results of round ") + QString::number(round) + tr(" (cont.)"), true, false); if (mg.getState() != STAT_MG_FINISHED) { result->skip(1.0); result->writeLine(tr("Note: this round is not finished yet; results for this group can be incomplete.")); } result->skip(3.0); } // set header and footer setHeaderAndFooter(result, repName); return result; }
// Check each predicate in the MatchList for common sub-expressions static void cse_matchlist(MatchList *matchList) { for( MatchList *mList = matchList; mList != NULL; mList = mList->get_next() ) { Predicate* predicate = mList->get_pred_obj(); char* pred = mList->get_pred(); if( pred != NULL ) { for(int index = 0; index < count; ++index ) { const char *shared_pred = dfa_shared_preds::pred(index); const char *shared_pred_var = dfa_shared_preds::var(index); bool result = dfa_shared_preds::cse_predicate(predicate, shared_pred, shared_pred_var); if( result ) dfa_shared_preds::set_found(index, true); } } } }
void fast_hammingnorm_matchserial(const cv::Mat &des1, const cv::Mat &des2, ListIdxCorrespondance &_list, const float ratio){ MatchList good; good.clear(); bool flipcorrespondence = false; if ( des1.rows <= des2.rows ){ _hammingmatchserial(des1, des2, good, ratio); } else { flipcorrespondence = true; _hammingmatchserial(des2, des1, good, ratio); } correspondance_list(good, _list, flipcorrespondence); }
void SearchSet::addSubDirectoriesMatching(const FSNode &directory, String origPattern, bool ignoreCase, int priority) { FSList subDirs; if (!directory.getChildren(subDirs)) return; String nextPattern, pattern; String::const_iterator sep = Common::find(origPattern.begin(), origPattern.end(), '/'); if (sep != origPattern.end()) { pattern = String(origPattern.begin(), sep); ++sep; if (sep != origPattern.end()) nextPattern = String(sep, origPattern.end()); } else { pattern = origPattern; } // TODO: The code we have for displaying all matches, which vary only in case, might // be a bit overhead, but as long as we want to display all useful information to the // user we will need to keep track of all directory names added so far. We might // want to reconsider this though. typedef HashMap<String, bool, IgnoreCase_Hash, IgnoreCase_EqualTo> MatchList; MatchList multipleMatches; MatchList::iterator matchIter; for (FSList::const_iterator i = subDirs.begin(); i != subDirs.end(); ++i) { String name = i->getName(); if (Common::matchString(name.c_str(), pattern.c_str(), ignoreCase)) { matchIter = multipleMatches.find(name); if (matchIter == multipleMatches.end()) { multipleMatches[name] = true; } else { if (matchIter->_value) { warning("Clash in case for match of pattern \"%s\" found in directory \"%s\": \"%s\"", pattern.c_str(), directory.getPath().c_str(), matchIter->_key.c_str()); matchIter->_value = false; } warning("Clash in case for match of pattern \"%s\" found in directory \"%s\": \"%s\"", pattern.c_str(), directory.getPath().c_str(), name.c_str()); } if (nextPattern.empty()) addDirectory(name, *i, priority); else addSubDirectoriesMatching(*i, nextPattern, ignoreCase, priority); } } }
/** Calculates scores for each player (who played at least one match) * and returns list of results */ PlayerResultsList Group::playersResults() const { PlayerResultsList list; for ( int i = 0; i < _players.count(); i ++ ) { Player p = _players.at( i ); MatchList ml = playedMatchList( p ); if ( !ml.isEmpty() ) { PlayerResults res( p, ml ); list << res; } } return list; }
void _hammingmatch_lowetest_slow(const cv::Mat &_des1, const cv::Mat &_des2, MatchList &_good, const float ratio){ // compute and copmare norms row by row int _n1 = _des1.rows; int _n2 = _des2.rows; int _idx, _mindist1, _mindist2; cv::DMatch _mtch; for ( int _i = 0; _i < _n1; ++_i ){ _idx=-1; _mindist1 = 10000; _mindist2 = 1000000; // some arbirtrary large value for initializing // compute best idx for row _i of _des1 for ( int _j = 0; _j < _n2; ++_j ){ // calculate hamming distance int _val = cv::normHamming(_des1.row(_i).data, _des2.row(_j).data, 4); if ( _val > 8) {continue;} // skip to make it fast _val = cv::normHamming(_des1.row(_i).data, _des2.row(_j).data, _des2.cols); if ( _val < _mindist2 ){ if ( _val < _mindist1 ){ _mindist2 = _mindist1; _mindist1 = _val; _idx = _j; } else _mindist2 = _val; } } // ratio test if ( (_idx != -1) && (_mindist1 < (_mindist2 * ratio ))){ // all is okay printf("distance %d: %d\n", _i, _mindist1); _mtch.distance = _mindist1; _mtch.queryIdx = _i; // the first _mtch.trainIdx = _idx; // the second _good.push_back(_mtch); } } }
Homography meanHomography(const Array<Feat>& feats1,const Array<Feat>& feats2,const MatchList& matches) { int nb=int(matches.size()); Matrix<double> A(2*nb,8); Vector<double> B(2*nb); A.fill(0); int k=0; // Completer: remplir A et B pour que H verifie AH=B for (MatchList::const_iterator it=matches.begin(); it!=matches.end(); k++,it++) { Vec2 m1=feats1[it->first].pos; Vec2 m2=feats2[it->second].pos; // ... } Matrix<double> C=pseudoInverse(A); // Moindres carr�s if(norm(C)==0) // non invertible return Homography(0.); Vector<double> H=C*B; return Homography(H.data()); // Painlesss Vector -> FVector conversion }
void fast_hammingnorm_match_neighborhood(const cv::Mat& des1, const cv::Mat& des2, const cv::Mat& neighborhood, ListIdxCorrespondance& _list, const float ratio, const int parscore) { cv::setNumThreads(3); MatchList good; good.clear(); bool flipcorrespondence = false; if ( des1.rows <= des2.rows ){ HammingMatchBatch _hmtbb(des1, des2,neighborhood, ratio, parscore); cv::parallel_for_(cv::Range(0, des1.rows), _hmtbb, 3); _hmtbb.getResult(good); } else { flipcorrespondence = true; cv::Mat _neight=neighborhood.t(); HammingMatchBatch _hmtbb(des2, des1, _neight, ratio, parscore); cv::parallel_for_(cv::Range(0, des2.rows), _hmtbb, 3); _hmtbb.getResult(good); } correspondance_list(good, _list, flipcorrespondence); }
void fast_hammingnorm_match(const cv::Mat &des1, const cv::Mat&des2, ListIdxCorrespondance &_list, const float ratio, const int parscore){ // Fast Hamming Norm based test cv::setNumThreads(3); cv::Mat empty; MatchList good; good.clear(); bool flipcorrespondence = false; if ( des1.rows <= des2.rows ){ HammingMatchBatch _hmtbb(des1, des2, empty, ratio, parscore); cv::parallel_for_(cv::Range(0, des1.rows), _hmtbb, 3); _hmtbb.getResult(good); } else { flipcorrespondence = true; HammingMatchBatch _hmtbb(des2, des1, empty, ratio, parscore); cv::parallel_for_(cv::Range(0, des2.rows), _hmtbb, 3); _hmtbb.getResult(good); } correspondance_list(good, _list, flipcorrespondence); }
void ArchDesc::gen_dfa_state_body(FILE* fp, Dict &minimize, ProductionState &status, Dict &operands_chained_from, int i) { // Start the body of each Op_XXX sub-dfa with a clean state. status.initialize(); // Walk the list, compacting it MatchList* mList = _mlistab[i]; do { // Hash each entry using inputs as key and pointer as data. // If there is already an entry, keep the one with lower cost, and // remove the other one from the list. prune_matchlist(minimize, *mList); // Iterate mList = mList->get_next(); } while(mList != NULL); // Hoist previously specified common sub-expressions out of predicates dfa_shared_preds::reset_found(); dfa_shared_preds::cse_matchlist(_mlistab[i]); dfa_shared_preds::generate_cse(fp); mList = _mlistab[i]; // Walk the list again, generating code do { // Each match can generate its own chains operands_chained_from.Clear(); gen_match(fp, *mList, status, operands_chained_from); mList = mList->get_next(); } while(mList != NULL); // Fill in any chain rules which add instructions // These can generate their own chains as well. operands_chained_from.Clear(); // if( debug_output1 ) { fprintf(fp, "// top level chain rules for: %s \n", (char *)NodeClassNames[i]); // %%%%% Explanation } const Expr *zeroCost = new Expr("0"); chain_rule(fp, " ", (char *)NodeClassNames[i], zeroCost, "Invalid", operands_chained_from, status); }
MatchList filterPlatformMatches(const Game *g, std::pair<ExtractMap::const_iterator, ExtractMap::const_iterator> range) { bool hasPlatformMatch = false; for (ExtractMap::const_iterator i = range.first; i != range.second; ++i) { if (i->second.desc.platform == g->platform) { hasPlatformMatch = true; break; } } MatchList result; if (hasPlatformMatch) { for (ExtractMap::const_iterator i = range.first; i != range.second; ++i) { if (i->second.desc.platform == g->platform) result.push_back(i); } } else { for (ExtractMap::const_iterator i = range.first; i != range.second; ++i) result.push_back(i); } return result; }
//---------------------------gen_match----------------------------------------- void ArchDesc::gen_match(FILE *fp, MatchList &mList, ProductionState &status, Dict &operands_chained_from) { const char *spaces4 = " "; const char *spaces6 = " "; fprintf(fp, "%s", spaces4); // Only generate child tests if this is not a leaf node bool has_child_constraints = mList._lchild || mList._rchild; const char *predicate_test = mList.get_pred(); if( has_child_constraints || predicate_test ) { // Open the child-and-predicate-test braces fprintf(fp, "if( "); status.set_constraint(hasConstraint); child_test(fp, mList); // Only generate predicate test if one exists for this match if( predicate_test ) { if( has_child_constraints ) { fprintf(fp," &&\n"); } fprintf(fp, "%s %s", spaces6, predicate_test); } // End of outer tests fprintf(fp," ) "); } else { // No child or predicate test needed status.set_constraint(noConstraint); } // End of outer tests fprintf(fp,"{\n"); // Calculate cost of this match const Expr *cost = calc_cost(fp, spaces6, mList, status); // Check against other match costs, and update cost & rule vectors cost_check(fp, spaces6, ArchDesc::getMachOperEnum(mList._resultStr), cost, mList._opcode, status); // If this is a member of an operand class, update the class cost & rule expand_opclass( fp, spaces6, cost, mList._resultStr, status); // Check if this rule should be used to generate the chains as well. const char *rule = /* set rule to "Invalid" for internal operands */ strcmp(mList._opcode,mList._resultStr) ? mList._opcode : "Invalid"; // If this rule produces an operand which has associated chain rules, // update the operands with the chain rule + this rule cost & this rule. chain_rule(fp, spaces6, mList._resultStr, cost, rule, operands_chained_from, status); // Close the child-and-predicate-test braces fprintf(fp, " }\n"); }
Homography autoHomography(const Image<Color>&I1,const Image<Color>&I2,bool ransac=false) { Detector d; Array<Feat> feats1=d.run(I1); drawFeatures(feats1); Array<Feat> feats2=d.run(I2); drawFeatures(feats2,IntPoint2(I1.width(),0)); MatchList matches=loweMatch(feats1,feats2,.5,true); cout << matches.size() << " matches" << endl; drawMatches(feats1,feats2,matches,IntPoint2(0,0),IntPoint2(I1.width(),0),1.,true); click(); if (ransac) { Homography H; double outlier_thres; double median_res = leastMedianOfSquares<4>(matches.begin(), matches.end(), HomEstimator(feats1,feats2), HomResidual(feats1,feats2),H,&outlier_thres); MatchList inliers; for (MatchList::const_iterator it=matches.begin(); it!=matches.end(); it++) { if ( HomResidual(feats1,feats2)(H,*it) < outlier_thres ) inliers.push_front(*it); } cout << inliers.size() << " inliers" << endl; matches=inliers; } return meanHomography(feats1,feats2,matches); }
void _hammingmatchserial(const cv::Mat &des1, const cv::Mat &des2, MatchList &good, const float ratio){ int _n1 = des1.rows; int dist, idx; cv::DMatch _mtch; int step = des1.step / sizeof(des1.ptr()[0]); for (int _i = 0; _i < _n1; ++_i){ if ( des2.cols == 64 ){ idx = _bestmatch64(des1.data+step*_i, des2, dist, ratio, FASTHAMMING_FREAK_PARSCORE); } else { idx = _bestmatch64(des1.data+step*_i, des2, dist, ratio); } if ( idx != -1){ _mtch.distance = dist; _mtch.queryIdx = _i; _mtch.trainIdx = idx; good.push_back(_mtch); } } }
bool getExtractionData(const Game *g, Search &search, ExtractMap &map) { SearchMap searchMap; const int *needList = getNeedList(g); if (!needList) { fprintf(stderr, "ERROR: No entry need list available\n"); return false; } if (!setupSearch(g, needList, search, searchMap)) return false; // Process the data search Search::ResultList results; search.search(results); if (results.empty()) { fprintf(stderr, "ERROR: Couldn't find any required data\n"); return false; } ExtractMap temporaryExtractMap; for (const int *entry = needList; *entry != -1; ++entry) { typedef std::pair<SearchMap::const_iterator, SearchMap::const_iterator> KeyRange; KeyRange idRange = searchMap.equal_range(*entry); for (Search::ResultList::const_iterator i = results.begin(); i != results.end(); ++i) { for (SearchMap::const_iterator j = idRange.first; j != idRange.second; ++j) { if (j->second.hint == i->data) temporaryExtractMap.insert(ExtractMapEntry(*entry, ExtractData(j->second, i->offset))); } } } // Free up some memory results.clear(); searchMap.clear(); bool result = true; for (const int *entry = needList; *entry != -1; ++entry) { MatchList possibleMatches = filterPlatformMatches(g, temporaryExtractMap.equal_range(*entry)); if (possibleMatches.empty()) { fprintf(stderr, "ERROR: No entry found for id %d/%s\n", *entry, getIdString(*entry)); result = false; continue; } if (isLangSpecific(*entry)) { for (int i = 0; i < 3; ++i) { if (g->lang[i] == -1) continue; MatchList langMatches = filterLanguageMatches(g->lang[i], possibleMatches); MatchList::const_iterator bestMatch = filterOutBestMatch(langMatches); if (bestMatch == langMatches.end()) { // TODO: Add nice language name to output message. fprintf(stderr, "ERROR: No entry found for id %d/%s for language %d\n", *entry, getIdString(*entry), g->lang[i]); result = false; continue; } #ifdef DEBUG_EXTRACTION_TABLES if (((*bestMatch)->second.desc.platform != kPlatformUnknown && (*bestMatch)->second.desc.platform != g->platform)) printf("%s: %.8X %.8X %d %d\n", getIdString(*entry), (*bestMatch)->second.desc.hint.size, (*bestMatch)->second.desc.hint.byteSum, (*bestMatch)->second.desc.lang, (*bestMatch)->second.desc.platform); #endif map.insert(**bestMatch); } } else { MatchList::const_iterator bestMatch = filterOutBestMatch(possibleMatches); if (bestMatch == possibleMatches.end()) { fprintf(stderr, "ERROR: No entry found for id %d/%s\n", *entry, getIdString(*entry)); result = false; continue; } #ifdef DEBUG_EXTRACTION_TABLES if (((*bestMatch)->second.desc.platform != kPlatformUnknown && (*bestMatch)->second.desc.platform != g->platform)) printf("%s: %.8X %.8X %d %d\n", getIdString(*entry), (*bestMatch)->second.desc.hint.size, (*bestMatch)->second.desc.hint.byteSum, (*bestMatch)->second.desc.lang, (*bestMatch)->second.desc.platform); #endif map.insert(**bestMatch); } } return result; }
void FileScanner::ScanFileLibPCRE(const char *file_data, size_t file_size, MatchList& ml) { // Match output vector. We won't support submatches, so we only need two entries, plus a third for pcre's own use. int ovector[3] = {-1, 0, 0}; long long line_no = 1; long long prev_lineno = 0; const char *prev_lineno_search_end = file_data; // Up-cast file_size, which is a size_t (unsigned) to a ptrdiff_t (signed) which should be able to handle the // same positive range, and not cause issues when compared with the ints of ovector[]. std::ptrdiff_t signed_file_size = file_size; // Loop while the start_offset is less than the file_size. while(ovector[1] < signed_file_size) { int options = 0; int start_offset = ovector[1]; // Was the previous match zero-length? if (ovector[0] == ovector[1]) { // Yes, are we at the end of the file? if (ovector[0] == signed_file_size) { // Yes, we're done searching. break; } // Not done, set options for another try for a non-empty match at the same point. options = PCRE_NOTEMPTY_ATSTART | PCRE_ANCHORED; } // Try to match the regex to whatever's left of the file. int rc = pcre_exec( m_pcre_regex, m_pcre_extra, file_data, file_size, start_offset, options, ovector, 3); // Check for no match. if(rc == PCRE_ERROR_NOMATCH) { if(options == 0) { // We weren't trying to recover from a zero-length match, so there are no more matches. // Break out of the loop. break; } else { // We've failed to find a non-empty-string match at a point where // we previously found an empty-string match. // Advance one character and continue. ovector[1] = start_offset + 1; /** * @todo If we're treating \r\n as a newline, we have to check here to see * if we are at the start of one, and if so, skip over the whole thing. * For now, we don't support this. */ if(/** @todo crlf_is_newline */ false && start_offset < file_size -1 && file_data[start_offset] == '\r' && file_data[start_offset] == '\n') { // Increment the new start position by one more byte, we're at a \r\n line ending. ovector[1]++; } /** * @todo Similarly, if we support UTF-8, we have to skip all bytes in the * possibly multi-byte character. * Again, UTF-8 is not something we support at the moment. */ else if(false /** @todo utf8 */) { // Increment a whole UTF8 character. while(ovector[1] < signed_file_size) { if((file_data[ovector[1]] & 0xC0) != 0x80) { // Found a non-start-byte. break; } else { // Go to the next byte in the character. ovector[1]++; } } } } // Try to match again. continue; } // Check for non-PCRE_ERROR_NOMATCH error codes. if(rc < 0) { std::cerr << "ERROR: Match error " << rc << "." << std::endl; return; } if (rc == 0) { std::cerr << "ERROR: ovector only has room for 1 captured substring" << std::endl; return; } // There was a match. Package it up in the MatchList which was passed in. long long num_lines_since_last_match = std::count(prev_lineno_search_end, file_data+ovector[0], '\n'); line_no += num_lines_since_last_match; prev_lineno_search_end = file_data+ovector[0]; if(line_no == prev_lineno) { // Skip multiple matches on one line. continue; } prev_lineno = line_no; Match m(file_data, file_size, ovector[0], ovector[1], line_no); ml.AddMatch(std::move(m)); } }