Exemplo n.º 1
0
  /*
   * Get the weight between nodes u and v; return 0 if there is no edge.
   *
   * Preconditions: 
   *     u and v are legal labels (i.e. 0 <= u < G.size(), 0 <= v < G.size())
   */
  EdgeWeight ListGraph::weight(NodeID u, NodeID v) const {
		EList::const_iterator it;
		NWPair check;
		if(u>=0 && u < edgeList.size() && v>=0 && v < edgeList.size() && u!=v){
			for(it = edgeList[u].begin(); it != edgeList[u].end();it++){
				check = *it;
				if(check.first == v ){
					return check.second;
				}
			}
			
		}
	  return EdgeWeight(0);
  }
float
getPathCost(vector<Vertex<FragmentInfo>*>& path,
			vector<ContourEQW>& contours)
{
	float cost = 0;
	for(int i=0; i<path.size()-1; ++i)
	{
		int cid1 = path[i]->key.contourID;
		int pid1 = path[i]->key.pointID;
		int cid2 = path[i+1]->key.contourID;
		int pid2 = path[i+1]->key.pointID;
		if(cid1 != cid2)
		{
			float x1 = contours[cid1].X[pid1];
			float y1 = contours[cid1].Y[pid1];
			float x2 = contours[cid2].X[pid2];
			float y2 = contours[cid2].Y[pid2];
			cost = cost + EdgeWeight(Distance(x1, y1, x2, y2));
		}
	}
	return cost;
}
/*
A slight modification of UpdateDistance.
This version allows non-zero weights on solid fragments. The feature is used to give preference to fragments that are selected by the user.
It is used in BidirectionalDPMPv3.cpp.
*/
bool 
UpdateDistanceWithPreference(vector<Vertex<FragmentInfo>*>& vertices, vector<ContourEQW>& contours, 
							 bool orientation,
							 int iter)
{
	float maxAng = PI/4;
	bool bchanged = false;
	int L = vertices.size()/2;
	Vertex<FragmentInfo>* dest = vertices[vertices.size()-1];
	if(orientation)
	{
		for(int i=0; i<vertices.size(); ++i) 
		{
			int cid1 = vertices[i]->key.contourID;
			int pid1 = vertices[i]->key.pointID;
			for(int j=0; j<i; ++j) //include the source
			{
				if(i-j > L)
				{
					continue;
				}
				int cid2 = vertices[j]->key.contourID;
				int pid2 = vertices[j]->key.pointID;
				float d = vertices[j]->d;
				if(cid1 != cid2)
				{
					float d0 = Distance(contours[cid1].X[pid1], contours[cid1].Y[pid1], contours[cid2].X[pid2], contours[cid2].Y[pid2]);
					d = d + EdgeWeight(d0);
				}
				else //this is where we used fragment specific weight
				{
					float d0 = vertices[i]->key.saliency;
					d += d0;
					/*if(d0<0)
					{
						printf("Negative strength: %f @[%d, %d] - [%d, %d]\n", d0, cid1, pid1, cid2, pid2);
					}*/
				}
				if(d < vertices[i]->d)
				{
					vertices[i]->d = d;
					vertices[i]->pi = vertices[j];
					vertices[i]->f = iter;
					if(cid1 == cid2)
					{
						if(pid1 < pid2)
						{
							for(int k=pid1; k<pid2; ++k)
							{
								contours[cid1].Strength[k] = (float)iter;
							}
						}
						else
						{
							for(int k=pid1; k>pid2; --k)
							{
								contours[cid1].Strength[k] = (float)iter;
							}
						}
					}
					else
					{
						contours[cid1].Strength[pid1] = (float)iter;
					}
					bchanged = true;
				}
			}
		}
	}
	else
	{
		for(int i=vertices.size()-1; i>=0; --i) //exclude the source
		{
			int cid1 = vertices[i]->key.contourID;
			int pid1 = vertices[i]->key.pointID;
			for(int j=i+1; j<vertices.size(); ++j) //include the dest 
			{
				if(j-i>L)
				{
					continue;
				}
				int cid2 = vertices[j]->key.contourID;
				int pid2 = vertices[j]->key.pointID;
				float d = vertices[j]->d;
				if(cid1 != cid2)
				{
					float d0 = Distance(contours[cid1].X[pid1], contours[cid1].Y[pid1], contours[cid2].X[pid2], contours[cid2].Y[pid2]);
					d = d + EdgeWeight(d0);
				}
				else //this is where we used fragment specific weight
				{
					float d0 = vertices[i]->key.saliency;
					d += d0;
					/*if(d0<0)
					{
						printf("Negative strength (R): %f @[%d, %d] - [%d, %d]\n", d0, cid1, pid1, cid2, pid2);
					}*/
				}
				if(d < vertices[i]->d)
				{
					vertices[i]->d = d;
					vertices[i]->pi = vertices[j];
					vertices[i]->f = iter;
					if(cid1 == cid2)
					{
						if(pid1 < pid2)
						{
							for(int k=pid1; k<pid2; ++k)
							{
								contours[cid1].Strength[k] = (float)iter;
							}
						}
						else
						{
							for(int k=pid1; k>pid2; --k)
							{
								contours[cid1].Strength[k] = (float)iter;
							}
						}
					}
					else
					{
						contours[cid1].Strength[pid1] = (float)iter;
					}
					bchanged = true;
				}
			}
		}
	}
	return bchanged;
}
/*
This is a slight modification to UpdateDistance. This version can exclude some nodes from being used
in the shortest path.
The fourth argument (excluded) supplies a set of vertices that need to be excluded from the update.
*/
bool 
UpdateDistanceWithExclusions(vector<Vertex<FragmentInfo>*>& vertices, vector<ContourEQW>& contours, 
			   bool orientation,
			   int iter,
			   vector<FragmentInfo>& excluded)
{
	float maxAng = PI/4;
	bool bchanged = false;
	int L = vertices.size()/2;
	Vertex<FragmentInfo>* dest = vertices[vertices.size()-1];
	if(orientation)
	{
		for(int i=0; i<vertices.size(); ++i) 
		{
			int cid1 = vertices[i]->key.contourID;
			int pid1 = vertices[i]->key.pointID;
			for(int j=0; j<i; ++j) //include the source
			{
				if(i-j > L)
				{
					continue;
				}
				if(find(excluded.begin(), excluded.end(), vertices[j]->key) != excluded.end())
				{
					continue;
				}
				int cid2 = vertices[j]->key.contourID;
				int pid2 = vertices[j]->key.pointID;
				float d = vertices[j]->d;
				if(cid1 != cid2)
				{
					float d0 = Distance(contours[cid1].X[pid1], contours[cid1].Y[pid1], contours[cid2].X[pid2], contours[cid2].Y[pid2]);
					d = d + EdgeWeight(d0);
				}
				if(d < vertices[i]->d)
				{
					vertices[i]->d = d;
					vertices[i]->pi = vertices[j];
					vertices[i]->f = iter;
					if(cid1 == cid2)
					{
						if(pid1 < pid2)
						{
							for(int k=pid1; k<pid2; ++k)
							{
								contours[cid1].Strength[k] = (float)iter;
							}
						}
						else
						{
							for(int k=pid1; k>pid2; --k)
							{
								contours[cid1].Strength[k] = (float)iter;
							}
						}
					}
					else
					{
						contours[cid1].Strength[pid1] = (float)iter;
					}
					bchanged = true;
				}
			}
		}
	}
	else
	{
		for(int i=vertices.size()-1; i>=0; --i) //exclude the source
		{
			int cid1 = vertices[i]->key.contourID;
			int pid1 = vertices[i]->key.pointID;
			for(int j=i+1; j<vertices.size(); ++j) //include the dest 
			{
				if(j-i>L)
				{
					continue;
				}
				if(find(excluded.begin(), excluded.end(), vertices[j]->key) != excluded.end())
				{
					continue;
				}
				int cid2 = vertices[j]->key.contourID;
				int pid2 = vertices[j]->key.pointID;
				float d = vertices[j]->d;
				if(cid1 != cid2)
				{
					float d0 = Distance(contours[cid1].X[pid1], contours[cid1].Y[pid1], contours[cid2].X[pid2], contours[cid2].Y[pid2]);
					d = d + EdgeWeight(d0);
				}
				if(d < vertices[i]->d)
				{
					vertices[i]->d = d;
					vertices[i]->pi = vertices[j];
					vertices[i]->f = iter;
					if(cid1 == cid2)
					{
						if(pid1 < pid2)
						{
							for(int k=pid1; k<pid2; ++k)
							{
								contours[cid1].Strength[k] = (float)iter;
							}
						}
						else
						{
							for(int k=pid1; k>pid2; --k)
							{
								contours[cid1].Strength[k] = (float)iter;
							}
						}
					}
					else
					{
						contours[cid1].Strength[pid1] = (float)iter;
					}
					bchanged = true;
				}
			}
		}
	}
	return bchanged;
}
/*
Perform update on an angularly ordered graph (given as the 1st argument). The 2nd argument
carries the necessary contour information.
The third argument dictates the angular direction (true for contour clock wise, and false for
clock wise).
Currently, the finalized time is set to the iteration number of the update. Thus, the 4th argument
is necessary.
*/
bool 
UpdateDistance(vector<Vertex<FragmentInfo>*>& vertices, 
			   vector<ContourEQW>& contours, 
			   bool orientation,
			   float angleThres,
			   int iter)
{
	bool bchanged = false;
	Vertex<FragmentInfo>* dest = vertices[vertices.size()-1];
	if(orientation)
	{
		for(int i=0; i<vertices.size(); ++i) 
		{
			int cid1 = vertices[i]->key.contourID;
			int pid1 = vertices[i]->key.pointID;
			float d1 = vertices[i]->d;
			for(int j=0; j<vertices.size(); ++j) //include the source
			{
				if(i == j) continue;
				if(vertices[i]->key.angle < vertices[j]->key.angle && Abs(vertices[i]->key.angle-vertices[j]->key.angle)<angleThres)
				{
					int cid2 = vertices[j]->key.contourID;
					int pid2 = vertices[j]->key.pointID;
					float d2 = d1;
					if(cid1 != cid2)
					{
						float d0 = Distance(contours[cid1].X[pid1], contours[cid1].Y[pid1], contours[cid2].X[pid2], contours[cid2].Y[pid2]);
						d2 = d2 + EdgeWeight(d0);
					}
					if(d2 < vertices[j]->d)
					{
						vertices[j]->d = d2;
						vertices[j]->pi = vertices[i];
						vertices[j]->f = iter;
						bchanged = true;
					}
				}
			}
		}
	}
	else
	{
		for(int i=0; i<vertices.size(); ++i) 
		{
			int cid1 = vertices[i]->key.contourID;
			int pid1 = vertices[i]->key.pointID;
			float d1 = vertices[i]->d;
			for(int j=0; j<vertices.size(); ++j) //include the source
			{
				if(i == j) continue;
				if(vertices[i]->key.angle >= vertices[j]->key.angle && Abs(vertices[i]->key.angle-vertices[j]->key.angle)<angleThres)
				{
					int cid2 = vertices[j]->key.contourID;
					int pid2 = vertices[j]->key.pointID;
					float d2 = d1;
					if(cid1 != cid2)
					{
						float d0 = Distance(contours[cid1].X[pid1], contours[cid1].Y[pid1], contours[cid2].X[pid2], contours[cid2].Y[pid2]);
						d2 = d2 + EdgeWeight(d0);
					}
					if(d2 < vertices[j]->d)
					{
						vertices[j]->d = d2;
						vertices[j]->pi = vertices[i];
						vertices[j]->f = iter;
						bchanged = true;
					}
				}
			}
		}
	}
	return bchanged;
}