Opencv3笔记27——直方图基础

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/huayunhualuo/article/details/81868014

1.概述

直方图广泛的应用于很多计算机视觉当中,通过标记帧与帧之间显著的边缘和颜色的统计变化,来检测视频场景的变化。
直方图就是对数据进行统计的一种方法,并且将统计值组织到一系列事先定义好的bin当中。bin其数值就是从数据中计算出的特征统计量,这些数据可以是诸如梯度,方向,色彩或者其他特征。
图像直方图(Image Histogram)是用以表示数字图像中亮度分布的直方图,标绘了图像中每个亮度值的像素数,可以用来观察直方图了解需要如何调整亮度分布。
直方图的意义:

  • 直方图是图像中像素强度分布的图形表达方式
  • 它统计了每一个强度值所具有的像素个数

具体的术语和细节

  • dims:需要统计的特征的数目
  • bins:每个特征空间子区段的数目
  • range:每个特征空间的取值范围

2. 直方图的计算与绘制

2.1 计算直方图:calcHist()函数

函数原型

void calcHist(const Mat * images,int nimages,const int * channels, InputArray mask, OutputArray hist,int dims,const int * histSize, const float ** ranges,bool uniform=true, bool accumulate = false)

这里写图片描述

2.2 找寻最值:minMaxLoc()函数

在数组中找到全局的最大值和最小值。
函数原型

void minMaxLoc(InputArray src, double * minVal,double * maxVal = 0,Point * minLoc= 0,Point maxLoc = 0, InputArray mask = noArray())

这里写图片描述

2.3 示例程序:H-S直方图

#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>

using namespace cv;

//main()函数
int main()
{
    //载入源图
    Mat srcImage, hsvImage;
    srcImage = imread("1.jpg");
    cvtColor(srcImage, hsvImage, COLOR_BGR2HSV);

    //参数准备
    //将色调量化为30个等级,将饱和度量化为32个等级
    //色调的直方图直条数量
    int hueBindim = 30;
    //饱和度的直方图直条数量
    int saturationBindim = 32;
    int histSize[] = { hueBindim,saturationBindim };
    //定义色调的变化范围
    float hueRanges[] = { 0,180 };
    //定义饱和度的变化范围为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);//查找数组和子数组的全局最小值和最大值存入maxValue中
    int scale = 10;
    Mat histImg = Mat::zeros(saturationBindim*scale, hueBindim * 10, CV_8UC3);
    //双层循环,进行直方图绘制
    for (int hue = 0; hue < hueBindim; hue++)
    {
        for (int saturation = 0; saturation < saturationBindim; 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::all(intensity), FILLED);
        }
    }
    imshow("素材图", srcImage);
    imshow("H-S直方图", histImg);
    waitKey(0);
    return 0;
}

这里写图片描述
这里写图片描述

2.3 示例程序:计算并绘制图像一维直方图

#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>

using namespace cv;
using namespace std;

//main()函数

int main()
{
    //载入原图并显示
    Mat srcImage = imread("1.jpg", 0);
    imshow("原图", srcImage);
    if (!srcImage.data)
    {
        printf("读取图片错误~!\n");
        return false;
    }

    //定义变量
    MatND dstHist;
    int dims = 1;
    float hrange[] = { 0,255 };
    const float * ranges[] = { hrange };
    int size = 256;
    int channels = 0;
    //计算图像的直方图
    calcHist(&srcImage, 1, &channels, Mat(), dstHist, dims, &size, ranges);
    int scale = 1;
    Mat dstImage(size*scale, size, CV_8U, Scalar(0));
    //获取最大值和最小值
    double minValue = 0;
    double maxValue = 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);
    return 0;
}

这里写图片描述
这里写图片描述

2.4示例程序:RGB三色直方图

#include <opencv2/opencv.hpp>
#include <opencv2/imgproc/imgproc.hpp>

using namespace cv;

int main()
{
    //载入素材图并显示
    Mat srcImage;
    srcImage = imread("1.jpg");
    imshow("素材图", srcImage);
    //参数准备
    int bins = 256;
    int hist_size[] = { bins };
    float range[] = { 0,256 };
    const float * ranges[] = { range };
    MatND redHist, grayHist, 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(), grayHist, 1, hist_size, ranges, true, false);
    //进行直方图计算,蓝色部分计算

    int channels_b[] = { 2 };
    calcHist(&srcImage, 1, channels_b, Mat(), blueHist, 1, hist_size, ranges, true, false);
    //绘制出三色直方图
    //参数准别
    double maxValue_red, maxValue_green, maxValue_blue;
    minMaxLoc(redHist, 0, &maxValue_red, 0, 0);
    minMaxLoc(grayHist, 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 = grayHist.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(255, 0, 0));
        //绘制绿色分量的直方图
        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(0, 0, 255));

    }

    //在窗口显示出绘制好的直方图
    imshow("图像的RGB直方图", histImage);
    waitKey(0);
    return 0;
}

这里写图片描述

这里写图片描述

猜你喜欢

转载自blog.csdn.net/huayunhualuo/article/details/81868014