当前位置: 首页 > news >正文

opencv再学习之路(五)---灰度直方图显示

1.calcHist() 函数的理解  

  函数原型: void calcHist(const Mat* arrays, int narrays, const int* channels, InputArray mask, OutputArray hist, int dims, const int* histSize, const float** ranges, bool uniform=true, bool accumulate= false );

  参数解释:

    arrays  输入图像的指针,可以是多幅图像,所有的图像都必须有相同的深度( CV_8U or CV_32F),同时一幅图像可以有多个 channels

    narrays   输入图像的个数

    channels   计算直方图的 channels 的数组,当输入图像为多通道图像时, channels[0] = {0}, 表示的是取其第一个通道, channels[0] = {1}表示取其第二个通道,以此类推, channels[2] = {1, 2}表示的是取其第2个和第3个通道的图像                                    进行直方图统计

    mask          掩码,如果 mask 不为空,那么它必须是一个8位(CV_8U)的数组,并且它的大小和 arrays[i] 的大小相同,值为1的点将用来计算直方图

    hist            计算出来的直方图

    dims          需要统计的特征的数目,计算出来的直方图的维数,直方图的维数就是图像的通道数,每一维的长度是灰度级数,一维直方图就是灰度图的直方图,直方图的尺寸是 256; 高维直方图可以理解为图像在每个维度上灰度级分布的直方图,常见的是二维                                    直方图,如红-蓝直方图的两个分量分别表示红光图像的灰度值和蓝光图像的灰度值的函数,其图像坐标(Dr,Db)处对应在红光图像中具有灰度级 Dr 同时在蓝光图像中具有灰度级 Db 的像素个数。

    histSize     在每一维上直方图的个数,把直方图看作一个一个的竖条的话,就是每一维竖条的个数

         ranges       用来统计的灰度值的范围  

2. 例程

绘制 二维 H-S 直方图

#include "stdafx.h"
#include "highgui/highgui.hpp"    
#include "opencv2/nonfree/nonfree.hpp"    
#include "opencv2/legacy/legacy.hpp"   
#include <iostream>  

using namespace cv;
using namespace std;

int main()
{
    // 载入原图 转化为 HSV 模型
    Mat srcImage, hsvImage;
    srcImage = imread("01.jpg");
    cvtColor(srcImage, hsvImage, CV_BGR2HSV);

    // 参数准备
    // 将色调量化为 30 个等级,将饱和度量化为 32 个等级
    int hueBinNum = 30;        //色调直方图直条数量
    int saturationBinNum = 32;        //饱和度的直方图直条数量
    int histSize[] = { hueBinNum, saturationBinNum};
    // 定义色调的变换范围为 0 到 179
    float hueRanges[] = {0, 179};
    // 定义饱和度的变化范围为 0 (黑、白、灰) 到 255(纯光谱颜色)
    float saturationRanges[] = {0, 256};
    const float* Ranges[] = {hueRanges, saturationRanges};
    MatND dstHist;
    // 参数准备, calcHist 函数中将计算第 0 通道和第 1 通道的直方图
    int channels[] = {0, 1};

    // 正式调用 calcHist, 进行直方图的计算
    calcHist( &hsvImage, 1, channels, Mat(), dstHist, 2, histSize, Ranges, true, false);

    // 为绘制直方图准备参数
    double maxValue = 0;        //    最大值
    minMaxLoc(dstHist, 0, &maxValue, 0, 0);        // 找出全局最小值
    int scale = 10;
    Mat histImg = Mat::zeros(saturationBinNum * scale, hueBinNum * scale, CV_8UC3);

    // 双层循环,进行直方图绘制
    for (int hue = 0; hue < hueBinNum; hue++)
    {
        for (int saturation  = 0; saturation  < saturationBinNum; saturation ++)
        {
            float binValue = dstHist.at<float>(hue, saturation);        // 直方图直条的值
            int intensity = cvRound(binValue * 255 / maxValue);        // 强度

            // 正式进行绘制
            rectangle(histImg, Point(hue * scale, saturation * scale), Point((hue + 1)*scale-1, (saturation + 1)*scale-1), Scalar(intensity), CV_FILLED);
        }
    }

    // 显式效果图
    namedWindow("H-S直方图", WINDOW_NORMAL);
    imshow("素材图", srcImage);
    imshow("H-S直方图", histImg);
    
    waitKey(0);
    return 0;
}

绘制 RGB 三色直方图

#include "stdafx.h"
#include "highgui/highgui.hpp"    
#include "opencv2/nonfree/nonfree.hpp"    
#include "opencv2/legacy/legacy.hpp"   
#include <iostream>  

using namespace cv;
using namespace std;

int main()
{
    // 载入原图并显示
    Mat srcImage;
    srcImage = imread("01.jpg");
    imshow("素材图", srcImage);

    // 参数准备
    int bins = 256;
    int hist_size[] = {bins};
    float range[] = {0, 255};
    const float* ranges[] = {range};
    MatND blueHist, greenHist, redHist;

    // 进行蓝色分量直方图计算
    int channel_b[] = {0};
    calcHist(&srcImage, 1, channel_b, Mat(), blueHist, 1, hist_size, ranges, true, false);

    // 进行绿色分量直方图计算
    int channel_g[] = {1};
    calcHist(&srcImage, 1, channel_g, Mat(), greenHist, 1, hist_size, ranges, true, false);

    // 进行红色分量直方图计算
    int channel_r[] = {2};
    calcHist(&srcImage, 1, channel_r, Mat(), redHist, 1, hist_size, ranges, true, false);

    // 绘制三色直方图
    // 准备参数
    double maxValue_r = 0;
    double maxValue_g = 0;
    double maxValue_b = 0;
    minMaxLoc( blueHist, 0, &maxValue_b, 0, 0);
    minMaxLoc( greenHist, 0, &maxValue_g, 0,0);
    minMaxLoc( redHist, 0, &maxValue_r, 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_blue = blueHist.at<float>(i);
        float binValue_green = greenHist.at<float>(i);
        float binValue_red = redHist.at<float>(i);

        int intensity_blue = cvRound(binValue_blue * 255 / maxValue_b);
        int intensity_green = cvRound(binValue_green * 255  / maxValue_g);
        int intensity_red = cvRound(binValue_red * 255 / maxValue_r);

        // 绘制蓝色分量直方图
        rectangle( histImage,Point(i * scale, histHeight-1), Point((i+1)*scale, histHeight-intensity_blue), Scalar(255, 0 ,0), CV_FILLED);
        rectangle( histImage,Point(i*scale+bins, histHeight-1), Point((i+1)*scale+bins, histHeight-intensity_green), Scalar(0, 255 ,0), CV_FILLED);
        rectangle( histImage,Point(i*scale+2*bins, histHeight-1), Point((i+1)*scale+2*bins, histHeight-intensity_red), Scalar(0, 0 ,255), CV_FILLED);
        
    }
    // 显示直方图
    namedWindow("BGR直方图", WINDOW_NORMAL);
    imshow("BGR直方图", histImage);
    waitKey(0);
    return 0;

}

 直方图对比

#include "stdafx.h"
#include "highgui/highgui.hpp"    
#include "opencv2/nonfree/nonfree.hpp"    
#include "opencv2/legacy/legacy.hpp"   
#include <iostream>  

using namespace cv;
using namespace std;

int main()
{
    // 定义储存基准图像和另外两张对比图像的矩阵(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("01.jpg");
    srcImage_test1 = imread("02.jpg");
    srcImage_test2 = imread("03.jpg");
    // 显示载入的3张图片
    imshow("基准图像",srcImage_base);
    imshow("测试图像1",srcImage_test1);
    imshow("测试图像2",srcImage_test2);

    // 创建包含基准图像下半部的半身图像(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 hist_size[] = { h_bins, s_bins};
    // hue 的取值范围从 0 到 255, saturation 取值范围从 0 到 180
    float h_ranges[] = {0, 255};
    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, hist_size, ranges, true, false);
    normalize( baseHist, baseHist, 0, 1, NORM_MINMAX, -1, Mat());

    calcHist( &hsvImage_halfDown, 1, channels, Mat(), halfDownHist, 2, hist_size, ranges, true, false);
    normalize( halfDownHist, halfDownHist, 0, 1, NORM_MINMAX, -1, Mat());

    calcHist( &hsvImage_test1, 1,channels, Mat(), testHist1, 2, hist_size, ranges, true, false);
    normalize( testHist1, testHist1, 0, 1, NORM_MINMAX, -1, Mat());

    calcHist( &hsvImage_test2, 1, channels, Mat(), testHist2, 2, hist_size,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);

        // 输出结果
        printf("方法 【%d】的匹配结果如下: \n\n 【基准图 - 基准图】: %f, 【基准图 - 半身图】: %f, 【基准图 - 侧视图】: %f, 【基准图 - 侧视图2】: %f\n\n",i, base_base, base_half, base_test1, base_test2);
    }
    printf("检测结束");

    waitKey(0);
    return 0;

}

 

转载于:https://www.cnblogs.com/zhp218/p/8626557.html

相关文章:

  • 在windows2003上部署MVC4.0需要具备的环境
  • 可能是历史上最全的CC0版权可以免费商用的图片网站
  • ContentProvider介绍
  • 10.19 iptables规则备份和恢复10.20 firewalld的9个zone 10.21 firewalld关于zone的操作 10.22 firewalld关于service的操作...
  • C# 屏幕监控 自动截屏程序 主窗体隐藏,仅在进程中显示
  • 手机加载优化 - 2x、3x图
  • 清明小感
  • [win7-oracle处理方法]--java.lang.Exception: Exception in sending Request :: null(转)
  • 0323-方法(函数)
  • 把每天当成人生第一天来过,把每一天当成人生最后一天来过
  • 第六届蓝桥杯java b组第五题
  • 在指定宽度和高度范围内最大化缩放图片
  • 戴尔大中华区解决方案顾问鲍荣钦:技术驱动,数据改变物流
  • HDU 2844 Coins
  • 上海商业发展研究院刘斌:变革下的供应链发展趋势
  • express.js的介绍及使用
  • Git同步原始仓库到Fork仓库中
  • Java 23种设计模式 之单例模式 7种实现方式
  • JAVA_NIO系列——Channel和Buffer详解
  • JavaScript 基础知识 - 入门篇(一)
  • Javascript弹出层-初探
  • leetcode98. Validate Binary Search Tree
  • linux安装openssl、swoole等扩展的具体步骤
  • Webpack4 学习笔记 - 01:webpack的安装和简单配置
  • 短视频宝贝=慢?阿里巴巴工程师这样秒开短视频
  • 翻译--Thinking in React
  • 浮动相关
  • 给github项目添加CI badge
  • 技术:超级实用的电脑小技巧
  • 今年的LC3大会没了?
  • 前端每日实战 2018 年 7 月份项目汇总(共 29 个项目)
  • 人脸识别最新开发经验demo
  • 软件开发学习的5大技巧,你知道吗?
  • 使用 Xcode 的 Target 区分开发和生产环境
  • 腾讯大梁:DevOps最后一棒,有效构建海量运营的持续反馈能力
  • # Swust 12th acm 邀请赛# [ A ] A+B problem [题解]
  • (02)vite环境变量配置
  • (翻译)Entity Framework技巧系列之七 - Tip 26 – 28
  • (附源码)ssm跨平台教学系统 毕业设计 280843
  • (亲测成功)在centos7.5上安装kvm,通过VNC远程连接并创建多台ubuntu虚拟机(ubuntu server版本)...
  • (算法)N皇后问题
  • (转)创业家杂志:UCWEB天使第一步
  • ***微信公众号支付+微信H5支付+微信扫码支付+小程序支付+APP微信支付解决方案总结...
  • .NET 2.0中新增的一些TryGet,TryParse等方法
  • .Net 6.0 处理跨域的方式
  • .net core 6 集成 elasticsearch 并 使用分词器
  • .NET开源项目介绍及资源推荐:数据持久层 (微软MVP写作)
  • [ element-ui:table ] 设置table中某些行数据禁止被选中,通过selectable 定义方法解决
  • [ IO.File ] FileSystemWatcher
  • [《百万宝贝》观后]To be or not to be?
  • [ajaxupload] - 上传文件同时附件参数值
  • [BZOJ 2142]礼物(扩展Lucas定理)
  • [bzoj4240] 有趣的家庭菜园
  • [C++] new和delete
  • [C++]priority_queue的介绍及模拟实现