[学习笔记-图像处理篇]直方图均衡化(直方图匹配)c++程序梳理

基于OpenCV 直方图匹配梳理一下直方图匹配的流程。

依上述链接所说,直方图匹配的步骤如下:

  1. 分别计算源图像与目标图像的累计概率分布
  2. 分别对源图像和目标图像进行直方图均衡化操作
  3. 利用映射关系使源图像直方图按照规定进行变换

发现还是注释代码梳理的快一点。

#include 
#include 
#include 

int main(int argc,char* argv[])
{
    /*********写路径读入源图像srcImage和目标图像dstImage*********/
    cv::Mat srcImage = cv::imread(R"(E:\CodeBlocks\data\lena.jpg)");
    cv::Mat dstImage = cv::imread(R"(E:\CodeBlocks\data\starry_night.jpg)");
    /***********判断数据是否为空***********/
    if (!srcImage.data || ! dstImage.data)
    {
        std::cerr << "fail to load image" <<std::endl;
        exit(-1);
    }
    /*********对dstImage大小重置,依据srcImage.size()大小重设dstImage大小,输出为dstImage************/
    cv::resize(dstImage,dstImage,srcImage.size(),0,0,cv::INTER_LINEAR);
    cv::imshow("srcImage",srcImage);
    cv::imshow("testImage",dstImage);
    /********定义一些空数组,后续统计灰度*************/
    //统计直方图参数
    float srcCdf[256];
    float dstCdf[256];
    int srcAddTemp[256];
    int dstAddTemp[256];
    int histMatchMap[256];
    for(int i=0;i<256;i++)
    {
        srcCdf[i] = 0;
        dstCdf[i] = 0;
        srcAddTemp[i] = 0;
        dstAddTemp[i] = 0;
        histMatchMap[i] = 0;
    }
    float srcSumTemp = 0;
    float dstSumTemp = 0;

    /***********计算总像素数***********/
    int srcNPixel = srcImage.rows * srcImage.cols;
    int dstNPixel = dstImage.rows * dstImage.cols;
    
    int matchFlag = 0;
    /*********遍历图片每个像素,统计不同灰度值的数量,存放在长256的灰度数组srcAddTemp和dstAddTemp中***********/
    //统计像素
    for(int i=0;i < srcImage.rows; i++)
    {
        for(int j = 0; j < srcImage.cols;j++)
        {
            srcAddTemp[(int)srcImage.at<uchar>(i,j)]++;
            dstAddTemp[(int)dstImage.at<uchar>(i,j)]++;
        }
    }

    /**********先累加所有灰度值到srcSumTemp和dstSumTemp,再计算平均每个灰度的分布概率(用每个灰度累计数量/总像素数)***********/
    //计算累计概率分布
    for(int i=0;i < 256;i++)
    {
        srcSumTemp += srcAddTemp[i];
        srcCdf[i] = srcSumTemp/ srcNPixel;
        dstSumTemp += dstAddTemp[i];
        dstCdf[i] = dstSumTemp/ dstNPixel;
    }
    
    /******先设置一个最小匹配参数minMatchPara,遍历源图像灰度级,查找目标图像灰度级中与其分布概率的差的绝对值最小的灰度级,并将目标图像此时的灰度级赋给matchFlag,统计与源图像256个灰度级对应分布概率最接近的目标图像灰度级,存在histMatchMap中。******/
    //直方图匹配实现
    for(int i=0;i<256;i++)
    {
        float minMatchPara = 20;
        for(int j=0;j<256;j++)
        {
            if (minMatchPara > cv::abs(srcCdf[i] - dstCdf[j]))
            {
                minMatchPara = cv::abs(srcCdf[i] - dstCdf[j]);
                matchFlag = j;
            }
        }
        histMatchMap[i] = matchFlag;
    }
    
    //初始化匹配图像
    cv::Mat HistMatchImage = cv::Mat::zeros(srcImage.size(),CV_8UC3);
    /*****彩图变灰******/
    cv::cvtColor(srcImage,HistMatchImage,cv::COLOR_BGR2GRAY);
    //映射
    for(int i=0;i<HistMatchImage.rows;i++)
    {
        for(int j=0;j<HistMatchImage.cols;j++)
        {
            HistMatchImage.at<uchar>(i,j) = histMatchMap[(int)HistMatchImage.at<uchar>(i,j) ];
        }
    }
     cv::imshow("ResultImage",HistMatchImage);
    cv::waitKey(0);
    cv::destroyAllWindows();
    return 0;
}

该例程匹配后图像均为灰度图,因为中间做了一个RGB转灰度图操作,但 OpenCV直方图(直方图、直方图均衡,直方图匹配,原理、实现) 提出的对RGB三通道分别匹配,最后累加,结果还是RGB,但程序会出现cv::Exception的奇异问题,待调试。

你可能感兴趣的:(图像处理篇,opencv)