相似图片搜索原理三(颜色直方图—c++实现)

图像的颜色直方图可以用于图像检索,适应有相同色彩,并且可以有平移、缩放、旋转不变性的图像检索,当然了这三大特点不如sift或者surf稳定性强,此外最大的局限就是如果形状内容一样,但色彩不一,结果是搜不到的。不过它在某些情况下达到较好的结果。

颜色直方图两种计算方式:

彩色图像的颜色直方图,这里可以有两种处理方式,得到的效果应该差不多。

首先第一种就是对像素的每个通道都进行划分,每个通道的最大像素值为255,可以等分8、16或者64等分,这样每个通道的范围就是0~15(以16等分为例,当然等分越小,像素值取的范围越大,越精确,但图像维数就越大,消耗时间复杂度大)。这样三通道得到图像维数就是16*16*16=4096维(从[0,0,0]一直到[15,15,15])。代码中我们使用了得到其下标操作为i+(j<<4)+(k<<8)就等于i+j*16+k*16*16。比如一个像素为[4,1,20],那么就会有hist[4+1*16+20*16*16]++;

第二种方法是单独计算每个通道像素值的个数,比如一个像素点值为[4,1,20],那么就有bhist[4] ++;ghist[1]++; rhist[20]++;这样就得到3个256维的一维向量,然后可以做叠加操作。

距离的度量

距离的度量通常有欧式距离、皮尔逊相关系数及余弦距离。但是这里百度百科上说在做直方图相似性度量时,巴氏距离效果最佳。我这里做了简单测试,发现欧式距离的确效果很差,这可能的原因比如当[5,5]与[1,1]应该相似的,但是欧式距离发现它们距离会很大。此外,这里余弦距离,测试效果也行,也是可以用的。

巴氏距离:又叫巴氏系数。用于测量两离散概率分布。它常在分类中测量类之间的可分离性。计算公式如下:

其中P, P’分别代表源与候选的图像直方图数据,对每个相同i的数据点乘积开平方以后相加得出的结果即为图像相似度值(巴氏系数因子值),范围为0到1之间。为什么是到1之间,这是数学的问题,就不追究了。当p(i)==p’(i)
for all i时,结果就会为1。 p(i)与p’(i)都在0~1之间。p(i)表示为该像素值出现的次数和除以总的像素个数,就是一个概率,代码中可以看出。

代码:

计算方式一:

(1)得到颜色直方图:

// 三维直方图 方式一
void getHistogram(Mat &image, int *histValue){
	MatND hist;       // 在cv中用CvHistogram *hist = cvCreateHist
	int dims = 3;

	float r_hranges[] = {0, 255};
	float g_hranges[] = {0, 255};
	float b_hranges[] = {0, 255};
	const float *ranges[] = {r_hranges, g_hranges, b_hranges};   // 这里需要为const类型
	int size[3] = {16, 16, 16};
	int channels[] ={0, 1, 2};   //代表 r g通道 2代表b通道
	// 计算图像的直方图
	calcHist(&image, 1, channels, Mat(), hist, dims, size, ranges);    // cv 中是cvCalcHist

	for(int i = 0; i < 16; i++)
	{
		for(int j = 0; j < 16; j++)
		{
			for(int k = 0; k < 16; k++)
			{
				float value = hist.at<float>(i,j,k);           //   注意直方图的值是float类型    cv中用cvQueryHistValue_1D
				int realValue = saturate_cast<int>(value);
				int index = i + (j<<4) + (k<<8);
				histValue[index] = realValue;

			}
		}
	}

}

(2)三种距离度量的代码

// 欧式距离
float getDistance(int *sur, int *dst){
	float sum = 0;
	for(int i = 0; i < MaxHistValue; i++){
		sum += pow(sur[i]-dst[i]+0.0,2);
	}
	return sqrt(sum);
}

// 余弦距离
float getCosDistance(int *sur, int *dst){
	float surSum = 0, dstSum = 0, sum = 0;
	for(int i = 0; i < MaxHistValue; i++){
		surSum += pow(sur[i]+0.0,2);
		dstSum += pow(dst[i]+0.0,2);
		sum += sur[i]*dst[i];
	}
	surSum = sqrt(surSum);
	dstSum = sqrt(dstSum);
	return sum/(surSum*dstSum);
}

// 巴氏距离,  需要除以总元素个个数
// 注意:在颜色直方图的相似度比较中,巴氏距离效果最好

float getPSDistance(int *sur, int*dst, const float sTotal, const float dTotal){
	float sum = 0;
	for(int i = 0; i < MaxHistValue; i++){
		sum += sqrt((sur[i]/sTotal)*(dst[i]/dTotal));
	}
	return sum;
}

测试图片:

余弦结果:

巴氏距离结果:

其中【i-j】, i代表personi, j代表personi与person的汉明距离。并由结果可见phash对于图片的旋转肯定是无能为力的。

由结果可见,针对person6,很相似,但余弦结果不好,而巴氏距离很好,此外巴氏距离对于原图不是1,是因为计算过程中的精度丢失造成的。

计算方式二:

(1)得到颜色直方图

// 三维直方图 方式二
void getHistogram2(Mat &image, int **HistValue){
	for(int i = 0; i < image.rows; i++){
		for(int j = 0; j < image.cols; j++){
			HistValue[0][image.at<Vec3b>(i,j)[0]] ++;
			HistValue[1][image.at<Vec3b>(i,j)[1]] ++;
			HistValue[2][image.at<Vec3b>(i,j)[2]] ++;
		}
	}

}

(2)三种距离度量的代码

// 欧式距离
float getDistance(int **sur, int **dst){
	float sum = 0;
	for(int i = 0; i < 3; i++){
		for(int j = 0; j < 256; j++){
			sum += pow(sur[i][j]-dst[i][j]+0.0,2);
		}

	}
	return sqrt(sum);
}

// 余弦距离
float getCosDistance(int **sur, int **dst){
	float surSum = 0, dstSum = 0, sum = 0;
	for(int i = 0; i < 3; i++){
		for(int j = 0; j < 256; j++){
			surSum += pow(sur[i][j]+0.0,2);
			dstSum += pow(dst[i][j]+0.0,2);
			sum += sur[i][j]*dst[i][j];
		}

	}
	surSum = sqrt(surSum);
	dstSum = sqrt(dstSum);
	return sum/(surSum*dstSum);
}

// 巴氏距离,  需要除以总元素个个数
// 注意:在颜色直方图的相似度比较中,巴氏距离效果最好

float getPSDistance(int **sur, int**dst, const float sTotal, const float dTotal){
	float sum = 0;
	for(int i = 0; i < 3; i++){
		for(int j = 0; j < 256; j++){
			sum += sqrt((sur[i][j]/sTotal)*(dst[i][j]/dTotal));
		}
	}
	return sum/3;    // 因为这里有三个
}

余弦结果:

巴氏距离结果:

其中【i-j】, i代表personi, j代表personi与person的汉明距离。并由结果可见phash对于图片的旋转肯定是无能为力的。

完整源码(均匀hash、感知hash、颜色直方图)下载地址:

http://download.csdn.net/detail/lu597203933/8710535

参考文献:

1:http://blog.csdn.net/jia20003/article/details/7771651

2http://blog.csdn.net/luoweifu/article/details/8690835

3http://baike.baidu.com/view/10343198.htm巴氏距离

时间: 2024-11-03 05:28:48

相似图片搜索原理三(颜色直方图—c++实现)的相关文章

相似图片搜索原理二(phash—c++实现)

前段时间介绍过相似图片搜索原理一(ahash) http://blog.csdn.net/lu597203933/article/details/45101859,它是基于内容检索最简单的一种:这里介绍它的增强版本感知哈希算法(perceptual hash, phash).它主要也是用缩略图搜原图并能达到较好点的效果. 理论部分: 理论部分主要包括以下几个步骤: <1> 图像缩放-将图像缩放到32*32大小 <2>灰度化-对32*32大小的图像进行灰度化 <3>离散余

Google 以图搜图 - 相似图片搜索原理 - Java实现

前阵子在阮一峰的博客上看到了这篇<相似图片搜索原理>博客,就有一种冲动要将这些原理实现出来了. Google "相似图片搜索":你可以用一张图片,搜索互联网上所有与它相似的图片. 打开Google图片搜索页面: 点击使用上传一张angelababy原图: 点击搜索后,Google将会找出与之相似的图片,图片相似度越高就越排在前面.如: 这种技术的原理是什么?计算机怎么知道两张图片相似呢? 根据Neal Krawetz博士的解释,实现相似图片搜素的关键技术叫做"感知

相似图片搜索原理一(ahash—c++实现)

ahash,全称叫做average hash,应该是phash(perceptual hash, 感知哈希)算法的一种.是基于图像内容搜索最简单的一种(search image by image),因此也有很多的局限性.主要用于由图像的缩略图搜原图,对于图像的旋转.平移.对比度和微变形等都无能为力,所以很局限.此次讲解主要分为两个部分,理论部分主要参考是网上的资料,最核心的应该是自己的c++代码实现. 理论部分: 理论部分主要包括以下几个步骤: <1> 图像缩放-将图像缩放到8*8大小 <

相似图片搜索的三种哈希算法

想必大家都用google或baidu的识图功能,上面就是我搜索冠希哥一幅图片的结果,达到图片比较目的且利用信息指纹比较有三种算法,这些算法都很易懂,下面分别介绍一下: 一.平均哈希算法(aHash) 此算法是基于比较灰度图每个像素与平均值来实现的,最适用于缩略图,放大图搜索. 步骤: 1.缩放图片:为了保留结构去掉细节,去除大小.横纵比的差异,把图片统一缩放到8*8,共64个像素的图片. 2.转化为灰度图:把缩放后的图片转化为256阶的灰度图. 附上灰度图相关算法(R = red, G = gr

图片搜索的原理

http://www.zhihu.com/question/19726630 Google 图片搜索的原理是什么? 1 条评论 分享 按投票排序按时间排序 18 个回答 389赞同反对,不会显示你的姓名 知乎用户,安全行业 XsXs.知乎用户.知乎用户 等人赞同 针对这个问题,请教了算法组的同事,他分享了基本的思路: 对于这种图像搜索的算法,一般是三个步骤: 1. 将目标图片进行特征提取,描述图像的算法很多,用的比较多的是:SIFT描述子,指纹算法函数,bundling features算法,h

相似图片搜索的原理

http://www.ruanyifeng.com/blog/2011/07/principle_of_similar_image_search.html http://www.ruanyifeng.com/blog/2013/03/similar_image_search_part_ii.html 相似图片搜索的原理 作者: 阮一峰 日期: 2011年7月21日 上个月,Google把"相似图片搜索"正式放上了首页. 你可以用一张图片,搜索互联网上所有与它相似的图片.点击搜索框中照相

相似图片搜索的原理(转)

http://www.ruanyifeng.com/blog/2011/07/principle_of_similar_image_search.html 作者: 阮一峰 日期: 2011年7月21日 上个月,Google把"相似图片搜索"正式放上了首页. 你可以用一张图片,搜索互联网上所有与它相似的图片.点击搜索框中照相机的图标. 一个对话框会出现. 你输入网片的网址,或者直接上传图片,Google就会找出与其相似的图片.下面这张图片是美国女演员Alyson Hannigan. 上传

相似图片搜索的原理(二)

二年前,我写了<相似图片搜索的原理>,介绍了一种最简单的实现方法. 昨天,我在isnowfy的网站看到,还有其他两种方法也很简单,这里做一些笔记. 一.颜色分布法 每张图片都可以生成颜色分布的直方图(color histogram).如果两张图片的直方图很接近,就可以认为它们很相似. 任何一种颜色都是由红绿蓝三原色(RGB)构成的,所以上图共有4张直方图(三原色直方图 + 最后合成的直方图). 如果每种原色都可以取256个值,那么整个颜色空间共有1600万种颜色(256的三次方).针对这160

Java爬虫搜索原理实现

permike 原文 Java爬虫搜索原理实现 没事做,又研究了一下爬虫搜索,两三天时间总算是把原理闹的差不多了,基本实现了爬虫搜索的原理,本次实现还是俩程序,分别是按广度优先和深度优先完成的,广度优先没啥问题,深度优先请慎用,有极大的概率会造成死循环情况,下面深度优先的测试网站就造成了死循环....好吧,我承认是我人品不太好...下面有请代码君出场~~~~~~~~~~~~~~~ 1.广度优先 [java] view plaincopy /** * 完成广度优先搜索 */ package imp