Esempio n. 1
0
void gridStartIterateFiltered(int32_t x, int32_t y, uint32_t radius, PointTree::Filter *filter, Condition const &condition)
{
	if (filter == NULL)
	{
		gridPointTree->query(x, y, radius);
	}
	else
	{
		gridPointTree->query(*filter, x, y, radius);
	}
	PointTree::ResultVector::iterator w = gridPointTree->lastQueryResults.begin(), i;
	for (i = w; i != gridPointTree->lastQueryResults.end(); ++i)
	{
		BASE_OBJECT *obj = static_cast<BASE_OBJECT *>(*i);
		if (!condition.test(obj))  // Check if we should skip this object.
		{
			filter->erase(gridPointTree->lastFilteredQueryIndices[i - gridPointTree->lastQueryResults.begin()]);  // Stop the object from appearing in future searches.
		}
		else if (isInRadius(obj->pos.x - x, obj->pos.y - y, radius))  // Check that search result is less than radius (since they can be up to a factor of sqrt(2) more).
		{
			*w = *i;
			++w;
		}
	}
	gridPointTree->lastQueryResults.erase(w, i);  // Erase all points that were a bit too far.
	gridPointTree->lastQueryResults.push_back(NULL);  // NULL-terminate the result.
	gridIterator = &gridPointTree->lastQueryResults[0];
	/*
	// In case you are curious.
	debug(LOG_WARNING, "gridStartIterateFiltered(%d, %d, %u) found %u objects", x, y, radius, (unsigned)gridPointTree->lastQueryResults.size() - 1);
	*/
}
void QRFinder::FindFinderPatterns(cv::Mat& inputImg, Rect regionOfInterest, vector<FinderPattern*> & finderPatterns, vector<Drawable*> & debugVector)
{
	struct timespec start,end;
	SET_TIME(&start);	

	//Get parameters from config
	edgeThreshold = config->GetIntegerParameter("EdgeThreshold");
	debugLevel = config->GetIntegerParameter("QR Debug Level");
	int verticalResolution = config->GetIntegerParameter("YResolution");
	nonMaxEnabled = config->GetBooleanParameter("EdgeNonMax");
	minimumFinderPatternScore = config->GetIntegerParameter("MinimumFPScore");
	detectorSize = config->GetIntegerParameter("DetectorSize");

	int yBorder = detectorSize;
	vector<Point3i> exclusionZones;
	
	//Calculate limits
	int maxColumn = regionOfInterest.x + regionOfInterest.width;
	maxColumn -= detectorSize;	
	int maxRow = regionOfInterest.y + regionOfInterest.height;
	int xStart = regionOfInterest.x;
	int yStart = regionOfInterest.y;
	xStart += detectorSize;
	yStart += detectorSize;
	maxColumn -= detectorSize;
	maxRow -= detectorSize;

	
	if (debugLevel > 0)
		debugVector.push_back(new DebugRectangle(Rect(Point2i(xStart,yStart),Point2i(maxColumn,maxRow)),Colors::Aqua,1));

	
	//Find horizontal edges
	SET_TIME(&start);
	FindEdgesClosed(inputImg,regionOfInterest,edgeArray,edgeThreshold,nonMaxEnabled,detectorSize);
	SET_TIME(&end);
	double edgeTime_local = calc_time_double(start,end);
	edgeTime = (edgeTime + edgeTime_local)/2.0;
	config->SetLabelValue("EdgeTime",(float)edgeTime/1000.0f);
	
	//If debug level set, find all vertical edges and draw them
	if (debugLevel <= -2)
	{
		for (int x = 1; x < verticalEdgeArray.rows-1; x ++)
		{
			FindEdgesVerticalClosed(inputImg,x);		
			const short * verticalEdgePtr = verticalEdgeArray.ptr<short>(x);
			for (int y = 0; y < (verticalEdgeArray.cols);y++)
			{
				short transition = verticalEdgePtr[y];
				if (transition < 0)
				{
					debugVector.push_back(new DebugCircle(Point2i(x,y),0,Colors::Fuchsia,true));
				}
				else if (transition > 0)
				{
					debugVector.push_back(new DebugCircle(Point2i(x,y),0,Colors::Cyan,true));
				}
			}
		}	
	}
	//END
	
	
	int bw[6] = { 0 };
	int k = 0;
	//LOGV(LOGTAG_QR,"ImgSize=[%d,%d] EdgeSize=[%d,%d]",inputImg.rows,inputImg.cols,edgeArray.rows,edgeArray.cols);

	int yDirection = 1;
	int yCenter = yStart + (maxRow - yStart)/2;
	int y = yStart, absOffset = 0;

	LOGV(LOGTAG_QR,"Beginning search. y[%d->%d], Center=%d, x[%d->%d]",yStart,maxRow,yCenter,xStart,maxColumn);
	
	while (y < maxRow && y >= yStart)
	{	
		y = yCenter + absOffset * yDirection;

		if (yDirection == 1) absOffset += verticalResolution;	//Increment every other frame		
		yDirection = -yDirection;								//Change direction every frame

		k = 0;
		bw[0] = bw[1] = bw[2] = bw[3] = bw[4] = bw[5] = 0;

		const short * edgeRowPtr = edgeArray.ptr<short>(y);
		for (int x = xStart; x < maxColumn; x++)
		{
			if (isInRadius(exclusionZones,Point2i(x,y)))
				continue;

			int transition =  edgeRowPtr[x]; //getTransition(Mi,x,threshold);

			
			if (k == 0) //Haven't found edge yet
			{
				if (transition < 0) /* Light->dark transistion */
				{					
					k++;
				}
			}
			else //Found at least one edge
			{
				if ((k & 1) == 1) //Counting dark
				{
					if (transition > 0) //dark to light
					{					
						++k;
					}
				}
				else //Counting light
				{
					if (transition < 0) //light to dark
					{					
						++k;
					}
				}
			}

			if (k > 0) ++bw[k-1];

			if (FP_DEBUG_ENABLED && (debugLevel == -1 || debugLevel == -2))
			{				
				if (transition < 0)
					debugVector.push_back(new DebugCircle(Point2i(x,y),0,Colors::Lime,true));
				else if (transition > 0)
					debugVector.push_back(new DebugCircle(Point2i(x,y),0,Colors::Yellow,true));

				
			}	


			if (k == 6)
			{		
				int result = 0;
				result = CheckRatios(bw,NULL);

				if (result == 1)
				{	
					//LOGV(LOGTAG_QR,"Ratio check pass");
					//Center based on initial ratio					
					float patternCenterWidth = (float)bw[2];
					int tempXCenter = (x - bw[4] - bw[3]) - (int)round(patternCenterWidth/2.0f); 
					float xOffset = (patternCenterWidth/6.0f);
					
					//y coordinate of center. If check fails, returns 0.
					int tempYCenterArray[] = {0,0,0};

					int * verticalPatternSizes[3];

					for (int i = 0;i < 3;i++)
						verticalPatternSizes[i] = new int[5];

					tempYCenterArray[0] = FindCenterVertical(inputImg, tempXCenter, y, bw, debugVector,verticalPatternSizes[0]);
					tempYCenterArray[1] = FindCenterVertical(inputImg, tempXCenter - xOffset, y, bw, debugVector,verticalPatternSizes[1]);
					tempYCenterArray[2] = FindCenterVertical(inputImg, tempXCenter + xOffset, y, bw, debugVector,verticalPatternSizes[2]);
										
					int tempYCenter = 0;
					int passCount = 0;
					float avgYSize = 0;

					int averageVerticalSize[5] = {0,0,0,0,0};

					for (int yTest = 0; yTest < 3; yTest++)
					{
						if (tempYCenterArray[yTest] > 0)
						{
							passCount++;
							tempYCenter += tempYCenterArray[yTest];
							for (int i=0;i<5;i++)
							{
								averageVerticalSize[i] += (verticalPatternSizes[yTest])[i];
								avgYSize += (verticalPatternSizes[yTest])[i]; 
							}
						}						
					}

					if (passCount >= 2)
					{
						//LOGV(LOGTAG_QR,"Vertical test pass-1");
						
						tempYCenter = (int)round((float)tempYCenter / (float)passCount);
						avgYSize = (float)avgYSize / (float)passCount;

						int allowedVariance = (int)avgYSize >> 2;
						bool yVarianceTest = true;
						for (int yTest = 0; yTest < 3; yTest++)
						{
							if (tempYCenterArray[yTest] > 0)
							{
								if (abs(tempYCenterArray[yTest] - tempYCenter) > allowedVariance)
								{
									yVarianceTest = false;
									break;
								}
							}						
						}

						if (yVarianceTest)
						{
							//LOGV(LOGTAG_QR,"Vertical test pass-2. Passcount=%d",passCount);
							//Average the vertical pattern sizes
							for (int i=0;i<5;i++)
							{
								averageVerticalSize[i] = idiv(averageVerticalSize[i],passCount);
							}
							//LOGV(LOGTAG_QR,"Averaged sizes. Center=%d",averageVerticalSize[2]);

							int tempXCenterArray[] = {0,0,0};
							int xSizeArray[] = {0,0,0};
							int yOffset = idiv(averageVerticalSize[2],6.0f);

							//LOGV(LOGTAG_QR,"Yoffset=%d,yCenter=%d",yOffset,tempYCenter);
							tempXCenterArray[0] = FindCenterHorizontal(tempXCenter, tempYCenter-yOffset, bw, xSizeArray[0], debugVector); 
							tempXCenterArray[1] = FindCenterHorizontal(tempXCenter, tempYCenter, bw, xSizeArray[1], debugVector); 
							tempXCenterArray[2] = FindCenterHorizontal(tempXCenter, tempYCenter+yOffset, bw, xSizeArray[2], debugVector); 

							tempXCenter = 0;
							passCount = 0;
							float avgXSize = 0;

							for (int xTest = 0; xTest < 3; xTest++)
							{
								if (tempXCenterArray[xTest] > 0)
								{
									passCount++;
									tempXCenter += tempXCenterArray[xTest];
									avgXSize += xSizeArray[xTest];
								}						
							}

							if (passCount >= 2)
							{
								
								//LOGV(LOGTAG_QR,"Horizontal test pass");
								tempXCenter = (int)round((float)tempXCenter / (float)passCount);
								avgXSize = (float)avgXSize/(float)passCount;
								//allowedVariance = (int)round((float)avgYSize/1.5f);
								float aspectRatio = avgXSize/avgYSize;
								
								if (aspectRatio > 0.33f && aspectRatio < 3.0f)
								{
									
									//LOGV(LOGTAG_QR,"Size test pass");
									Point2i finderPatternCenter = Point2i(tempXCenter,tempYCenter); //Center of finder pattern

									int finderPatternSize =  MAX(avgXSize,avgYSize);
									int fpRadius = (int)round((float)finderPatternSize/2.0f);
									int fpRadiusExclude = ipow(finderPatternSize,2);

									//LOGD(LOGTAG_QR,"Creating new pattern[%d,%d]",avgXSize,avgYSize);
									//Create a new pattern
									FinderPattern * newPattern = new FinderPattern(finderPatternCenter,Size2i(avgXSize,avgYSize));
									Size2f patternSearchSize = Size2f(avgXSize,avgYSize);

									vector<Point2i> corners;
									struct timespec fastStart,fastEnd;
									SET_TIME(&fastStart);
									fastQRFinder->LocateFPCorners(inputImg,newPattern,corners,debugVector);
//									fastQRFinder->CheckAlignmentPattern(inputImg,finderPatternCenter,patternSearchSize,corners,debugVector);
									SET_TIME(&fastEnd);
									double fastFPTime_Local = calc_time_double(fastStart,fastEnd);
									fastFPTime += fastFPTime_Local;
									if (corners.size() == 4)
									{
										//if (validatePattern(newPattern,finderPatterns))
										//{
										newPattern->patternCorners = corners;
										exclusionZones.push_back(Point3i(finderPatternCenter.x,finderPatternCenter.y, fpRadiusExclude));
										finderPatterns.push_back(newPattern);
										if (FP_DEBUG_ENABLED && debugLevel > 0)
										{
											debugVector.push_back(new DebugCircle(finderPatternCenter,fpRadius,Colors::MediumSpringGreen,1,true));
											for (int i=0;i<corners.size();i++)
											{
												if (FP_DEBUG_ENABLED && debugLevel > 0)
													debugVector.push_back(new DebugCircle(corners[i],10,Colors::DodgerBlue,2));
											}
										}
										//}
										//else
										//{
										//	//LOGV(LOGTAG_QR,"Compare check failed");
										//	if (FP_DEBUG_ENABLED && debugLevel > 0)
										//		debugVector.push_back(new DebugCircle(finderPatternCenter,fpRadius,Colors::HotPink,2));
										//}
									}
									else
									{
										
										//LOGV(LOGTAG_QR,"FAST check failed");
										if (FP_DEBUG_ENABLED && debugLevel > 0)
											debugVector.push_back(new DebugCircle(finderPatternCenter,fpRadius,Colors::Red,2));
										delete newPattern;
									}
								}
								else
								{
									//LOGV(LOGTAG_QR,"Size check failed");
									//Size check failed
									if (FP_DEBUG_ENABLED && debugLevel > 1)
										debugVector.push_back(new DebugCircle(Point2i(tempXCenter,tempYCenter),13, Colors::HotPink,1));
								}
							}
							else
							{
								//LOGV(LOGTAG_QR,"Horizontal check failed");
								//Vertical check succeeded, but horizontal re-check failed
								if (FP_DEBUG_ENABLED && debugLevel > 1)
									debugVector.push_back(new DebugCircle(Point2i(tempXCenter,tempYCenter),12, Colors::OrangeRed,1));
							}
						}
						else
						{
							//LOGV(LOGTAG_QR,"Variance test failed. AllowedVariance = %d, yCenters = %d,%d,%d [avg=%d], AvgYSize=%d",allowedVariance,tempYCenterArray[0],tempYCenterArray[1],tempYCenterArray[2],tempYCenter,avgYSize);
							//Vertical variance test failed
							if (FP_DEBUG_ENABLED && debugLevel > 1)
								debugVector.push_back(new DebugCircle(Point2i(tempXCenter,tempYCenter),14, Colors::MediumSpringGreen,1));
						}

					} else
					{
						//Ratios were correct but vertical check failed
						if (FP_DEBUG_ENABLED && debugLevel > 2)
						{
							if (tempYCenter == 0) //ratio fail
								debugVector.push_back(new DebugCircle(Point2i(tempXCenter,y),10,Colors::Aqua,1));
							else if (tempYCenter == -1)	//topcheck fail				
								debugVector.push_back(new DebugCircle(Point2i(tempXCenter,y),10,Colors::Orange,1));
							else if (tempYCenter == -2)	//bottomcheck fail							
								debugVector.push_back(new DebugCircle(Point2i(tempXCenter,y),10,Colors::Lime,1));
						}
					}
				}