/* Construct GCGraph */ void constructGCGraph( const Mat& img, const Mat& mask, const GMM& bgdGMM, const GMM& fgdGMM, double lambda, const Mat& leftW, const Mat& upleftW, const Mat& upW, const Mat& uprightW, GCGraph<double>& graph ) { int vtxCount = img.cols*img.rows, edgeCount = 2*(4*img.cols*img.rows - 3*(img.cols + img.rows) + 2); graph.create(vtxCount, edgeCount); Point p; for( p.y = 0; p.y < img.rows; p.y++ ) { for( p.x = 0; p.x < img.cols; p.x++) { // add node int vtxIdx = graph.addVtx(); Vec3b color = img.at<Vec3b>(p); // set t-weights double fromSource, toSink; if( mask.at<uchar>(p) == GC_PR_BGD || mask.at<uchar>(p) == GC_PR_FGD ) { fromSource = -log( bgdGMM(color) ); toSink = -log( fgdGMM(color) ); } else if( mask.at<uchar>(p) == GC_BGD ) { fromSource = 0; toSink = lambda; } else // GC_FGD { fromSource = lambda; toSink = 0; } graph.addTermWeights( vtxIdx, fromSource, toSink ); // set n-weights if( p.x>0 ) { double w = leftW.at<double>(p); graph.addEdges( vtxIdx, vtxIdx-1, w, w ); } if( p.x>0 && p.y>0 ) { double w = upleftW.at<double>(p); graph.addEdges( vtxIdx, vtxIdx-img.cols-1, w, w ); } if( p.y>0 ) { double w = upW.at<double>(p); graph.addEdges( vtxIdx, vtxIdx-img.cols, w, w ); } if( p.x<img.cols-1 && p.y>0 ) { double w = uprightW.at<double>(p); graph.addEdges( vtxIdx, vtxIdx-img.cols+1, w, w ); } } } }
/* Construct GCGraph */ static void constructGCGraph( const Mat& img, double lambda, const Mat& leftW, const Mat& upleftW, const Mat& upW, const Mat& uprightW, GCGraph<double>& graph ) { int vtxCount = img.cols*img.rows, edgeCount = 2*(4*img.cols*img.rows - 3*(img.cols + img.rows) + 2); graph.create(vtxCount, edgeCount); Point p; Mat gray; cvtColor(img, gray, CV_BGR2GRAY); Mat bw; threshold(gray, bw, 0, 255, CV_THRESH_BINARY | CV_THRESH_OTSU); for( p.y = 0; p.y < img.rows; p.y++ ) { for( p.x = 0; p.x < img.cols; p.x++) { // add node int vtxIdx = graph.addVtx(); Vec3b color = img.at<Vec3b>(p); // set t-weights double fromSource, toSink; if(bw.at<uchar>(p) == 0) { fromSource = lambda; toSink = 0; } else { fromSource = 0; toSink = lambda; } graph.addTermWeights( vtxIdx, fromSource, toSink ); // set n-weights if( p.x>0 ) { double w = leftW.at<double>(p); graph.addEdges( vtxIdx, vtxIdx-1, w, w ); } if( p.x>0 && p.y>0 ) { double w = upleftW.at<double>(p); graph.addEdges( vtxIdx, vtxIdx-img.cols-1, w, w ); } if( p.y>0 ) { double w = upW.at<double>(p); graph.addEdges( vtxIdx, vtxIdx-img.cols, w, w ); } if( p.x<img.cols-1 && p.y>0 ) { double w = uprightW.at<double>(p); graph.addEdges( vtxIdx, vtxIdx-img.cols+1, w, w ); } } } }
/** * Add edges between * nodes in a graph * * @param graph The graph pointer * @param img The Source image * @param neighboursWeight Neighbours influence * @param windowSize Neighbours range * * @return Updates the graph */ void GRAPHCUT::addEdges(GCGraph<float>& graph, Mat& img, float neighboursWeight, int windowSize) { for (int r = windowSize; r < img.rows - windowSize; r++) for (int c = windowSize; c < img.cols - windowSize; c++) for (int i = -windowSize; i <= windowSize; i++) for (int j = -windowSize; j <= windowSize; j++) if (i != 0 || j != 0) { float v = abs(img.at<float>(r, c) - img.at<float>(r + i, c + j)) * neighboursWeight; graph.addEdges(c + img.cols * r, (c + j) + img.cols * (r + i), v, v); } }