gregion.cpp
来自「一个由Mike Gashler完成的机器学习方面的includes neural」· C++ 代码 · 共 1,037 行 · 第 1/2 页
CPP
1,037 行
/* Copyright (C) 2006, Mike Gashler This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. see http://www.gnu.org/copyleft/lesser.html*/#include "GRegion.h"#include "GArray.h"#include "GImage.h"#include "GHashTable.h"#include "GVideo.h"#include "GFourier.h"#include "GBits.h"#include <math.h>struct GRegion;struct GRegionEdge{ int m_nRegion1; int m_nRegion2; GRegionEdge* m_pNext1; GRegionEdge* m_pNext2; int GetOther(int n) { if(n == m_nRegion1) return m_nRegion2; else if(n == m_nRegion2) return m_nRegion1; else { GAssert(false, "That region doesn't share this edge"); return -1; } } struct GRegionEdge* GetNext(int nRegion) { if(nRegion == m_nRegion1) return m_pNext1; else if(nRegion == m_nRegion2) return m_pNext2; else { GAssert(false, "That region doesn't share this edge"); return NULL; } }};struct GRegion{ int m_nPixels; int m_nSumRed; int m_nSumGreen; int m_nSumBlue; struct GRegionEdge* m_pNeighbors;};GRegionAjacencyGraph::GRegionAjacencyGraph(){ m_pRegions = new GPointerArray(128); m_pNeighbors = new GPointerArray(256); m_pHeap = new GStringHeap(2048);}GRegionAjacencyGraph::~GRegionAjacencyGraph(){ delete(m_pRegions); delete(m_pNeighbors); delete(m_pHeap);}int GRegionAjacencyGraph::AddRegion(){ int nRegion = m_pRegions->GetSize(); struct GRegion* pNewRegion = (struct GRegion*)m_pHeap->Allocate(sizeof(struct GRegion)); pNewRegion->m_nPixels = 0; pNewRegion->m_nSumRed = 0; pNewRegion->m_nSumGreen = 0; pNewRegion->m_nSumBlue = 0; pNewRegion->m_pNeighbors = NULL; m_pRegions->AddPointer(pNewRegion); return nRegion;}int GRegionAjacencyGraph::GetRegionCount(){ return m_pRegions->GetSize();}void GRegionAjacencyGraph::GetAverageColor(int nRegion, float* pRed, float* pGreen, float* pBlue){ struct GRegion* pRegion = (struct GRegion*)m_pRegions->GetPointer(nRegion); *pRed = (float)pRegion->m_nSumRed / pRegion->m_nPixels; *pGreen = (float)pRegion->m_nSumGreen / pRegion->m_nPixels; *pBlue = (float)pRegion->m_nSumBlue / pRegion->m_nPixels;}bool GRegionAjacencyGraph::AreNeighbors(int nRegion1, int nRegion2){ GAssert(nRegion1 != nRegion2, "same region"); struct GRegion* pRegion1 = (struct GRegion*)m_pRegions->GetPointer(nRegion1); struct GRegionEdge* pEdge; for(pEdge = pRegion1->m_pNeighbors; pEdge; pEdge = pEdge->GetNext(nRegion1)) { if(pEdge->GetOther(nRegion1) == nRegion2) return true; } return false;}void GRegionAjacencyGraph::MakeNeighbors(int nRegion1, int nRegion2){ if(AreNeighbors(nRegion1, nRegion2)) return; struct GRegion* pRegion1 = (struct GRegion*)m_pRegions->GetPointer(nRegion1); struct GRegion* pRegion2 = (struct GRegion*)m_pRegions->GetPointer(nRegion2); struct GRegionEdge* pNewEdge = (struct GRegionEdge*)m_pHeap->Allocate(sizeof(struct GRegionEdge)); pNewEdge->m_nRegion1 = nRegion1; pNewEdge->m_nRegion2 = nRegion2; pNewEdge->m_pNext1 = pRegion1->m_pNeighbors; pNewEdge->m_pNext2 = pRegion2->m_pNeighbors; pRegion1->m_pNeighbors = pNewEdge; pRegion2->m_pNeighbors = pNewEdge; m_pNeighbors->AddPointer(pNewEdge);}int GRegionAjacencyGraph::GetAjacencyCount(){ return m_pNeighbors->GetSize();}void GRegionAjacencyGraph::GetAjacency(int nEdge, int* pRegion1, int* pRegion2){ struct GRegionEdge* pEdge = (struct GRegionEdge*)m_pNeighbors->GetPointer(nEdge); *pRegion1 = pEdge->m_nRegion1; *pRegion2 = pEdge->m_nRegion2;}// ------------------------------------------------------------------------------------------G2DRegionGraph::G2DRegionGraph(int nWidth, int nHeight) : GRegionAjacencyGraph(){ m_pRegionMask = new GImage(); m_pRegionMask->SetSize(nWidth, nHeight); m_pRegionMask->Clear(0xffffffff);}G2DRegionGraph::~G2DRegionGraph(){ delete(m_pRegionMask);}void G2DRegionGraph::SetMaskPixel(int x, int y, GColor c, int nRegion){ GAssert(x >= 0 && x < (int)m_pRegionMask->GetWidth() && y >= 0 && y < (int)m_pRegionMask->GetHeight(), "out of range"); GAssert(m_pRegionMask->GetPixel(x, y) == 0xffffffff, "This pixel is already set"); m_pRegionMask->SetPixel(x, y, nRegion); struct GRegion* pRegion = (struct GRegion*)m_pRegions->GetPointer(nRegion); pRegion->m_nSumRed += gRed(c); pRegion->m_nSumGreen += gGreen(c); pRegion->m_nSumBlue += gBlue(c); pRegion->m_nPixels++;}int MaxChan(GColor c){ //return MAX(gRed(c), MAX(gGreen(c), gBlue(c))); return c;}void PickTobogganDirection(GImage* pGradMagImage, int u, int v, int* pdu, int* pdv){ int cand; int grad = MaxChan(pGradMagImage->GetPixel(u, v)); int du = 0; int dv = 0; if(u > 0) { cand = MaxChan(pGradMagImage->GetPixel(u - 1, v)); if(cand < grad) { grad = cand; du = -1; dv = 0; } } if(v > 0) { cand = MaxChan(pGradMagImage->GetPixel(u, v - 1)); if(cand < grad) { grad = cand; du = 0; dv = -1; } } if(u < (int)pGradMagImage->GetWidth() - 1) { cand = MaxChan(pGradMagImage->GetPixel(u + 1, v)); if(cand < grad) { grad = cand; du = 1; dv = 0; } } if(v < (int)pGradMagImage->GetHeight() - 1) { cand = MaxChan(pGradMagImage->GetPixel(u, v + 1)); if(cand < grad) { grad = cand; du = 0; dv = 1; } } *pdu = du; *pdv = dv;}void G2DRegionGraph::MakeWatershedRegions(const GImage* pImage){ GImage gradMag; gradMag.MakeGradientMagnitudeImage(pImage); GImage* pMask = GetRegionMask(); int x, y, u, v, du, dv; unsigned int region, other; for(y = 0; y < pImage->GetHeight(); y++) { for(x = 0; x < pImage->GetWidth(); x++) { u = x; v = y; do { region = pMask->GetPixel(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->GetPixel(u, v), region); } u = x; v = y; do { if(pMask->GetPixel(u, v) != 0xffffffff) break; SetMaskPixel(u, v, pImage->GetPixel(u, v), region); PickTobogganDirection(&gradMag, u, v, &du, &dv); u += du; v += dv; } while(du != 0 || dv != 0); if(x > 0) { other = pMask->GetPixel(x - 1, y); if(other != region) MakeNeighbors(region, other); } if(y > 0) { other = pMask->GetPixel(x, y - 1); if(other != region) MakeNeighbors(region, other); } } }}double MeasureRegionDifference(struct GRegion* pA, struct GRegion* pB){ double dSum = 0; double d; d = (double)pA->m_nSumRed / pA->m_nPixels - (double)pB->m_nSumRed / pB->m_nPixels; dSum += (d * d); d = (double)pA->m_nSumGreen / pA->m_nPixels - (double)pB->m_nSumGreen / pB->m_nPixels; dSum += (d * d); d = (double)pA->m_nSumBlue / pA->m_nPixels - (double)pB->m_nSumBlue / pB->m_nPixels; dSum += (d * d); return dSum;}void G2DRegionGraph::MakeCoarserRegions(G2DRegionGraph* pFineRegions){ // Find every region's closest neighbor GImage* pFineRegionMask = pFineRegions->GetRegionMask(); GImage* pCoarseRegionMask = GetRegionMask(); GAssert(pCoarseRegionMask->GetWidth() == pFineRegionMask->GetWidth() && pCoarseRegionMask->GetHeight() == pFineRegionMask->GetHeight(), "size mismatch"); int* pBestNeighborMap = new int[pFineRegions->GetRegionCount()]; Holder<int*> hBestNeighborMap(pBestNeighborMap); int i, j; for(i = 0; i < pFineRegions->GetRegionCount(); i++) { struct GRegion* pRegion = (struct GRegion*)pFineRegions->m_pRegions->GetPointer(i); struct GRegionEdge* pEdge; double d; double dBestDiff = 1e200; int nBestNeighbor = -1; for(pEdge = pRegion->m_pNeighbors; pEdge; pEdge = pEdge->GetNext(i)) { j = pEdge->GetOther(i); struct GRegion* pOtherRegion = (struct GRegion*)pFineRegions->m_pRegions->GetPointer(j); d = MeasureRegionDifference(pRegion, pOtherRegion); if(d < dBestDiff) { dBestDiff = d; nBestNeighbor = j; } } GAssert(nBestNeighbor != -1 || pFineRegions->GetRegionCount() == 1, "failed to find a neighbor"); pBestNeighborMap[i] = nBestNeighbor; } // Create a mapping to new regions numbers int* pNewRegionMap = new int[pFineRegions->GetRegionCount()]; Holder<int*> hNewRegionMap(pNewRegionMap); memset(pNewRegionMap, 0xff, sizeof(int) * pFineRegions->GetRegionCount()); int nNewRegionCount = 0; for(i = 0; i < pFineRegions->GetRegionCount(); i++) { int nNewRegion = -1; 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] = nNewRegion; j = pBestNeighborMap[j]; } } // Make the new regions int k; for(i = 0; i < pFineRegions->GetRegionCount(); i++) { struct GRegion* pRegion = (struct GRegion*)pFineRegions->m_pRegions->GetPointer(i); j = pNewRegionMap[i]; if(GetRegionCount() <= j) { GAssert(GetRegionCount() == j, "how'd it get two behind?"); AddRegion(); } struct GRegion* pCoarseRegion = (struct GRegion*)m_pRegions->GetPointer(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(i = 0; i < pFineRegions->GetRegionCount(); i++) { struct GRegion* pRegion = (struct GRegion*)pFineRegions->m_pRegions->GetPointer(i); j = pNewRegionMap[i]; struct GRegionEdge* pEdge; for(pEdge = pRegion->m_pNeighbors; pEdge; pEdge = pEdge->GetNext(i)) { 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->GetHeight(); y++) { for(x = 0; x < (int)pFineRegionMask->GetWidth(); x++) { nOldRegion = pFineRegionMask->GetPixel(x, y); pCoarseRegionMask->SetPixel(x, y, pNewRegionMap[nOldRegion]); } }}// ------------------------------------------------------------------------------------------G3DRegionGraph::G3DRegionGraph(int nWidth, int nHeight) : GRegionAjacencyGraph(){ m_pRegionMask = new GVideo(nWidth, nHeight);}G3DRegionGraph::~G3DRegionGraph(){ delete(m_pRegionMask);}void G3DRegionGraph::SetMaskPixel(int x, int y, int z, GColor c, int nRegion){ GAssert(x >= 0 && x < m_pRegionMask->GetWidth() && y >= 0 && y < m_pRegionMask->GetHeight() && z >= 0 && z < m_pRegionMask->GetFrameCount(), "out of range"); GAssert(m_pRegionMask->GetFrame(z)->GetPixel(x, y) == 0xffffffff, "This pixel is already set"); m_pRegionMask->GetFrame(z)->SetPixel(x, y, nRegion); struct GRegion* pRegion = (struct GRegion*)m_pRegions->GetPointer(nRegion); pRegion->m_nSumRed += gRed(c); pRegion->m_nSumGreen += gGreen(c); pRegion->m_nSumBlue += gBlue(c); pRegion->m_nPixels++;}void PickTobogganDirection(GVideo* pGradMagVideo, int u, int v, int w, int* pdu, int* pdv, int* pdw){ unsigned int cand; GImage* pFrame = pGradMagVideo->GetFrame(w); unsigned int grad = pFrame->GetPixel(u, v); int du = 0; int dv = 0; int dw = 0; if(w > 0) { pFrame = pGradMagVideo->GetFrame(w - 1); cand = pFrame->GetPixel(u, v); if(cand < grad) { grad = cand; du = 0; dv = 0; dw = -1; } } if(w < pGradMagVideo->GetFrameCount() - 1) { pFrame = pGradMagVideo->GetFrame(w + 1); cand = pFrame->GetPixel(u, v); if(cand < grad) { grad = cand; du = 0; dv = 0; dw = 1; } } if(u > 0) { cand = pFrame->GetPixel(u - 1, v); if(cand < grad) { grad = cand; du = -1; dv = 0; dw = 0; } } if(v > 0) { cand = pFrame->GetPixel(u, v - 1); if(cand < grad) { grad = cand; du = 0; dv = -1; dw = 0; } } if(u < pGradMagVideo->GetWidth() - 1) { cand = pFrame->GetPixel(u + 1, v); if(cand < grad) { grad = cand; du = 1; dv = 0; dw = 0; } } if(v < pGradMagVideo->GetHeight() - 1) { cand = pFrame->GetPixel(u, v + 1); if(cand < grad) { grad = cand; du = 0; dv = 1; dw = 0; } } *pdu = du; *pdv = dv; *pdw = dw;}void G3DRegionGraph::MakeWatershedRegions(GVideo* pVideo){ GVideo gradMag(pVideo->GetWidth(), pVideo->GetHeight()); gradMag.MakeGradientMagnitudeVideo(pVideo, false); GVideo* pMask = GetRegionMask(); GAssert(pVideo->GetWidth() == pMask->GetWidth() && pVideo->GetHeight() == pMask->GetHeight(), "size mismatch"); int x, y, z, u, v, w, du, dv, dw; unsigned int region, other; while(pMask->GetFrameCount() < pVideo->GetFrameCount()) { pMask->AddBlankFrame(); pMask->GetFrame(pMask->GetFrameCount() - 1)->Clear(0xffffffff); }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?