C++版本OpenCv教程(二十三)直方图均衡化

如果一个图像的直方图都集中在一个区域,则整体图像的对比度比较小,不便于图像中纹理的识别。例如相邻的两个像素灰度值如果分别是120和121,仅凭肉眼是如法区别出来的。同时,如果图像中所有的像素灰度值都集中在100到150之间,则整个图像想会给人一种模糊的感觉,看不清图中的内容。如果通过映射关系,将图像中灰度值的范围扩大,增加原来两个灰度值之间的差值,就可以提高图像的对比度,进而将图像中的纹理突出显现出来,这个过程称为图像直方图均衡化。

在OpenCV 4中提供了equalizeHist()函数用于将图像的直方图均衡化,该函数的函数原型在代码清单4-7中给出。

void cv::equalizeHist(InputArray src,OutputArray dst)
  • src:需要直方图均衡化的CV_8UC1图像。
  • dst:直方图均衡化后的输出图像,与src具有相同尺寸和数据类型。

该函数形式比较简单,但是需要注意该函数只能对单通道的灰度图进行直方图均衡化。对图像的均衡化示例程序在代码清单4-8中给出,程序中我们将一张图像灰度值偏暗的图像进行均衡化,通过结果可以发现经过均衡化后的图像对比度明显增加,可以看清楚原来看不清的纹理。通过绘制原图和均衡化后的图像的直方图可以发现,经过均衡化后的图像直方图分布更加均匀。

#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
using namespace cv;
using namespace std;

void drawHist(Mat&hist,int type,string name){
    
    //归一化并回执直方图函数
    int hist_w=512;
    int hist_h=400;
    int width=2;
    Mat histImage=Mat::zeros(hist_h,hist_w,CV_8UC3);
    normalize(hist,hist,1,0,type,-1,Mat());
    for(int i=1;i<=hist.rows;++i){
    
    
        rectangle(histImage,Point(width*(i-1),hist_h-1),
                  Point(width*i-1,hist_h-cvRound(hist_h*hist.at<float>(i-1))-1),
                  Scalar(255,255,255),-1);
    }
    imshow(name,histImage);
}

int main(){
    
    
    Mat img=imread("gearwheel.jpg");
    if(img.empty()){
    
    
        cout<<"请确认输入的图片路径是否正确"<<endl;
        return -1;
    }
    Mat gray,hist,hist2;
    cvtColor(img,gray,COLOR_BGR2GRAY);
    Mat equalImg;
    equalizeHist(gray,equalImg);//将图像直方图均衡化
    const int channels[1]={
    
    0};
    float inRanges[2]={
    
    0,255};
    const float*ranges[1]={
    
    inRanges};
    const int bins[1]={
    
    256};
    calcHist(&gray,1,channels,Mat(),hist,1,bins,ranges);
    calcHist(&equalImg,1,channels,Mat(),hist2,1,bins,ranges);
    drawHist(hist,NORM_INF,"hist");
    drawHist(hist2,NORM_INF,"hist2");
    imshow("原图",gray);
    imshow("均衡化后的图像",equalImg);
    waitKey(0);
    return 0;
}

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_33287871/article/details/112168885
今日推荐