Hatena::ブログ(Diary)

にのせき日記

2009-02-08

[][]ヒストグラムの比較

OpenCVを使ってヒストグラムの比較を行ってみる。

どうやるかというと、二つの画像のヒストグラムを計算してから、cvCompareHistを用いてそれらを比較すればいい。

今回は以下の二つの画像を使ってみた。自分の手の画像です。

myhand1.jpg

f:id:ninoseki:20090208214500j:image

myhand2.jpg

f:id:ninoseki:20090208214100j:image


cvCompareHistには四つのメソッド(Correlation、Chi-square、Intersection、Bhattacharyya distance)がサポートされている。

  • Correlationを用いると
    • 結果が高いほうがよりマッチしている
    • 完璧なマッチだった場合は1
    • 完璧なミスマッチの場合は-1
  • Chi-squareを用いると
    • 結果が低いほうがよりマッチしている
    • 完璧なマッチだった場合は0
    • 完璧なミスマッチだった場合は際限のない値が得られる(ヒストグラムのサイズに依存する)
  • Intersectionを用いると
    • 結果が高いほうがよりマッチしている
    • ヒストグラムが1にノーマライズされている場合
      • 完璧なマッチだった場合は1
      • 完璧なミスマッチだった場合は0
  • Bhattacharyya distanceを用いると
    • 結果が低いほうがよりマッチしている
    • 完璧なマッチだった場合は0
    • 完璧なミスマッチだった場合は1

Learning OpenCVによると、速さを求める場合にはIntersection、正確さを求める場合にはBhattacharyya distanceかChi-squareを用いるのがいいとのこと。


ソースコード

#include <cv.h>
#include <highgui.h>
#include <stdio.h>

int main(void)
{
    IplImage *src1 = 0, *src2 = 0;
	IplImage *dst1[4] = {0, 0, 0, 0}, *dst2[4] = {0, 0, 0, 0};
	CvHistogram *hist1, *hist2;
	int sch1 = 0, sch2 = 0;
	int hist_size = 256;
	float range_0[] = { 0, 256 };
	float *ranges[] = { range_0 };

	src1 = cvLoadImage("myhand1.jpg", CV_LOAD_IMAGE_COLOR);
	src2 = cvLoadImage("myhand2.jpg", CV_LOAD_IMAGE_COLOR);
	if(src1 == 0 || src2 == 0){
		return -1;
	}

	sch1 = src1->nChannels;
	sch2 = src2->nChannels;
	if(sch1 != sch2){
		return -1;
	}

	for(int i=0;i<sch1;i++) {
		dst1[i] = cvCreateImage (cvSize (src1->width, src1->height), src1->depth, 1);
		dst2[i] = cvCreateImage (cvSize (src2->width, src2->height), src2->depth, 1);
	}

	//ヒストグラム構造体を確保
	hist1 = cvCreateHist (1, &hist_size, CV_HIST_ARRAY, ranges, 1);
	hist2 = cvCreateHist (1, &hist_size, CV_HIST_ARRAY, ranges, 1);

	//入力画像がマルチチャンネルの場合,画像をチャンネル毎に分割
	if (sch1 == 1) {
		cvCopy (src1, dst1[0], NULL);
		cvCopy (src2, dst2[0], NULL);
	}else{
		cvSplit (src1, dst1[0], dst1[1], dst1[2], dst1[3]);
		cvSplit (src2, dst2[0], dst2[1], dst2[2], dst2[3]);
	}
	//ヒストグラムの計算
	for(int i= 0;i<sch1;i++){
		cvCalcHist (&dst1[i], hist1, 0, NULL);
		cvCalcHist (&dst2[i], hist2, 0, NULL);
		cvNormalizeHist(hist1, 1.0);
		cvNormalizeHist(hist2, 1.0);
	}
	printf("ヒストグラムの比較\n");
	printf("Correlation(CV_COMP_CORREL) : %f\n",cvCompareHist( hist1, hist2, CV_COMP_CORREL));
	printf("Chi-square(CV_COMP_CHSQR) : %f\n",cvCompareHist( hist1, hist2, CV_COMP_CHISQR));
	printf("Intersection(CV_COMP_INTERSECT) : %f\n",cvCompareHist( hist1, hist2, CV_COMP_INTERSECT));
	printf("Bhattacharyya distance(CV_COMP_BHATTACHARYYA) : %f\n",cvCompareHist( hist1, hist2, CV_COMP_BHATTACHARYYA));

	return 0;

}

・実行結果

ヒストグラムの比較
Correlation(CV_COMP_CORREL) : 0.870168
Chi-square(CV_COMP_CHSQR) : 0.075862
Intersection(CV_COMP_INTERSECT) : 0.847536
Bhattacharyya distance(CV_COMP_BHATTACHARYYA) : 0.139961

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証

トラックバック - http://d.hatena.ne.jp/ninoseki/20090208/1234100058