// Removes ccs which are too small. void CCImage::erase_tiny_ccs() { // ISSUE: HALFTONE DETECTION // We should not remove tiny ccs if they are part of a halftone pattern... for (int i=0; i<ccs.size(); i++) { CC& cc = ccs[i]; if (cc.npix <= tinysize) { // Mark cc to be erased Run *r = &runs[cc.frun]; int nr = cc.nrun; cc.nrun = 0; cc.npix = 0; while (--nr >= 0) (r++)->ccid = -1; } } }
// -- Merges small ccs of similar color and splits large ccs void CCImage::merge_and_split_ccs(int smallsize, int largesize) { int ncc = ccs.size(); int nruns = runs.size(); int splitsize = largesize; if (ncc <= 0) return; // Associative map for storing merged ccids GMap<Grid_x_Color,int> map; nregularccs = ncc; // Set the correct ccids for the runs for (int ccid=0; ccid<ccs.size(); ccid++) { CC* cc = &ccs[ccid]; if (cc->nrun <= 0) continue; Grid_x_Color key; key.color = cc->color; int ccheight = cc->bb.height(); int ccwidth = cc->bb.width(); if (ccheight<=smallsize && ccwidth<=smallsize) { key.gridi = (cc->bb.ymin+cc->bb.ymax)/splitsize/2; key.gridj = (cc->bb.xmin+cc->bb.xmax)/splitsize/2; int newccid = makeccid(key, map, ncc); for(int runid=cc->frun; runid<cc->frun+cc->nrun; runid++) runs[runid].ccid = newccid; } else if (ccheight>=largesize || ccwidth>=largesize) { for(int runid=cc->frun; runid<cc->frun+cc->nrun; runid++) { Run *r = & runs[runid]; key.gridi = r->y/splitsize; key.gridj = r->x1/splitsize; int gridj_end = r->x2/splitsize; int gridj_span = gridj_end - key.gridj; r->ccid = makeccid(key, map, ncc); if (gridj_span>0) { // truncate current run runs.touch(nruns+gridj_span-1); r = &runs[runid]; int x = key.gridj*splitsize + splitsize; int x_end = r->x2; r->x2 = x-1; // append additional runs to the runs array while (++key.gridj < gridj_end) { Run& newrun = runs[nruns++]; newrun.y = r->y; newrun.x1 = x; x += splitsize; newrun.x2 = x-1; newrun.color = key.color; newrun.ccid = makeccid(key, map, ncc); } // append last run to the run array Run& newrun = runs[nruns++]; newrun.y = r->y; newrun.x1 = x; newrun.x2 = x_end; newrun.color = key.color; newrun.ccid = makeccid(key, map, ncc); } } } } // Recompute cc descriptors make_ccs_from_ccids(); }
// -- Merges small ccs and split large ccs void CCImage::merge_and_split_ccs() { int ncc = ccs.size(); int nruns = runs.size(); int splitsize = largesize; if (ncc <= 0) return; // Grid of special components int gridwidth = (width+splitsize-1)/splitsize; nregularccs = ncc; // Set the correct ccids for the runs for (int ccid=0; ccid<ncc; ccid++) { CC* cc = &ccs[ccid]; if (cc->nrun <= 0) continue; int ccheight = cc->bb.height(); int ccwidth = cc->bb.width(); if (ccheight<=smallsize && ccwidth<=smallsize) { int gridi = (cc->bb.ymin+cc->bb.ymax)/splitsize/2; int gridj = (cc->bb.xmin+cc->bb.xmax)/splitsize/2; int newccid = ncc + gridi*gridwidth + gridj; for(int runid=cc->frun; runid<cc->frun+cc->nrun; runid++) runs[runid].ccid = newccid; } else if (ccheight>=largesize || ccwidth>=largesize) { for(int runid=cc->frun; runid<cc->frun+cc->nrun; runid++) { Run& r = runs[runid]; int y = r.y; int x_start = r.x1; int x_end = r.x2; int gridi = y/splitsize; int gridj_start = x_start/splitsize; int gridj_end = x_end/splitsize; int gridj_span = gridj_end-gridj_start; int newccid = ncc + gridi*gridwidth + gridj_start; if (! gridj_span) { r.ccid = newccid; } else // gridj_span>0 { // truncate the current run r.ccid = newccid++; int x = (gridj_start+1)*splitsize; r.x2 = x-1; runs.touch(nruns+gridj_span-1); // append additional runs to the runs array for(int gridj=gridj_start+1; gridj<gridj_end; gridj++) { Run& newrun = runs[nruns++]; newrun.y = y; newrun.x1 = x; x += splitsize; newrun.x2 = x-1; newrun.ccid = newccid++; } // append last run to the run array Run& newrun = runs[nruns++]; newrun.y = y; newrun.x1 = x; newrun.x2 = x_end; newrun.ccid = newccid++; } } } } // Recompute cc descriptors make_ccs_from_ccids(); }