最近在研究颜色直方图匹配算法,提取一张图的色彩特征有很多种方法,最常用的一种特征是提取它的颜色直方图分布特征。网上搜了很多文章,颜色直方图匹配算法主要有两类,一类基于RGB色彩空间的直方图匹配,另一类是基于HSV色彩空间的直方图匹配。其中基于RGB色彩空间的直方图匹配,网上大多是将图像分成RGB三通道,计算每一个通道的直方图,然后求平均,最后计算相似度;我觉得这种方法会丢失很多颜色特征,很不靠谱,还不如直接转成灰度图像,求灰度直方图并计算相似度。在维基百科上看到一种基于区间统计的颜色直方图方法,感觉比较靠谱,它是将R,G,B各分量的颜色信息划分为N 区间。比如;将图像每个像素的R、G和B的值都分成4个bins(256除以64),构建RGB(4X4X4 )颜色模型,然后再统计各个区间内的像素数,如下图:

C/C++代码实现方法如下:

统计颜色直方图方法一:采用三维数组a[][][]来遍历Mat每一个像素。

vector<float> getHist1(Mat testImg)//RGB色彩空间的(4,4,4)模型。
{const int div = 64;const int bin_num = 256 / div;int length = bin_num*bin_num*bin_num;Vec3i pix;vector<float> b;float a[bin_num*bin_num*bin_num] = { 0 };float d[bin_num][bin_num][bin_num] = { 0 };for (int r = 0; r < testImg.rows; r++){for (int c = 0; c < testImg.cols; c++){pix = testImg.at<Vec3b>(r, c);pix.val[0] = pix.val[0] / div;pix.val[1] = pix.val[1] / div;pix.val[2] = pix.val[2] / div;//  testImg.at<Vec3b>(r, c) = pix;d[pix.val[0]][pix.val[1]][pix.val[2]]++;}}float sum = 0;for (int i = 0; i < bin_num; i++)for (int j = 0; j < bin_num; j++)for (int k = 0; k < bin_num; k++){a[i*bin_num*bin_num + j*bin_num + k] = d[i][j][k];sum += d[i][j][k];cout << d[i][j][k] << " ";}for (int i = 0; i < length; i++)//归一化{a[i] = a[i] / sum;b.push_back(a[i]);}return b;
}

统计颜色直方图方法二:采用一维数组a[]来遍历Mat每一个像素。

vector<float> getHist(Mat testImg)//RGB色彩空间的(8,8,8)模型。
{//CV_8UC3---Vec3b  //相应的CV_8SC3---Vec3s  //相应的CV_16UC3---Vec3w  const int div = 32;const int bin_num = 256 / div;const int length = bin_num*bin_num*bin_num;Vec3i pix;vector<float> b;int ord = 0;float a[length] = { 0 };//Mat test = Mat::zeros(64, 1, CV_8UC1);//Mat mat = cvCreateMat(64, 1, CV_32FC1);for (int r = 0; r < testImg.rows; r++){for (int c = 0; c < testImg.cols; c++){pix = testImg.at<Vec3b>(r, c);pix.val[0] = pix.val[0] / div;pix.val[1] = pix.val[1] / div;pix.val[2] = pix.val[2] / div;// testImg.at<Vec3b>(r, c) = pix;ord = pix.val[0] * bin_num * bin_num + pix.val[1] * bin_num + pix.val[2];a[ord] += 1;}}float sum = 0;for (int i = 0; i < length; i++){sum += a[i];//cout << a[i] << " ";}for (int i = 0; i < length; i++)//归一化{a[i] = a[i] / sum;//cout << a[i] << " ";b.push_back(a[i]);}return b;
}

由于以上方法通过testImg.at<Vec3b>(r, c)的方法遍历每个像素,效率低下,对实时性要求较高的场合,不建议采用。
有一种更高效的方法就是采用指针来遍历,方法如下:

vector<float> getHist2(Mat &image)//RGB色彩空间的(4,4,4)模型。
{const int div = 64;const int bin_num = 256 / div;int nr = image.rows; // number of rowsint nc = image.cols; // number of columnsif (image.isContinuous())  {// then no padded pixels  nc = nc*nr;nr = 1;  // it is now a 1D array  }int n = static_cast<int>(log(static_cast<double>(div)) / log(2.0));// mask used to round the pixel valueuchar mask = 0xFF << n; // e.g. for div=16, mask= 0xF0int b, g, r;vector<float> bin_hist;int ord = 0;float a[bin_num*bin_num*bin_num] = { 0 };for (int j = 0; j < nr; j++) {const uchar* idata = image.ptr<uchar>(j);for (int i = 0; i < nc; i++) {b = ((*idata++)&mask) / div;g = ((*idata++)&mask) / div;r = ((*idata++)&mask) / div;ord = b * bin_num * bin_num + g * bin_num + r;a[ord] += 1;} // end of row      }float sum = 0;
//  cout << "a[i]2:" << endl;for (int i = 0; i < div; i++){sum += a[i];
//      cout << a[i] << " ";}for (int i = 0; i < div; i++)//归一化{a[i] = a[i] / sum;bin_hist.push_back(a[i]);}return bin_hist;}

颜色直方图匹配方法实现:

double GetCompareHist(Mat testImg1, Mat testImg2)//基于RGB色彩空间的(4,4,4)模型直方图匹配。
{double start, end, cost;start = clock();vector<float> b1;vector<float> b2;//b1 = getHist1(testImg1);//采用自带函数(Img.at<Vec3b>(r, c))取像素,时间为:78ms//b2 = getHist1(testImg2);b1 = getHist2(testImg1);//利用指针取像素,时间为:10msb2 = getHist2(testImg2);double base_test = compareHist(b1, b2, CV_COMP_CORREL);//   double base_test = compareHist(b1, b2, CV_COMP_BHATTACHARYYA);//CV_COMP_BHATTACHARYYAend = clock();cost = end - start;printf("代码执行时间为:%f\n", cost);return base_test;
}

另一类是基于HSV色彩空间的直方图匹配实现方法:

double GetCompareHist1(Mat src_base, Mat src_test1)//基于HSV色彩空间的直方图匹配。
{/// 转换到 HSVMat  hsv_base;Mat  hsv_test1;cvtColor(src_base, hsv_base, CV_BGR2HSV);cvtColor(src_test1, hsv_test1, CV_BGR2HSV);/// 对hue通道使用30个bin,对saturatoin通道使用32个binint h_bins = 50; int s_bins = 60;int histSize[] = { h_bins, s_bins };// hue的取值范围从0到256, saturation取值范围从0到180float h_ranges[] = { 0, 256 };float s_ranges[] = { 0, 180 };const float* ranges[] = { h_ranges, s_ranges };// 使用第0和第1通道int channels[] = { 0, 1 };/// 直方图MatND hist_base;MatND hist_half_down;MatND hist_test1;/// 计算HSV图像的直方图calcHist(&hsv_base, 1, channels, Mat(), hist_base, 2, histSize, ranges, true, false);normalize(hist_base, hist_base, 0, 1, NORM_MINMAX, -1, Mat());calcHist(&hsv_test1, 1, channels, Mat(), hist_test1, 2, histSize, ranges, true, false);normalize(hist_test1, hist_test1, 0, 1, NORM_MINMAX, -1, Mat());int compare_method = CV_COMP_CORREL;double base_test = compareHist(hist_base, hist_test1, compare_method);return base_test;
}

未完待续。。。。。。

颜色直方图匹配(一)相关推荐

  1. python实现-颜色直方图pHash图像检索分类-图像检索引擎

    这是我们课程作业的一部分,我已经把所有的代码都上传到了我的github,基于高效检索算法可以构建图像搜索引擎,关键在于找到合适的算法 https://github.com/miaogen123/ima ...

  2. 基于HOG-LBP特征融合的头肩检测研究

    from: http://www.hqew.com/tech/fangan/1721922.html 摘  要: 提出了一种基于HOG-LBP特征融合的人体头肩检测方法,其要点是将人体头肩图像等分为多 ...

  3. 数字图像处理与Python实现笔记之图像特征提取

    数字图像处理与Python实现笔记 摘要 绪论 1 数字图像处理基础知识 2 彩色图像处理初步 3 空间滤波 4 频域滤波 5 图像特征提取 5.1 图像颜色特征提取 5.1.1 颜色直方图 1 一般 ...

  4. 编译原理语义分析代码_Pix2Pix原理分析与代码解读

    原理分析: 图像.视觉中很多问题都涉及到将一副图像转换为另一幅图像(Image-to-Image Translation Problem),这些问题通常都使用特定的方法来解决,不存在一个通用的方法.但 ...

  5. Elliptical Head Tracking Using Intensity Gradients and Color Histograms(1998)

    摘要翻译 本文提出了人头追踪的算法.人物头部映射到图像平面的区域用椭圆形模拟,结合椭圆形的边缘梯度模型和椭圆形内部的颜色直方图模型实时的更新椭圆形的位置和大小.由于这两个模型是正交的,成互补关系.追踪 ...

  6. 《Image-to-Image Translation with Conditional Adversarial Networks》文章翻译

    图1 在图像处理,计算机图形.视觉中,将一幅图输入转换到另一张图输出的过程中存在很多问题.即使这里面的一些设置总是相同的,都是图像像素的映射,但这些问题通常使用特殊应用的算法.CAN似乎能很好的解决各 ...

  7. CVPR2017/图像翻译:Image-to-Image Translation with Conditional Adversarial Networks基于条件对抗网络的图像到图像的翻译

    CVPR2017/图像翻译:Image-to-Image Translation with Conditional Adversarial Networks基于条件对抗网络的图像到图像的翻译 0.摘要 ...

  8. 【翻译】Controlling Perceptual Factors in Neural Style Transfer

    文章目录 摘 要 1.介绍 2.相关工作 3.神经风格迁移 4.空间控制 4.1. 引导性 Gram 矩阵 4.2. 引导性总和 5.颜色控制 5.1. 仅有亮度的转移 5.2. 颜色直方图匹配 5. ...

  9. 读论文- pix2pix

    Image-to-Image Translation with Conditional Adversarial Networks(pix2pix) 代码地址:https://github.com/ph ...

  10. [论文笔记]:Image-to-Image Translation with Conditional Adversarial Networks

    Image-to-Image Translation with Conditional Adversarial Networks 论文翻译 摘要 1. 介绍 2. 相关工作 3. 方法 3.1 评估 ...

最新文章

  1. jquery实现单行滚动效果
  2. ntu 课程笔记 :MAS714(7) 最短路径和优先队列
  3. softened softmax vs softmax
  4. SpringMVC中JSP取不到ModelAndView的数据原因
  5. 操作篇 ospf认识和应用
  6. 传惠普下周公布webOS平台最终命运
  7. Bug面前程序员的30种反应,戳中你了没
  8. linux内核开发基础(linux内核源码、树莓派源码编译、SD卡挂载)
  9. sizeof和strlen的区别(其中涉及NUL的讲解)
  10. java 工作6年 面试_为什么不想搞Java了,6年经验去面试5分钟结束,现在Java面试为何这么难...
  11. 【jvm】jvm优化 jvm linux 大页
  12. BestCoder4 1002 Miaomiao's Geometry (hdu 4932) 解题报告
  13. 第八章 了解tempdb数据库
  14. 区块链优秀gitbook资料
  15. Mac电脑的12个神奇隐藏功能
  16. java 创建消息队列_java - 在Java中动态创建异步消息队列 - 堆栈内存溢出
  17. Pandownload百度网盘不限速下载器PC版|Android版
  18. web小说目录倒序php实现,php实现WEB在线文件管理器
  19. MT【325】垂心的向量形式
  20. 论文笔记 -- Communication Lower Bound in Convolution Accelerators 卷积加速器中的通信下界

热门文章

  1. [exgcd] Jzoj P5855 吃蛋糕
  2. chd6.0.1 kerberos安装碰到问题:
  3. PHP开发安全之近墨者浅谈(转)
  4. OWIN与Katana
  5. 离职原因该怎么回答?
  6. 使用jq来封装一个瀑布流插件
  7. 计算机视觉三大国际会议ICCV、ECCV、CVPR
  8. instagram动态网页图片内容爬取(一)
  9. git提交错分支怎么办
  10. 30天自制操作系统——第一天到第二天