OpenCV基于直方图特征的图像搜索
来源:互联网 发布:拼音打字软件下载 编辑:程序博客网 时间:2024/05/29 16:02
转自: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%, 一般相似
程序直方图计算源代码如下:
- <span style="white-space: pre;"> </span>publicvoid setGreenBinCount(int greenBinCount) {
- <span style="white-space: pre;"> </span>this.greenBins = greenBinCount;
- <span style="white-space: pre;"> </span>}
- <span style="white-space: pre;"> </span>publicvoid setBlueBinCount(int blueBinCount) {
- <span style="white-space: pre;"> </span>this.blueBins = blueBinCount;
- <span style="white-space: pre;"> </span>}
- <span style="white-space: pre;"> </span>publicfloat[] filter(BufferedImage src, BufferedImage dest) {
- <span style="white-space: pre;"> </span>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++) {
- <span style="white-space: pre;"> </span>int ta = 0, tr = 0, tg = 0, tb = 0;
- <span style="white-space: pre;"> </span>for(int col=0; col<width; col++) {
- <span style="white-space: pre;"> </span>index = row * width + col;
- <span style="white-space: pre;"> </span>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;
- <span style="white-space: pre;"> </span>}
- }
- // start to normalize the histogram data
- for (int i = 0; i < histogramData.length; i++)
- {
- <span style="white-space: pre;"> </span>histogramData[i] = histogramData[i] / total;
- }
- return histogramData;
- <span style="white-space: pre;"> </span>}
- 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;
- }
- /**
- * 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;
- }
- OpenCV基于直方图特征的图像搜索
- OpenCV基于直方图特征的图像搜索
- 基于直方图特征的图像搜索
- 基于直方图特征的图像搜索
- 图像相似度(测试)--基于直方图特征的图像搜索
- 基于直方图的图像检索OpenCV实现
- OpenCV-基于特征点的图像匹配
- 基于opencv和c++的图像处理:直方图均衡化
- 基于opencv和c++的图像处理:直方图匹配
- 基于opencv和c++的图像处理:直方图均衡化
- 基于opencv和c++的图像处理:直方图匹配
- 【图像处理】基于OpenCV底层实现的直方图匹配
- OpenCV-统计图像的直方图,绘制直方图
- opencv基于直方图实现图像检索匹配
- 【OpenCV】绘制图像的直方图
- opencv:基于不变矩方法的图像特征提取
- 基于颜色直方图的搜索
- 我的OpenCV学习笔记(14):用直方图对比完成基于内容的图像检索
- android 自动化测试monkey
- DevExpress添加右键菜单
- 苹果的用户体验只是一种斯德哥尔摩综合症 —— 写给鼓吹用户体验的产品经理们
- WMSYS.WM_CONCAT函数返回结果为CLOB引起视图无法创建
- [Android] 细节问题
- OpenCV基于直方图特征的图像搜索
- 【观点】我跳槽是因为他们的显示器更大
- 学习CVS( 2.0.2.4)系列----(二)同步、提交、添加、删除项目
- qt 如何让窗口置顶
- 火星坐标系 (GCJ-02) 与百度坐标系 (BD-09) 的转换算法
- 发布与订阅---来自维基百科
- linux上构建freeradius,网上搜索的
- (编译内核)Vmware编译内核
- 用ISO文件安装Xen虚拟机