void FeatureMatchThread::run()
{
	Mat resultImg;
	Mat grayImg;

	cvtColor(cropImg,grayImg,CV_BGR2GRAY);
	featureDetector.detect(grayImg,keyPoints);
	featureExtractor.compute(grayImg,keyPoints,descriptors);
	flannIndex.build(descriptors,flann::LshIndexParams(12,20,2),cvflann::FLANN_DIST_HAMMING);

	while(true)
	{
		Mat captureImage_gray;

		vector<KeyPoint> captureKeyPoints;
		Mat captureDescription;
		vector<DMatch> goodMatches;

		cap >> captureImage;
		
		if(captureImage.empty())
			continue;

		cvtColor(captureImage,captureImage_gray,CV_BGR2GRAY);
		featureDetector.detect(captureImage_gray,captureKeyPoints);
		featureExtractor.compute(captureImage_gray,captureKeyPoints,captureDescription);

		Mat matchIndex(captureDescription.rows,2,CV_32SC1);
		Mat matchDistance(captureDescription.rows,2,CV_32FC1);

		flannIndex.knnSearch(captureDescription,matchIndex,matchDistance,2,flann::SearchParams());
		
		for(int i=0;i<matchDistance.rows;i++)
		{
			if(matchDistance.at<float>(i,0) < 0.6 * matchDistance.at<float>(i,1))
			{
				DMatch dmatches(i,matchIndex.at<int>(i,0),matchDistance.at<float>(i,0));
				goodMatches.push_back(dmatches);
			}
		}

		drawMatches(captureImage,captureKeyPoints,cropImg,keyPoints,goodMatches,resultImg);
		emit NewFeatureMatch(&resultImg);

		imshow(WindowName,captureImage);
		cv::setMouseCallback(WindowName,mouse_callback);

		captureKeyPoints.clear();
		goodMatches.clear();
		waitKey(30);
	}

	return;
}
void YawAngleEstimator::Indexmatch(Mat& CurrentDescriptors, float* CurrentVote)
{
	//Lowe's Algorithm to caculate vote for each angletemplate
	for (int i = 4; i < AngleNum; i++)
	{
		//rows:numbers of keypoints
		Mat matchIndex(CurrentDescriptors.rows, 2, CV_32SC1), matchDistance(CurrentDescriptors.rows, 2, CV_32FC1);

		CurrentVote[i] = 0;

		//cout << CurrentDescriptors[0] << endl;

		YawIndex[i].knnSearch(CurrentDescriptors, matchIndex, matchDistance, 2, flann::SearchParams());
		for (int j = 0; j < matchDistance.rows; j++)
		{
			if (matchDistance.at<float>(j, 0) < 0.6*matchDistance.at<float>(j, 1))
				++CurrentVote[i];
		}
	}
}
/**
Removes comm addresses from the 3 lists that are already in the database and have been updated.
It takes the 3 lists in as parameters and modifies them accordingly. It also populates the list
of comm address ids that are free to be recycled during updating.
*/
void CPplCommAddrTable::RemoveNonUpdatedAddrsL(RArray<TMatch>& aNewPhones, RArray<TPtrC>& aNewEmails, RArray<TPtrC>& aNewSips,
					  RArray<TInt>& aFreeCommAddrIds, const TInt aItemId,CPplCommAddrTable::TCommAddrExtraInfoType 
                      aExtraInfoType )
	{
	// build the RSqlStatement
	RSqlStatement stmnt;
	CleanupClosePushL(stmnt);
	stmnt.PrepareL(iDatabase, iWholeSelectStmnt->SqlStringL() );
	const TInt KContactIdParamIndex(KFirstIndex); // first and only parameter in the query
	User::LeaveIfError(stmnt.BindInt(KContactIdParamIndex, aItemId) ) ;

	// fetch the results from the query and compare them with the new comm_addrs we have
	TInt err(KErrNone);
	while ((err = stmnt.Next() ) == KSqlAtRow)
		{
		const TInt KType(stmnt.ColumnInt(iWholeSelectStmnt->ParameterIndex(KCommAddrType() ) ) );
		if (KType == EPhoneNumber)
			{
			TMatch phoneNumber;
			TPtrC valString    = stmnt.ColumnTextL(iWholeSelectStmnt->ParameterIndex(KCommAddrValue() ) );
			TPtrC extValString = stmnt.ColumnTextL(iWholeSelectStmnt->ParameterIndex(KCommAddrExtraValue() ) );
			TInt extTypeInfoString = stmnt.ColumnInt(iWholeSelectStmnt->ParameterIndex(KCommAddrExtraTypeInfo() ) );
			User::LeaveIfError(TLex(valString).Val(phoneNumber.iLowerSevenDigits) );
			User::LeaveIfError(TLex(extValString).Val(phoneNumber.iUpperDigits) );

			TInt matchIndex(aNewPhones.Find(phoneNumber, TIdentityRelation<TMatch>(&TMatch::Equals) ) );
			// remove any phone numbers from the new list if we already
			// have them in the db and they haven't changed...
			if (matchIndex != KErrNotFound  && (extTypeInfoString == aExtraInfoType))
				{
				aNewPhones.Remove(matchIndex);
				}
			// ...and add any spare ids to the recycle list
			else
				{
				aFreeCommAddrIds.AppendL(
					stmnt.ColumnInt(iWholeSelectStmnt->ParameterIndex(KCommAddrId() ) ) );
				}
			}
		else // is Email or SIP
			{
			TPtrC valString = stmnt.ColumnTextL(iWholeSelectStmnt->ParameterIndex(KCommAddrValue() ) );
			TInt matchIndex(0);

			// remove any email and sip addresses from the new list if
			// we already have them in the db and they haven't changed...
			if (KType == EEmailAddress)
				{
				matchIndex = aNewEmails.Find(valString);
				if (matchIndex != KErrNotFound)
					{
					aNewEmails.Remove(matchIndex);
					}
				}
			else // SIP
				{
				matchIndex = aNewSips.Find(valString);
				if (matchIndex != KErrNotFound)
					{
					aNewSips.Remove(matchIndex);
					}
				}

			// ...and add any spare ids to the recycle list
			if (matchIndex == KErrNotFound)
				{
				aFreeCommAddrIds.AppendL(
					stmnt.ColumnInt(iWholeSelectStmnt->ParameterIndex(KCommAddrId() ) ) );
				}
			}
		}
	// leave if we didn't complete going through the results properly
	if(err != KSqlAtEnd)
		{
		User::Leave(err);
		}
	CleanupStack::PopAndDestroy(&stmnt);
	}