/* * Copyright (C) 2012 Jacquet Wong * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.musicg.fingerprint; import java.util.HashMap; import java.util.Iterator; import java.util.List; import com.musicg.math.rank.MapRank; import com.musicg.math.rank.MapRankInteger; /** * Compute the similarity of two fingerprints * * @author jacquet * */ public class FingerprintSimilarityComputer{ private FingerprintSimilarity fingerprintSimilarity; byte[] fingerprint1, fingerprint2; /** * Constructor, ready to compute the similarity of two fingerprints * * @param fingerprint1 * @param fingerprint2 */ public FingerprintSimilarityComputer(byte[] fingerprint1, byte[] fingerprint2){ this.fingerprint1=fingerprint1; this.fingerprint2=fingerprint2; fingerprintSimilarity=new FingerprintSimilarity(); } /** * Get fingerprint similarity of inout fingerprints * * @return fingerprint similarity object */ public FingerprintSimilarity getFingerprintsSimilarity(){ HashMap<Integer,Integer> offset_Score_Table=new HashMap<Integer,Integer>(); // offset_Score_Table<offset,count> int numFrames=0; float score=0; int mostSimilarFramePosition=Integer.MIN_VALUE; // one frame may contain several points, use the shorter one be the denominator if (fingerprint1.length>fingerprint2.length){ numFrames=FingerprintManager.getNumFrames(fingerprint2); } else{ numFrames=FingerprintManager.getNumFrames(fingerprint1); } // get the pairs PairManager pairManager=new PairManager(); HashMap<Integer,List<Integer>> this_Pair_PositionList_Table=pairManager.getPair_PositionList_Table(fingerprint1); HashMap<Integer,List<Integer>> compareWave_Pair_PositionList_Table=pairManager.getPair_PositionList_Table(fingerprint2); Iterator<Integer> compareWaveHashNumberIterator=compareWave_Pair_PositionList_Table.keySet().iterator(); while (compareWaveHashNumberIterator.hasNext()){ int compareWaveHashNumber=compareWaveHashNumberIterator.next(); // if the compareWaveHashNumber doesn't exist in both tables, no need to compare if (!this_Pair_PositionList_Table.containsKey(compareWaveHashNumber) || !compareWave_Pair_PositionList_Table.containsKey(compareWaveHashNumber)){ continue; } // for each compare hash number, get the positions List<Integer> wavePositionList=this_Pair_PositionList_Table.get(compareWaveHashNumber); List<Integer> compareWavePositionList=compareWave_Pair_PositionList_Table.get(compareWaveHashNumber); Iterator<Integer> wavePositionListIterator=wavePositionList.iterator(); while (wavePositionListIterator.hasNext()){ int thisPosition=wavePositionListIterator.next(); Iterator<Integer> compareWavePositionListIterator=compareWavePositionList.iterator(); while (compareWavePositionListIterator.hasNext()){ int compareWavePosition=compareWavePositionListIterator.next(); int offset=thisPosition-compareWavePosition; if (offset_Score_Table.containsKey(offset)){ offset_Score_Table.put(offset, offset_Score_Table.get(offset)+1); } else{ offset_Score_Table.put(offset, 1); } } } } // map rank MapRank mapRank=new MapRankInteger(offset_Score_Table,false); // get the most similar positions and scores List<Integer> orderedKeyList=mapRank.getOrderedKeyList(100, true); if (orderedKeyList.size()>0){ int key=orderedKeyList.get(0); // get the highest score position if (mostSimilarFramePosition==Integer.MIN_VALUE){ mostSimilarFramePosition=key; score=offset_Score_Table.get(key); // accumulate the scores from neighbours if (offset_Score_Table.containsKey(key-1)){ score+=offset_Score_Table.get(key-1)/2; } if (offset_Score_Table.containsKey(key+1)){ score+=offset_Score_Table.get(key+1)/2; } } } /* Iterator<Integer> orderedKeyListIterator=orderedKeyList.iterator(); while (orderedKeyListIterator.hasNext()){ int offset=orderedKeyListIterator.next(); System.out.println(offset+": "+offset_Score_Table.get(offset)); } */ score/=numFrames; float similarity=score; // similarity >1 means in average there is at least one match in every frame if (similarity>1){ similarity=1; } fingerprintSimilarity.setMostSimilarFramePosition(mostSimilarFramePosition); fingerprintSimilarity.setScore(score); fingerprintSimilarity.setSimilarity(similarity); return fingerprintSimilarity; } }