// -- Constructs the ``ccs'' array from run's ccids. void CCImage::make_ccs_from_ccids() { int n; Run *pruns = runs; // Find maximal ccid int maxccid = -1; for (n=0; n<=runs.hbound(); n++) if (pruns[n].ccid > maxccid) maxccid = runs[n].ccid; GTArray<int> armap(0,maxccid); int *rmap = armap; // Renumber ccs for (n=0; n<=maxccid; n++) armap[n] = -1; for (n=0; n<=runs.hbound(); n++) if (pruns[n].ccid >= 0) rmap[ pruns[n].ccid ] = 1; int nid = 0; for (n=0; n<=maxccid; n++) if (rmap[n] > 0) rmap[n] = nid++; // Adjust nregularccs (since ccs are renumbered) while (nregularccs>0 && rmap[nregularccs-1]<0) nregularccs -= 1; if (nregularccs>0) nregularccs = 1 + rmap[nregularccs-1]; // Prepare cc descriptors ccs.resize(0,nid-1); for (n=0; n<nid; n++) ccs[n].nrun = 0; // Relabel runs for (n=0; n<=runs.hbound(); n++) { Run &run = pruns[n]; if (run.ccid < 0) continue; // runs with negative ccids are destroyed int oldccid = run.ccid; int newccid = rmap[oldccid]; CC &cc = ccs[newccid]; run.ccid = newccid; cc.nrun += 1; } // Compute positions for runs of cc int frun = 0; for (n=0; n<nid; n++) { ccs[n].frun = rmap[n] = frun; frun += ccs[n].nrun; } // Copy runs GTArray<Run> rtmp; rtmp.steal(runs); Run *ptmp = rtmp; runs.resize(0,frun-1); pruns = runs; for (n=0; n<=rtmp.hbound(); n++) { int id = ptmp[n].ccid; if (id < 0) continue; int pos = rmap[id]++; pruns[pos] = ptmp[n]; } // Finalize ccs for (n=0; n<nid; n++) { CC &cc = ccs[n]; int npix = 0; runs.sort(cc.frun, cc.frun+cc.nrun-1); Run *run = &runs[cc.frun]; int xmin = run->x1; int xmax = run->x2; int ymin = run->y; int ymax = run->y; cc.color = run->color; for (int i=0; i<cc.nrun; i++, run++) { if (run->x1 < xmin) xmin = run->x1; if (run->x2 > xmax) xmax = run->x2; if (run->y < ymin) ymin = run->y; if (run->y > ymax) ymax = run->y; npix += run->x2 - run->x1 + 1; } cc.npix = npix; cc.bb.xmin = xmin; cc.bb.ymin = ymin; cc.bb.xmax = xmax + 1; cc.bb.ymax = ymax + 1; } }
// -- Performs color connected component analysis void CCImage::make_ccids_by_analysis() { // Sort runs runs.sort(); // Single Pass Connected Component Analysis (with unodes) int n; int p=0; GTArray<int> umap; for (n=0; n<=runs.hbound(); n++) { int y = runs[n].y; int x1 = runs[n].x1 - 1; int x2 = runs[n].x2 + 1; int color = runs[n].color; int id = (umap.hbound() + 1); // iterate over previous line runs if (p>0) p--; for(;runs[p].y < y-1;p++); for(;(runs[p].y < y) && (runs[p].x1 <= x2);p++ ) { if ( runs[p].x2 >= x1 ) { if (runs[p].color == color) { // previous run touches current run and has same color int oid = runs[p].ccid; while (umap[oid] < oid) oid = umap[oid]; if ((int)id > umap.hbound()) { id = oid; } else if (id < oid) { umap[oid] = id; } else { umap[id] = oid; id = oid; } // freshen previous run id runs[p].ccid = id; } // stop if previous run goes past current run if (runs[p].x2 >= x2) break; } } // create new entry in umap runs[n].ccid = id; if (id > umap.hbound()) { umap.touch(id); umap[id] = id; } } // Update umap and ccid for (n=0; n<=runs.hbound(); n++) { Run &run = runs[n]; int ccid = run.ccid; while (umap[ccid] < ccid) ccid = umap[ccid]; umap[run.ccid] = ccid; run.ccid = ccid; } }