public static double[] GetTemplateSimilarity(Template query, Template[] db) { double[] similarityRates = new double[db.Length]; for (int k = 0; k < db.Length; k++) { Template templateDb = db[k]; // Reset buckets array // Is this necessary? for (int j = 0; j < buckets.Length; j++) { buckets[j] = 0; } foreach (Cylinder queryCylinder in query.Cylinders) { foreach (Cylinder cylinderDb in templateDb.Cylinders) { if (CylinderHelper.GetAngleDiff(queryCylinder.Angle, cylinderDb.Angle) < angleThreshold && queryCylinder.Norm + cylinderDb.Norm != 0) { uint[] givenXOR = queryCylinder.Values.Zip(cylinderDb.Values, (first, second) => first ^ second).ToArray(); double givenXORNorm = Math.Sqrt(CylinderHelper.GetOneBitsCount(givenXOR)); // Bitwise version //double givenXORNorm = CalculateCylinderNorm(givenXOR); // Stupid version uint bucketIndex = (uint)Math.Floor(givenXORNorm / (queryCylinder.Norm + cylinderDb.Norm) * bucketsCount); if (bucketIndex == bucketsCount) { bucketIndex--; } buckets[bucketIndex]++; } } } int numPairs = ComputeNumPairs(templateDb.Cylinders.Length, query.Cylinders.Length); int sum = 0, t = numPairs, i = 0; while (i < bucketsCount && t > 0) { sum += (int)Math.Min(buckets[i], t) * i; t -= (int)Math.Min(buckets[i], t); i++; } sum += t * (int)bucketsCount; similarityRates[k] = 1 - (float)sum / (numPairs * bucketsCount); } return similarityRates; }
public static double[] GetTemplateSimilarityOptimized(Template query, CylinderDatabase db, int[] dbTemplateLengths) { double[] similarityRates = new double[dbTemplateLengths.Length]; bucketMatrix = new uint[dbTemplateLengths.Length, bucketsCount]; for (int k = 0; k < db.Cylinders.Length; k++) { Cylinder cylinderDb = db.Cylinders[k]; foreach (Cylinder queryCylinder in query.Cylinders) { uint[] givenXOR = queryCylinder.Values.Zip(cylinderDb.Values, (first, second) => first ^ second).ToArray(); //for (int i = 0; i < givenXOR.Length; i++) //{ // Console.Write(givenXOR[i] + ", "); //} //Console.WriteLine(); uint oneBitsCount = CylinderHelper.GetOneBitsCount(givenXOR); //Console.Write(oneBitsCount + " "); double givenXORNorm = Math.Sqrt(oneBitsCount); // Bitwise version //double givenXORNorm = CalculateCylinderNorm(givenXOR); // Stupid version if (CylinderHelper.GetAngleDiff(queryCylinder.Angle, cylinderDb.Angle) < angleThreshold && queryCylinder.Norm + cylinderDb.Norm != 0) { uint bucketIndex = (uint)Math.Floor(givenXORNorm / (queryCylinder.Norm + cylinderDb.Norm) * bucketsCount); //if (bucketIndex >= 63) //{ // Console.Write("LOOOOL"); // Console.WriteLine(k); //} if (bucketIndex == bucketsCount) { bucketIndex--; } uint row = db.TemplateIndices[k]; bucketMatrix[row, bucketIndex]++; } } } //Console.WriteLine("END"); PrintMatrix(bucketMatrix); for (int k = 0; k < dbTemplateLengths.Length; k++) { int numPairs = ComputeNumPairs(dbTemplateLengths[k], query.Cylinders.Length); int sum = 0, t = numPairs, i = 0; while (i < bucketsCount && t > 0) { sum += (int)Math.Min(bucketMatrix[k, i], t) * i; t -= (int)Math.Min(bucketMatrix[k, i], t); i++; } sum += t * (int)bucketsCount; similarityRates[k] = 1 - (float)sum / (numPairs * bucketsCount); } return similarityRates; }
public static double[] GetTemplateSimilarityWithMask(Template query, Template[] db) { double[] similarityRates = new double[db.Length]; for (int k = 0; k < db.Length; k++) { Template templateDb = db[k]; // Reset buckets array // Is this necessary? for (int j = 0; j < buckets.Length; j++) { buckets[j] = 0; } for (int countI = 0; countI < query.Cylinders.Length; countI += 2) { for (int countJ = 0; countJ < templateDb.Cylinders.Length; countJ += 2) { if (CylinderHelper.GetAngleDiff(query.Cylinders[countI].Angle, templateDb.Cylinders[countJ].Angle) <= angleThreshold) { uint[] common = query.Cylinders[countI + 1].Values.Zip(templateDb.Cylinders[countJ + 1].Values, (first, second) => first & second).ToArray(); uint[] firstAndSecond = query.Cylinders[countI].Values.Zip(common, (first, second) => first & second).ToArray(); uint[] secondAndFirst = templateDb.Cylinders[countJ].Values.Zip(common, (first, second) => first & second).ToArray(); double givenFristNorm = Math.Sqrt(CylinderHelper.GetOneBitsCount(firstAndSecond)); double givenSecondNorm = Math.Sqrt(CylinderHelper.GetOneBitsCount(secondAndFirst)); uint[] givenXOR = firstAndSecond.Zip(secondAndFirst, (first, second) => first ^ second).ToArray(); double givenXORNorm = Math.Sqrt(CylinderHelper.GetOneBitsCount(givenXOR)); // Bitwise version //double givenXORNorm = CalculateCylinderNorm(givenXOR); // Stupid version uint bucketIndex = (uint)Math.Floor(givenXORNorm / (givenFristNorm + givenSecondNorm) * bucketsCount); if (bucketIndex == bucketsCount) { bucketIndex--; } buckets[bucketIndex]++; } } } int numPairs = ComputeNumPairs(templateDb.Cylinders.Length/2, query.Cylinders.Length/2); int sum = 0, t = numPairs, i = 0; while (i < bucketsCount && t > 0) { sum += (int)Math.Min(buckets[i], t) * i; t -= (int)Math.Min(buckets[i], t); i++; } sum += t * (int)bucketsCount; similarityRates[k] = 1 - (float)sum / (numPairs * bucketsCount); } return similarityRates; }