/** Merge graph \p ga into graph \p gb. Returns false on failure. */ bool mergeNfaPair(NGHolder &ga, NGHolder &gb, const ReportManager *rm, const CompileContext &cc) { assert(ga.kind == gb.kind); auto a_state_ids = numberStates(ga); auto b_state_ids = numberStates(gb); // Vacuous NFAs require special checks on their starts to ensure that tops // match, and that reports match for mixed-accept cases. if (!mergeableStarts(ga, gb)) { DEBUG_PRINTF("starts aren't mergeable\n"); return false; } u32 cpl = commonPrefixLength(ga, a_state_ids, gb, b_state_ids); if (!shouldMerge(gb, b_state_ids, ga, a_state_ids, cpl, rm, cc)) { return false; } mergeNfaComponent(gb, ga, cpl); reduceImplementableGraph(gb, SOM_NONE, rm, cc); b_state_ids = numberStates(gb); return true; }
int* StatMerge::doSegmentation(int* ch1, int* ch2, int* ch3, double p) { // first, build the edge array for(int x = 0; x < iWidth - 1; ++x) { for(int y = 0; y < iHeight - 1; ++y) { int p1 = (y * iWidth) + x; int p2 = p1 + 1; int p3 = p1 + iWidth; // vertical edge edgeArray[p1 * 2].p1 = p1; edgeArray[p1 * 2].p2 = p2; edgeArray[p1 * 2].val = findVal(ch1,ch2,ch3,p1,p2); // horizontal edge edgeArray[(p1 * 2)+1].p1 = p1; edgeArray[(p1 * 2)+1].p2 = p3; edgeArray[(p1 * 2)+1].val = findVal(ch1,ch2,ch3,p1,p3); } } // we have to handle the very bottom and right differently int y = iHeight - 1; int x = 0; for(x = 0; x < iWidth - 1; ++x) { int p1 = (y * iWidth) + x; int p2 = p1 + 1; // vertical edge edgeArray[p1 * 2].p1 = p1; edgeArray[p1 * 2].p2 = p2; edgeArray[p1 * 2].val = findVal(ch1,ch2,ch3,p1,p2); } y = 0; x = iWidth - 1; for(y = 0; y < iHeight - 1; ++y) { int p1 = (y * iWidth) + x; int p2 = p1 + iWidth; // horizontal edge edgeArray[(p1 * 2)+1].p1 = p1; edgeArray[(p1 * 2)+1].p2 = p2; edgeArray[(p1 * 2)+1].val = findVal(ch1,ch2,ch3,p1,p2); } // now sort the edges (probably the most expensive part of this entire operation). std::sort(edgeArray, edgeArray + (iWidth * iHeight * 2)); // now let us prepare for the merging! uf.reset(); resetStats(ch1,ch2,ch3); double Qg = 255.0 * sqrt(0.5 * log(2.0 / p)); int p1, p2; int p1r, p2r; // first, note what our old maximum group number was int oldCutoff = maxGroup; ++maxGroup; // first merge: merge unchanged pixels for(int i = 0; i < (iWidth*iHeight*2); ++i) { p1 = edgeArray[i].p1; p2 = edgeArray[i].p2; if(p1 < 0 || p2 < 0) continue; // don't merge if one of us has changed or if we're in different groups if(changeMask[p1] || changeMask[p2] || (retArray[p1] != retArray[p2])) continue; //std::cout << "I should never be called!\n"; // otherwise, merge p1r = uf.Find(p1); p2r = uf.Find(p2); uf.UFUnion(p1r, p2r); //statsArray[p1r].merge(statsArray[p2r]); // cheat a bit to make sure new groups are formed statsArray[p1r].merge(statsArray[p2r], -1, maxGroup); } // second merge: merge everything again according to statistical rules //std::cout << "MaxGroup: " << maxGroup << std::endl; for(int i = 0; i < (iWidth*iHeight*2); ++i) { p1 = edgeArray[i].p1; p2 = edgeArray[i].p2; if(p1 < 0 || p2 < 0) continue; p1r = uf.Find(p1); p2r = uf.Find(p2); // (curLabels[p1]==curLabels[p2]) // if we aren't already merged and the stats indicate we should, merge if(p1r != p2r && (false || shouldMerge(statsArray[p1r], statsArray[p2r], Qg))) { uf.UFUnion(p1r, p2r); // this merge call makes sure that new groups merge into old ones and that // new groups are properly created statsArray[p1r].merge(statsArray[p2r], oldCutoff, maxGroup); } } // now to fill in the return array thingy... int curR; int curSize; for(int curP = 0; curP < iWidth * iHeight; ++curP) { curR = uf.Find(curP); //curG = statsArray[curR].G; //retArray[curP] = changeMask[curR]; curSize = statsArray[curR].N; sizeArray[curP] = curSize; retArray[curP] = curR; } return retArray; }