The source interpretation of the graph and maximum flow/minimum cut in the "graph cut" OpenCV

Source: Internet
Author: User

#include <vector>using namespace std; #define MIN (a) ((a) < (b)) ( A):(B)) typedef unsigned char uchar;template <class tweight>class gcgraph{public:gcgraph (); Gcgraph (unsigned int vtxcount, unsigned int edgecount); ~gcgraph (); void Create (unsigned int vtxcount, unsigned int edgecou NT); int addvtx (); void addedges (int i, int J, Tweight W, tweight revw); void addtermweights (int i, Tweight sourcew, Tweight SINKW); Tweight Maxflow (); bool Insourcesegment (int i);p rivate:class VTX//Node class {PUBLIC:VTX *next;//For building advanced-first-out queue int only in Maxflow algorithm Parent int first; First adjacent edge int ts; timestamp int dist; To the root of the distance tweight weight; Uchar T; The label of the node in the figure, the value 0 or 1,0 is the source node (foreground point), 1 is the sink node (background point)};class edge{public:int DST,//edge points to the node int next;//the next edge of the vertex of the edge tweight weight; The weight of the edge};std::vector<vtx> VTCs; Store all the nodes std::vector<edge> edges; Store all sides tweight flow; Figure of Traffic};template <class tweight>gcgraph<tweight>::gcgraph () {flow = 0;} Template <class tweight>gcgraph<tweight>::gcgraph (unsigned int vtxcount, unsigned int edgecount) {Create (Vtxcount, edgecount);} Template <class tweight>gcgraph<tweight>::~gcgraph () {}template <class tweight>void GCGraph< tweight>::create (unsigned int vtxcount, unsigned int edgecount) {vtcs.reserve (vtxcount); Edges.reserve (Edgecount + 2 ); flow = 0;} /* Function: Add an empty node, all members initialized to null parameter description: No return value: The current node number in the collection */template <class tweight>int gcgraph<tweight>::addvtx () {Vtx V;memset (&v, 0, sizeof (VTX));//apply the node to the memory space 0 (the second parameter 0) vtcs.push_back (v); return (int) vtcs.size ()-1;// Return value: The number of the current node in the collection}/* function function: Add a node I and a node J between the Edge N-link (the edge between normal nodes) parameter description: int---I: Arc head node number int---J: Arc tail junction number Tweight---w: Forward arc weight value tweight---reww: Reverse arc Weight return value: No */template <class tweight>void gcgraph<tweight>::addedges (int i, Int J, Tweight W, Tweight revw) {assert (i >= 0 && i < (int) vtcs.size ()), assert (J >= 0 && J < (int) VTCs . Size ()); Assert (w >= 0 && revw >= 0); assert (I! = j); Edge FromI, ToI; Forward Arc: FromI, Reverse arc toifromi.dst = j; Forward arc points to node Jfromi.next = Vtcs[i].first; All N-link arcs (4 directions) emitted by each node will be connected to a list of all arcs Fromi.weight = W, using the head interpolation method; The weighted value of the forward arc is w vtcs[i].first = (int) edges.size (); Modifying the first arc of the node I is the current forward arc edges.push_back (FromI); The forward Arc joins the arc set toi.dst = I;toi.next = Vtcs[j].first;toi.weight = Revw;vtcs[j].first = (int) edges.size (); Edges.push_back (ToI );} /* Function: Add a t-link arc to the node I (to the arc of the terminal node), when adding nodes, call this function parameter description: int---I: node number tweight---sourcew: positive arc weight tweight---sinkw: reverse arc weight * /template <class tweight>void gcgraph<tweight>::addtermweights (int i, Tweight SourceW, TWeight SinkW) { ASSERT (i >= 0 && i < (int) vtcs.size ()); Tweight DW = vtcs[i].weight;if (DW > 0) sourcew + dw;elsesinkw-= Dw;flow + = (Sourcew < sinkw)? Sourcew:sinkw;vtcs[i].weight = sourcew-sinkw;} Template <class tweight>tweight Gcgraph<tweight>::maxflow () {const int TERMINAL =-1, orphan =-2; Vtx stub, *nilnode = &stub, *first = nilnode, *last = nilnode;//FIFO queue, save current active node, stub for sentinel node int curr_ts = 0; Current timestamp stub.next = Nilnode; Initialize the active node queue, the first node points to itself vtx *vtxptr = &vtcs[0]; Node pointer edge *edgeptr = &edges[0]; Arc pointer vector<vtx*> orphans; Outliers collection//Traverse all nodes, initialize active node (active node) queue for (int i = 0; i < (int) vtcs.size (); i++) {vtx* v = vtxptr + i;v->ts = 0;i F (v->weight! = 0)//current node t-vaule (i.e. flow) not 0{last = Last->next = V;//queue, insert to tail v->dist = 1;//path length record 1v->parent = TER minal; Label their parents as terminal nodes V->t = v->weight < 0;} elsev->parent = 0; Solitary node}first = first->next; The first node is used as a sentinel, it has no practical meaning, and moves to the next one, that is, the first effective junction last->next = Nilnode; The sentry was placed at the end of the line ... Detected Sentry Description One layer find end nilnode->next = 0;//very long loop, each time follow these three steps://search path, split into forest---tree refactoring for (;;) {vtx* V, *u;//V indicates the current element, U is its neighboring element int e0 = 1, ei = 0, ej = 0; Tweight minweight, weight; Path minimum cut (flow), weight current flow uchar VT; Flow identifier, forward 0, reverse 1//===================================================////First stage: S and T-tree growth, find a s->t path while ( First! = Nilnode) {v = primary;//take the initial element into V, as the current node if (v->parent)//V non-orphan point {VT = v->t;//record v flow//breadth-first search to search for all neighboring nodes of the current node. By traversing all adjacent edges, and the end point of the callout edge is the adjacent node for (ei = v->First Ei! = 0; EI = edgeptr[ei].next) {//Each pair of nodes has two opposite sides, EI^VT indicates that the detected edge is the same as V-junction if (Edgeptr[ei^vt].weight = = 0) Continue;u = vtxptr + edgeptr[ EI].DST; Take out the adjacency point UIF (!u->parent)//No parent node, that is, orphan Point, V accepts U as its child node {u->t = VT;//Set node U and V to the same direction u->parent = ei ^ 1;//EI at the end of the reverse ... U->ts = v->ts; Update timestamp, because the path length of U is calculated by V, so the validity is the same u->dist = v->dist + 1; U depth equals v plus 1if (!u->next)//U is not in queue, enqueue, insert position for team Tail {u->next = Nilnode;//modify next element pointer to Sentinel last = Last->next = u;//Insert Team tail}co Ntinue;} if (u->t! = VT)//U and V are in different directions, you can reach another endpoint, then find a path {e0 = ei ^ vt;break;} You already have a parent node, but if you have a path length greater than v+1, and you have an earlier timestamp, you have detours, modify the path of U to make it a sub-node of V if (u->dist > v->dist + 1 && u->ts &L t;= v->ts) {//reassign the parentu->parent = ei ^ 1;//The parent node of the new setting U is V (number EI), recorded as current arc u->ts = v->ts;//update u with the same timestamp as V U->dist = v->dist + 1; U is a sub-node of V, path length plus 1}}if (E0 > 0) break;} Exclude the vertex from the active Listfirst = First->next;v->next = 0;} if (E0 <= 0) break;//===================================================////Second stage: traffic statistics and tree splitting//=== the first section ===////Find the minimum weight in the path minweight = Edgeptr[e0].weight;assert (minweight > 0) ;//traverse the entire path in two directions, starting from the current node, back to the S-tree, backward-backtracking T-tree//2-time traversal, k=1: backtracking S-Tree, k=0: backtracking T-tree for (int k = 1; k >= 0; k--) {//Backtracking method: Take the current node's parent, If the break is Terminal node for (v = vtxptr + edgeptr[e0^k].dst;; v = vtxptr + edgeptr[ei].dst) {if ((ei = v->parent) < 0) Break;weight = Edgeptr[ei^k].weight;minweight = MIN (minweight, weight); assert (Minweight > 0);} Weight = Fabs (v->weight); minweight = MIN (minweight, weight); assert (Minweight > 0);} = = = Second section ===////Modify all weight weights in the current path/* Note that at any time the nodes of s and T trees have only one arc connecting them to the tree, when the arc weight is reduced to 0, the node breaks from the tree, and if it has no sub-nodes, it becomes an outlier, and if it has a child node, Is independent of the forest, but the sub-nodes of EI do not know they are isolated! */edgeptr[e0].weight-= Minweight; Forward path weight Reduction edgeptr[e0 ^ 1].weight + = Minweight; Inverse path weights increase flow + = Minweight; Modify current traffic//k = 1:source tree, k = 0:destination treefor (int k = 1; k >= 0; k--) {for (v = vtxptr + edgeptr[e0^k].dst; ; v = vtxptr + edgeptr[ei].dst) {if ((ei = v->parent) < 0) Break;edgeptr[ei ^ (k ^ 1)]. Weight + = minweight;if ((edgeptr[ei^k].weight = minweight) = = 0) {orphans.push_back (v); v->parent = Orphan;}} V->weight = V->weight + minweight* (1-K * 2); if (v->weight = = 0) {orphans.push_back (v); v->parent = ORPHAN;}} Phase III: Tree Reconstruction find a new parent node, restore search Tree Curr_ts++;while (!orphans.empty ()) {vtx* v = orphans.back ();//Take an orphan and remember it as V2orphans.pop_back (); Delete the top element of the stack, the two-step operation is equivalent to the stack INT d, mindist = Int_max;e0 = 0;VT = v->t;//traverse the neighboring point of the current node, EI is the number of the current arc for (ei = v->first; ei! = 0; ei = Edgeptr[ei].next) {if (edgeptr[ei ^ (vt ^ 1)].weight = = 0) Continue;u = vtxptr + edgeptr[ei].dst;if (u->t = VT | | U-&G T;parent = = 0) continue;//calculates the current point path length for (d = 0;;) {if (u->ts = = curr_ts) {D + = U->dist;break;} EJ = u->parent;d++;if (EJ < 0) {if (EJ = = orphan) d = int_max-1;else{u->ts = Curr_ts;u->dist = 1;} break;} U = vtxptr + edgeptr[ej].dst;} Update the Distanceif (++d < Int_max) {if (D < mindist) {mindist = D;e0 = ei;} for (U = vtxptr + edgeptr[ei].dst; U->ts! = curr_ts; u = vtxptr + edgeptr[U-&GT;PARENT].DST] {u->ts = Curr_ts;u->dist =--d;}}} if ((v->parent = E0) > 0) {v->ts = Curr_ts;v->dist = mindist;continue;} /* No parent is found */v->ts = 0;for (ei = v->first; ei! = 0; ei = edgeptr[ei].next) {u = vtxptr + edgeptr[ei].dst;e j = u->parent;if (u->t! = VT | |!ej) continue;if (edgeptr[ei ^ (vt ^ 1)].weight &&!u->next) {U->next = Nilnode;last = Last->next = u;} if (EJ > 0 && vtxptr + edgeptr[ej].dst = = v) {orphans.push_back (u); u->parent = Orphan;}}}} return flow; Returns the maximum flow}template <class tweight>bool gcgraph<tweight>::insourcesegment (int i) {assert (I >= 0 & & I < (int) vtcs.size ()); return vtcs[i].t = = 0;};


The source interpretation of the graph and maximum flow/minimum cut in the "graph cut" OpenCV

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.