OpenCV成长之路:图像直方图

http://ronny.blog.51cto.com/8801997/1394115

2014-04-11 13:47:27

标签:opencv 直方图 统计表

原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。http://ronny.blog.51cto.com/8801997/1394115

一、图像直方图的概念

图像直方图是反映一个图像像素分布的统计表,其实横坐标代表了图像像素的种类,可以是灰度的,也可以是彩色的。纵坐标代表了每一种颜色值在图像中的像素总数或者占所有像素个数的百分比。

图像是由像素构成,因为反映像素分布的直方图往往可以作为图像一个很重要的特征。在实际工程中,图像直方图在特征提取、图像匹配等方面都有很好的应用。

二、利用OpenCV计算图像的直方图

OpenCV中计算图像直方图像函数是calcHist,它的参数比较多,下面分析一下它的接口和用法。


1

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

const Mat* images:为输入图像的指针。

int nimages:要计算直方图的图像的个数。此函数可以为多图像求直方图,我们通常情况下都只作用于单一图像,所以通常nimages=1。

const int* channels:图像的通道,它是一个数组,如果是灰度图像则channels[1]={0};如果是彩色图像则channels[3]={0,1,2};如果是只是求彩色图像第2个通道的直方图,则channels[1]={1};

IuputArray mask:是一个遮罩图像用于确定哪些点参与计算,实际应用中是个很好的参数,默认情况我们都设置为一个空图像,即:Mat()。

OutArray hist:计算得到的直方图

int dims:得到的直方图的维数,灰度图像为1维,彩色图像为3维。

const int* histSize:直方图横坐标的区间数。如果是10,则它会横坐标分为10份,然后统计每个区间的像素点总和。

const float** ranges:这是一个二维数组,用来指出每个区间的范围。

后面两个参数都有默认值,uniform参数表明直方图是否等距,最后一个参数与多图像下直方图的显示与存储有关。

下面我们来计算一幅图像的灰度直方图,彩色直方图以及自定义的灰度分布图。

灰度直方图:


1

2

3

4

5

6

7

8

9

10

11

12

int main()

{

    Mat Image=imread("../cat.png");

    cvtColor(Image,Image,CV_BGR2GRAY);

    const int channels[1]={0};

    const int histSize[1]={256};

    float hranges[2]={0,255};

    const float* ranges[1]={hranges};

    MatND hist;

    calcHist(&Image,1,channels,Mat(),hist,1,histSize,ranges);

    return 0;

}

彩色直方图:


1

2

3

4

5

6

7

8

9

10

11

int main()

{

    Mat Image=imread("../cat.png");

    const int channels[3]={0,1,2};

    const int histSize[3]={256,256,256};

    float hranges[2]={0,255};

    const float* ranges[3]={hranges,hranges,hranges};

    MatND hist;

    calcHist(&Image,1,channels,Mat(),hist,3,histSize,ranges);

    return 0;

}

不均匀直方图,我们分别统计0-50,50-80,80-150,150-230,230-255区间的灰度分布:


1

2

3

4

5

6

7

8

9

10

11

12

int main()

{

    Mat Image=imread("../cat.png");

    cvtColor(Image,Image,CV_BGR2GRAY);

    const int channels[1]={0};

    int histSize[1]={5};

    float hranges[6]={0,50,80,150,230,255};

    const float* ranges[1]={hranges};

    MatND hist;

    calcHist(&Image,1,channels,Mat(),hist,1,histSize,ranges,false);

    return 0;

}

三、直方图的显示

从上面的例子中我们可以看出,直方图计算得到的实际上是一个多维数组,这并不够直观,我们希望能够像在Excel中把相关数据通过表的形式表示出来。

下面通过划线函数来把一个灰度直方图显示出来:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

Mat getHistImg(const MatND& hist)

{

    double maxVal=0;

    double minVal=0;

    //找到直方图中的最大值和最小值

    minMaxLoc(hist,&minVal,&maxVal,0,0);

    int histSize=hist.rows;

    Mat histImg(histSize,histSize,CV_8U,Scalar(255));

    // 设置最大峰值为图像高度的90%

    int hpt=static_cast<int>(0.9*histSize);

    for(int h=0;h<histSize;h++)

    {

        float binVal=hist.at<float>(h);

        int intensity=static_cast<int>(binVal*hpt/maxVal);

        line(histImg,Point(h,histSize),Point(h,histSize-intensity),Scalar::all(0));

    }

    return histImg;

}

四、直方图变换

直方图变换是图像处理中一个很重要的概念,图像直方图可以反映出图像对比度,明暗程度等特征,所以我们可以利用直方图的变换进行图像画面的调节。

直方图变换在实际工程中的应用很广,一些美化照片的软件很多工具都是在图像的直方图上作文章,如果有读者对这这方面感兴趣的推荐:http://www.cnblogs.com/Imageshop/

下面介绍两个简单的直方图变换函数:直方图拉伸与直方图均衡化。

如果图像的灰度在直方图上显示集中在某一个区间,则说明图像色彩单一,我们可以将其扩展到更宽的灰度范围内让图像更有层次感。

变换函数:将图像的一种灰度值经过变换得到另一个灰度。

直方图变换的核心就是变换函数,s=T(r),r是变换前的灰度值,s是变换后的灰度值,如要我们想将[a,b]区间的灰度变换到[0,255]范围内,则变换函数是:T(r)=255*(r-a)/(b-a)。

我们在OpenCV中创建这样一个变换函数:


1

2

3

4

5

6

7

8

9

10

11

12

// 创建一个1*256的矢量

Mat lut(1,256,CV_8U);

for(int i=0;i<256;i++)

{

    if(lut.at<uchar>(i)<imin)

        lut.at<uchar>(i)=0;

    else if(lut.at<uchar>(i)>imax)

        lut.at<uchar>(i)=255;

    else

        lut.at<uchar>(i)=static_cast<uchar>(

        255.0*(i-imin)/(imax-imin)+0.5);

}

其中imax,imin是图像中的最小灰度与最大灰度。我们可以从直方图中求出:


1

2

3

4

5

6

7

8

9

10

11

int imax,imin;

for(imin=0;imin<256;imin++)

{

    if(hist.at<uchar>(imin)>minValue)

        break;

}

for(imax=255;imax>-1;imax--)

{

    if(hist.at<uchar>(imax)>minValue)

        break;

}

最后我们应用OpenCV中的LUT函数,把变换应用在直方图上即可。


1

LUT(image,lut,result);

第二个参数就像一个查找表一样,将原图像中的灰度按表查找,然后把灰度值替换为表中对应的值。

有了上面灰度拉伸的例子就不难理解图像的直方图均衡了,直方图均衡化可以让图像灰度分布更加均匀,让图像的对比度增强。

在OpenCV中直方图均衡不用像灰度拉伸那样先构造一个变换函数,它有直接对应的函数,当然你如果有兴趣也可以去尝试写一下变换函数均衡化的变换原理会稍复杂一些,在OpenCV这个系列里面,不会太多的介绍数字图像中的算法,以后有机会再专门来讨论。


1

2

3

4

5

6

7

8

9

int main()

{

    Mat Image=imread("../cat.png");

    cvtColor(Image,Image,CV_BGR2GRAY);

         

    Mat result;

    equalizeHist(Image,result);

    return 0;

}

时间: 2024-10-24 21:26:06

OpenCV成长之路:图像直方图的相关文章

OpenCV成长之路:图像直方图的应用

2014-04-11 13:57:03 标签:opencv 图像 直方图 原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://ronny.blog.51cto.com/8801997/1394118 正如第4篇文章所说的图像直方图在特征提取方面有着很重要的作用,本文将举两个实际工程中非常实用的例子来说明图像直方图的应用. 一.直方图的反向映射. 我们以人脸检测举例,在人脸检测中,我们第一步往往需要先提取图像中皮肤区域来缩小人脸的检

OpenCV入门教程之四 图像直方图

一.图像直方图的概念 图像直方图是反映一个图像像素分布的统计表,其实横坐标代表了图像像素的种类,可以是灰度的,也可以是彩色的.纵坐标代表了每一种颜色值在图像中的像素总数或者占所有像素个数的百分比. 图像是由像素构成,因为反映像素分布的直方图往往可以作为图像一个很重要的特征.在实际工程中,图像直方图在特征提取.图像匹配等方面都有很好的应用.  二.利用OpenCV计算图像的直方图 OpenCV中计算图像直方图像函数是calcHist,它的参数比较多,下面分析一下它的接口和用法. void calc

OpenCV入门教程之五 图像直方图的应用

正如第4篇文章所说的图像直方图在特征提取方面有着很重要的作用,本文将举两个实际工程中非常实用的例子来说明图像直方图的应用. 一.直方图的反向映射 我们以人脸检测举例,在人脸检测中,我们第一步往往需要先提取图像中皮肤区域来缩小人脸的检测范围,这一般获得皮肤的颜色范围还需要定义阈值并不断的调整,实际中参数太多而不容易控制. 这里我们就可以考虑用直方图的反射映射. 1,收集人脸皮肤样本. 2,拼合样本并计算其颜色直方图. 3,将得到的样本颜色直方图反射映射到待检测的图片中,然后进行阈值化即可. 这里为

OpenCV成长之路:直线、轮廓的提取与描述

http://ronny.blog.51cto.com/8801997/1394139 原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://ronny.blog.51cto.com/8801997/1394139 基于内容的图像分析的重点是提取出图像中具有代表性的特征,而线条.轮廓.块往往是最能体现特征的几个元素,这篇文章就针对于这几个重要的图像特征,研究它们在OpenCV中的用法,以及做一些简单的基础应用. 一.Canny检测轮

OpenCV 学习(计算图像的直方图)

OpenCV 计算图像的直方图 计算图像的直方图是图像处理领域一个非常常见的基本操作. OpenCV 中提供了 calcHist 函数来计算图像直方图.不过这个函数说实话挺难用的,研究了好久才掌握了些基本的用法. calcHist 函数 C++ 的函数原型如下: void calcHist(const Mat* images, int nimages, const int* channels, InputArray mask, SparseMat& hist, int dims, const i

图像直方图均衡化增强opencv与C语言版

本文实现彩色图像的全局直方图均衡.分别对R/G/B三通道均衡,读写图片采用OpenCV.代码如下: #include <opencv2/opencv.hpp> //#include <cv.h> //#include <cxcore.h> //#include <highgui.h> #include <time.h> #include <stdio.h> #include <math.h> #include "

在python3下使用OpenCV 抓取摄像头图像并实时显示3色直方图

以下代码为在Python3环境下利用OpenCV 抓取摄像头的实时图像, 通过OpenCV的 calHist函数计算直方图, 并显示在3个不同窗口中. import cv2 import numpy as np from matplotlib import pyplot as plt import time cap  = cv2.VideoCapture(0) for i in range(0, 19):     print(cap.get(i)) while(1):     ret, fram

opencv图像直方图均衡化及其原理

直方图均衡化是什么有什么用 先说什么是直方图均衡化,通俗的说,以灰度图为例,原图的某一个像素为x,经过某个函数变为y.形成新的图.新的图的灰度值的分布是均匀的,这个过程就叫直方图均衡化. 图像直方图均衡化作用:用来增强对比度. 这种方法通常用来增加许多图像的全局对比度,尤其是当图像的有用数据的对比度相当接近的时候.通过这种方法,亮度可以更好地在直方图上分布.这样就可以用于增强局部的对比度而不影响整体的对比度,直方图均衡化通过有效地扩展常用的亮度来实现这种功能. 这种方法对于背景和前景都太亮或者太

opencv python:图像直方图 histogram

直接用matplotlib画出直方图 def plot_demo(image): plt.hist(image.ravel(), 256, [0, 256]) # image.ravel()将图像展开,256为bins数量,[0, 256]为范围 plt.show() 图像直方图 def image_hist(image): color = ('blue', 'green', 'red') for i, color in enumerate(color): # 计算出直方图,calcHist(i