void G2DRegionGraph::makeWatershedRegions(const GImage* pImage) { GImage gradMag; gradMag.gradientMagnitudeImage(pImage); GImage* pMask = regionMask(); int x, y, u, v, du, dv; size_t region, other; for(y = 0; y < (int)pImage->height(); y++) { for(x = 0; x < (int)pImage->width(); x++) { u = x; v = y; do { region = pMask->pixel(u, v); if(region != 0xffffffff) break; PickTobogganDirection(&gradMag, u, v, &du, &dv); u += du; v += dv; } while(du != 0 || dv != 0); if(region == 0xffffffff) { region = addRegion(); setMaskPixel(u, v, pImage->pixel(u, v), region); } u = x; v = y; do { if(pMask->pixel(u, v) != 0xffffffff) break; setMaskPixel(u, v, pImage->pixel(u, v), region); PickTobogganDirection(&gradMag, u, v, &du, &dv); u += du; v += dv; } while(du != 0 || dv != 0); if(x > 0) { other = pMask->pixel(x - 1, y); if(other != region) makeNeighbors(region, other); } if(y > 0) { other = pMask->pixel(x, y - 1); if(other != region) makeNeighbors(region, other); } } } }
void G2DRegionGraph::makeCoarserRegions(G2DRegionGraph* pFineRegions) { // Find every region's closest neighbor GImage* pFineRegionMask = pFineRegions->regionMask(); GImage* pCoarseRegionMask = regionMask(); GAssert(pCoarseRegionMask->width() == pFineRegionMask->width() && pCoarseRegionMask->height() == pFineRegionMask->height()); // size mismatch int* pBestNeighborMap = new int[pFineRegions->regionCount()]; ArrayHolder<int> hBestNeighborMap(pBestNeighborMap); for(size_t i = 0; i < pFineRegions->regionCount(); i++) { struct GRegion* pRegion = pFineRegions->m_regions[i]; struct GRegionEdge* pEdge; double d; double dBestDiff = 1e200; int nBestNeighbor = -1; for(pEdge = pRegion->m_pNeighbors; pEdge; pEdge = pEdge->GetNext(i)) { size_t j = pEdge->GetOther(i); struct GRegion* pOtherRegion = pFineRegions->m_regions[j]; d = MeasureRegionDifference(pRegion, pOtherRegion); if(d < dBestDiff) { dBestDiff = d; nBestNeighbor = (int)j; } } GAssert(nBestNeighbor != -1 || pFineRegions->regionCount() == 1); // failed to find a neighbor pBestNeighborMap[i] = nBestNeighbor; } // Create a mapping to new regions numbers int* pNewRegionMap = new int[pFineRegions->regionCount()]; ArrayHolder<int> hNewRegionMap(pNewRegionMap); memset(pNewRegionMap, 0xff, sizeof(int) * pFineRegions->regionCount()); int nNewRegionCount = 0; for(size_t i = 0; i < pFineRegions->regionCount(); i++) { size_t nNewRegion = -1; size_t j = i; while(pNewRegionMap[j] == -1) { pNewRegionMap[j] = -2; j = pBestNeighborMap[j]; } if(pNewRegionMap[j] == -2) nNewRegion = nNewRegionCount++; else nNewRegion = pNewRegionMap[j]; j = i; while(pNewRegionMap[j] == -2) { pNewRegionMap[j] = (int)nNewRegion; j = pBestNeighborMap[j]; } } // Make the new regions for(size_t i = 0; i < pFineRegions->regionCount(); i++) { struct GRegion* pRegion = pFineRegions->m_regions[i]; size_t j = pNewRegionMap[i]; if(regionCount() <= j) { GAssert(regionCount() == j); // how'd it get two behind? addRegion(); } struct GRegion* pCoarseRegion = m_regions[j]; pCoarseRegion->m_nSumRed += pRegion->m_nSumRed; pCoarseRegion->m_nSumGreen += pRegion->m_nSumGreen; pCoarseRegion->m_nSumBlue += pRegion->m_nSumBlue; pCoarseRegion->m_nPixels += pRegion->m_nPixels; } for(size_t i = 0; i < pFineRegions->regionCount(); i++) { struct GRegion* pRegion = pFineRegions->m_regions[i]; size_t j = pNewRegionMap[i]; struct GRegionEdge* pEdge; for(pEdge = pRegion->m_pNeighbors; pEdge; pEdge = pEdge->GetNext(i)) { size_t k = pNewRegionMap[pEdge->GetOther(i)]; if(j != k) makeNeighbors(j, k); } } // Make the fine region mask unsigned int nOldRegion; int x, y; for(y = 0; y < (int)pFineRegionMask->height(); y++) { for(x = 0; x < (int)pFineRegionMask->width(); x++) { nOldRegion = pFineRegionMask->pixel(x, y); pCoarseRegionMask->setPixel(x, y, pNewRegionMap[nOldRegion]); } } }