参考:
《OpenCV3编程入门》
《学习OpenCV(中文版)》
#################################################################33
最近上课需要将颜色直方图的内容,所以就把直方图一些常用的知识点复习了一遍,包括灰度图,均衡化,对比等。
#include "hist.h" /** * @function : 显示灰度图和均衡化后的灰度图 * @param : img_address - const string 图片地址 */ void show_gray(const string img_address) { Mat img, dst; //加载源图像 img = imread(img_address, 1); if (img.empty()) { cout<<"读取图片错误\n"; return ; } //转为灰度图 cvtColor(img, img, COLOR_BGR2GRAY); //直方图均衡化 equalizeHist(img, dst); imshow("show", img); //显示结果 imshow("show_equalize", dst); waitKey(0); } /** * @function : 提取灰度颜色直方图并展示 * @param : color_address - string 图像地址 */ void show_gray_color_histogram(const string color_address) { //载入原图并显示 Mat srcImage = imread(color_address, 0); //imshow("原图", srcImage); if (!srcImage.data) { cout<<"fail to load image"<<endl; return ; } Mat dst; equalizeHist(srcImage, dst); imshow("均衡化", dst); //定义变量 MatND dstHist; int dims = 1; float hranges[] = {0,255}; const float *ranges[] = {hranges}; int size = 256; int channels = 0; //计算直方图 calcHist(&dst, 1, &channels, Mat(), dstHist, dims, &size, ranges); int scale = 1; Mat dstImage(size*scale, size, CV_8U, Scalar(0)); //获取最大值和最小值 double maxValue = 0; double minValue = 0; minMaxLoc(dstHist, &minValue, &maxValue, 0, 0); //绘制直方图 int hpt = saturate_cast<int>(0.9 * size); for (int i=0; i<256; i++) { float binValue = dstHist.at<float>(i); int realValue = saturate_cast<int>(binValue * hpt / maxValue); rectangle(dstImage, Point(i*scale, size-1), Point((i+1)*scale-1, size-realValue), Scalar(255)); } imshow("灰度直方图", dstImage); waitKey(0); } /** * @function : 绘制RGB颜色直方图 * @param : img_address - const string 图片地址 */ void show_RGB_histogram(const string img_address) { //载入图片 Mat srcImage; srcImage = imread(img_address); imshow("原图", srcImage); //参数准备 int bins = 256; int hist_size[] = {bins}; float range[] = {0, 256}; const float *ranges[] = {range}; MatND redHist, greenHist, blueHist; int channels_r[] = {0}; //进行直方图的计算(红色部分) calcHist(&srcImage, 1, channels_r, Mat(), redHist, 1, hist_size, ranges, true, false); //绿色分量计算 int channels_g[] = {1}; calcHist(&srcImage, 1, channels_g, Mat(), greenHist, 1, hist_size, ranges, true, false); //蓝色分量计算 int channels_b[] = {1}; calcHist(&srcImage, 1, channels_b, Mat(), blueHist, 1, hist_size, ranges, true, false); //绘制rgb颜色直方图 //参数准备 double maxValue_red, maxValue_green, maxValue_blue; minMaxLoc(redHist, 0, &maxValue_red, 0, 0); minMaxLoc(greenHist, 0, &maxValue_green, 0, 0); minMaxLoc(blueHist, 0, &maxValue_blue, 0, 0); int scale = 1; int histHeight = 256; Mat histImage = Mat::zeros(histHeight, bins*3, CV_8UC3); //开始绘制 for (int i=0; i<bins; i++) { //参数准备 float binValue_red = redHist.at<float>(i); float binValue_green = greenHist.at<float>(i); float binValue_blue = blueHist.at<float>(i); int intensity_red = cvRound(binValue_red * histHeight / maxValue_red); //计算绘制高度 int intensity_green = cvRound(binValue_green * histHeight / maxValue_green); //计算绘制高度 int intensity_blue = cvRound(binValue_blue * histHeight / maxValue_blue); //计算绘制高度 //绘制红色部分直方图 rectangle(histImage, Point(i*scale, histHeight-1), Point((i+1)*scale-1, histHeight-intensity_red), Scalar(0, 0, 255)); //绘制绿色部分直方图 rectangle(histImage, Point((i+bins)*scale, histHeight-1), Point((i+bins+1)*scale-1, histHeight-intensity_green), Scalar(0, 255, 0)); //绘制蓝色部分直方图 rectangle(histImage, Point((i+bins*2)*scale, histHeight-1), Point((i+bins*2+1)*scale-1, histHeight-intensity_blue), Scalar(255, 0, 0)); } //在窗口中显示 imshow("RGB", histImage); waitKey(0); } /** * @function : 直方图对比 * @param : srcImg_address - const string 原图地址 * @param : comp1_address - const string 对比图1地址 * @param : comp2_address - const string 对比图2地址 */ void compare_hist(const string srcImg_address, const string comp1_address, const string comp2_address) { //声明存储基准图像和另外两张对比图像的矩阵(RGB 和 HSV) Mat srcImage_base, hsvImage_base; Mat srcImage_test1, hsvImage_test1; Mat srcImage_test2, hsvImage_test2; Mat hsvImage_halfDown; //载入基准图像(srcImage_base)和两张测试图像srcImage_test1,srcImage_test2,并显示 srcImage_base = imread(srcImg_address, 1); srcImage_test1 = imread(comp1_address, 1); srcImage_test2 = imread(comp2_address, 1); //显示 imshow("基准图像", srcImage_base); imshow("测试图像1", srcImage_test1); imshow("测试图像2", srcImage_test2); //将图像由RGB色彩空间转换到HSV色彩空间 cvtColor(srcImage_base, hsvImage_base, COLOR_BGR2HSV); cvtColor(srcImage_test1, hsvImage_test1, COLOR_BGR2HSV); cvtColor(srcImage_test2, hsvImage_test2, COLOR_BGR2HSV); //创建包含基准图像下半身的半身图像(HSV格式) hsvImage_halfDown = hsvImage_base(Range(hsvImage_base.rows/2, hsvImage_base.rows-1), Range(0, hsvImage_base.cols-1)); //初始化计算直方图需要的实参 //对hue通道使用30个bin,对saturation通道使用32个bin int h_bins = 50; int s_bins = 60; int histSize[] = {h_bins, s_bins}; //hue的取值范围从0到256,saturation取值范围从0到180 float h_ranges[] = {0, 256}; float s_ranges[] = {0, 180}; const float* ranges[] = {h_ranges, s_ranges}; //使用第0和第1通道 int channels[] = {0, 1}; //创建存储直方图的MatND MatND baseHist; MatND halfDownHist; MatND testHist1; MatND testHist2; //计算基准图像,两张测试图像,半身基准图像的HSV直方图 calcHist(&hsvImage_base, 1, channels, Mat(), baseHist, 2, histSize, ranges, true, false); normalize(baseHist, baseHist, 0, 1, NORM_MINMAX, -1, Mat()); calcHist(&hsvImage_halfDown, 1, channels, Mat(), halfDownHist, 2, histSize, ranges, true, false); normalize(halfDownHist, halfDownHist, 0, 1, NORM_MINMAX, -1, Mat()); calcHist(&hsvImage_test1, 1, channels, Mat(), testHist1, 2, histSize, ranges, true, false); normalize(testHist1, testHist1, 0, 1, NORM_MINMAX, -1, Mat()); calcHist(&hsvImage_test2, 1, channels, Mat(), testHist2, 2, histSize, ranges, true, false); normalize(testHist2, testHist2, 0, 1, NORM_MINMAX, -1, Mat()); //按顺序使用4种对比标准将基准图像的直方图与其余各直方图进行对比 for (int i=0; i<4; i++) { //进行图像直方图的对比 int compare_method = i; double base_base = compareHist(baseHist, baseHist, compare_method); double base_half = compareHist(baseHist, halfDownHist, compare_method); double base_test1 = compareHist(baseHist, testHist1, compare_method); double base_test2 = compareHist(baseHist, testHist2, compare_method); //输出结果 cout<<"方法["<<i<<"]的匹配结果如下:"<<endl; cout<<"【基准图 - 基准图】:"<<base_base<<" 【基准图 - 半身图】:"<<base_half<<" 【基准图 - 测试图1】:"<<base_test1<<" 【基准图 - 测试图2】:"<<base_test2<<endl; } cout<<"endl..."<<endl; waitKey(0); }
将图像分成若干局域,比如上下左右四等分为4个区域,然后分别提取颜色直方图,计算相似度;
在上一步的基础上还可以增加权重值,对于比较重要的区域赋以高权重值;
还可以使用颜色直方图和其他特征向量进行联合对比,比如纹理特征,形状特征等。