轉自:http://blog.csdn.net/jia20003/article/details/7771651#comments
影像處理之相似圖片識別(長條圖應用篇)
演算法概述:
首先對源映像與要篩選的映像進行長條圖資料擷取,對採集的各自映像長條圖進行歸一化再
使用巴氏係數演算法對長條圖資料進行計算,最終得出映像相似性值,其值範圍在[0, 1]之間
0表示極其不同,1表示極其相似(相同)。
演算法步驟詳解:
大致可以分為兩步,根據源映像與候選映像的像素資料,產生各自長條圖資料。第二步:使
用第一步輸出的長條圖結果,運用巴氏係數(Bhattacharyya coefficient)演算法,計算出相似程
度值。
第一步:長條圖計算
長條圖分為灰階長條圖與RGB長條圖,對於灰階映像長條圖計算十分簡單,只要初始化一
個大小為256的長條圖數組H,然後根據像素值完成頻率分布統計,假設像素值為124,則
H[124] += 1, 而對於彩色RGB像素來說長條圖表達有兩種方式,一種是單一長條圖,另外一
種是三維長條圖,三維長條圖比較簡單明了,分別對應RGB三種顏色,定義三個長條圖HR,
HG, HB, 假設某一個像素點P的RGB值為(4, 231,129), 則對於的長條圖計算為HR[4] += 1,
HG[231] += 1, HB[129] += 1, 如此對每個像素點完成統計以後,RGB彩色長條圖資料就產生了。
而RGB像素的單一長條圖SH表示稍微複雜點,每個顏色的值範圍為0 ~ 255之間的,假設
可以分為一定範圍等份,當8等份時,每個等份的值範圍為32, 16等份時,每個等份值範
圍為16,當4等份時候,每個等份值的範圍為64,假設RGB值為(14, 68, 221), 16等份之
後,它對應長條圖索引值(index)分別為: (0, 4, 13), 根據計算索引值公式:index = R + G*16 + B*16*16
對應的長條圖index = 0 + 4*16 + 13 * 16 * 16, SH[3392] += 1
如此遍曆所有RGB像素值,完成長條圖資料計算。
第二步:巴氏係數計算,計算公式如下:
其中P, P’分別代表源與候選的映像長條圖資料,對每個相同i的資料點乘積開平方以後相加
得出的結果即為映像相似性值(巴氏係數因子值),範圍為0到1之間。
程式效果:
相似性超過99%以上,極其相似
相似性為:72%, 一般相似
程式長條圖計算原始碼如下:
[java]
view plaincopyprint?
- public void setGreenBinCount(int greenBinCount) {
- this.greenBins = greenBinCount;
- }
-
- public void setBlueBinCount(int blueBinCount) {
- this.blueBins = blueBinCount;
- }
-
- public float[] filter(BufferedImage src, BufferedImage dest) {
- int width = src.getWidth();
- int height = src.getHeight();
-
- int[] inPixels =
new int[width*height];
- float[] histogramData =
new float[redBins * greenBins * blueBins];
- getRGB( src, 0,
0, width, height, inPixels );
- int index = 0;
- int redIdx =
0, greenIdx = 0, blueIdx =0;
- int singleIndex = 0;
- float total =
0;
- for(int row=0; row<height; row++) {
- int ta =
0, tr = 0, tg =0, tb =
0;
- for(int col=0; col<width; col++) {
- index = row * width + col;
- ta = (inPixels[index] >> 24) &0xff;
- tr = (inPixels[index] >>
16) & 0xff;
- tg = (inPixels[index] >> 8) &0xff;
- tb = inPixels[index] &
0xff;
- redIdx = (int)getBinIndex(redBins, tr,255);
- greenIdx = (int)getBinIndex(greenBins, tg,255);
- blueIdx = (int)getBinIndex(blueBins, tb,255);
- singleIndex = redIdx + greenIdx * redBins + blueIdx * redBins * greenBins;
- histogramData[singleIndex] += 1;
- total += 1;
- }
- }
-
- // start to normalize the histogram data
- for (int i =0; i < histogramData.length; i++)
- {
- histogramData[i] = histogramData[i] / total;
- }
-
- return histogramData;
- }
public void setGreenBinCount(int greenBinCount) {this.greenBins = greenBinCount;}public void setBlueBinCount(int blueBinCount) {this.blueBins = blueBinCount;}public float[] filter(BufferedImage src, BufferedImage dest) {int width = src.getWidth(); int height = src.getHeight(); int[] inPixels = new int[width*height]; float[] histogramData = new float[redBins * greenBins * blueBins]; getRGB( src, 0, 0, width, height, inPixels ); int index = 0; int redIdx = 0, greenIdx = 0, blueIdx = 0; int singleIndex = 0; float total = 0; for(int row=0; row<height; row++) { int ta = 0, tr = 0, tg = 0, tb = 0; for(int col=0; col<width; col++) { index = row * width + col; ta = (inPixels[index] >> 24) & 0xff; tr = (inPixels[index] >> 16) & 0xff; tg = (inPixels[index] >> 8) & 0xff; tb = inPixels[index] & 0xff; redIdx = (int)getBinIndex(redBins, tr, 255); greenIdx = (int)getBinIndex(greenBins, tg, 255); blueIdx = (int)getBinIndex(blueBins, tb, 255); singleIndex = redIdx + greenIdx * redBins + blueIdx * redBins * greenBins; histogramData[singleIndex] += 1; total += 1; } } // start to normalize the histogram data for (int i = 0; i < histogramData.length; i++) { histogramData[i] = histogramData[i] / total; } return histogramData;}
計算巴氏係數的代碼如下:
[java]
view plaincopyprint?
- /**
- * Bhattacharyya Coefficient
- * http://www.cse.yorku.ca/~kosta/CompVis_Notes/bhattacharyya.pdf
- *
- * @return
- */
- public double modelMatch() {
- HistogramFilter hfilter = new HistogramFilter();
- float[] sourceData = hfilter.filter(sourceImage,null);
- float[] candidateData = hfilter.filter(candidateImage,null);
- double[] mixedData =new
double[sourceData.length];
- for(int i=0; i<sourceData.length; i++ ) {
- mixedData[i] = Math.sqrt(sourceData[i] * candidateData[i]);
- }
-
- // The values of Bhattacharyya Coefficient ranges from 0 to 1,
- double similarity =
0;
- for(int i=0; i<mixedData.length; i++ ) {
- similarity += mixedData[i];
- }
-
- // The degree of similarity
- return similarity;
- }
/** * Bhattacharyya Coefficient * http://www.cse.yorku.ca/~kosta/CompVis_Notes/bhattacharyya.pdf * * @return */public double modelMatch() {HistogramFilter hfilter = new HistogramFilter();float[] sourceData = hfilter.filter(sourceImage, null);float[] candidateData = hfilter.filter(candidateImage, null);double[] mixedData = new double[sourceData.length];for(int i=0; i<sourceData.length; i++ ) {mixedData[i] = Math.sqrt(sourceData[i] * candidateData[i]);}// The values of Bhattacharyya Coefficient ranges from 0 to 1,double similarity = 0;for(int i=0; i<mixedData.length; i++ ) {similarity += mixedData[i];}// The degree of similarityreturn similarity;}
轉載文章請務必註明出自本部落格