opencv图像处理学习(十六)——直方图变换——查找和累计

版权声明:不得随意转载 https://blog.csdn.net/qq_35789421/article/details/88926540

直方图变换是通过改变和调整图像的直方图形状来实现改变图像灰度阶分布与结构的增强方法。图像直方图反映图像的对比度、明暗等细节特征,如果直方图集中在某一区间,画面呈现出来彩色单一,不利于观察分析。常见的直方图变换是通过灰度变换s=T(r)=255*(r-a)/(b-a),将[a,b]映射到[0,255]实现的。另外,根据直方图均衡的原理,为尽可能使像素点均匀分布,可以通过累计平均分配的方式计算出均衡化的像素。

PS:opencv自带函数会大幅度提高效率。

<1>直方图变换——查找

思路:(1)将源图像转换为灰度图,计算图像的灰度直方图。(2)根据预设阈值参数由低到高查找iLow,再由高到低找iHigh。(3)根据上步得到直方图iLow与iHihg并进行查找表变换。(4)通过查找表进行映射变换,完成直方图查找方法变换。

在opencv中,提供了lookUpTable函数和LUT函数进行查找变换,函数如下:

void LookupTable(Mat& table, uchar quan_val);

其中参数table是建立查找表的矩阵,quan_val是通道数

void LUT(Mat I, Mat lookUpTable, Mat J);

其中I是输入矩阵,lookUpTable是查找表,J是输出矩阵

e.g:

/* 直方图变换——累计*/
#include <opencv2\core\core.hpp>
#include <opencv2\imgproc\imgproc.hpp>
#include <opencv2\highgui\highgui.hpp>
#include <opencv2\opencv.hpp>
#include <iostream>

using namespace cv;
using namespace std;

int main(void)
{
    Mat srcImage = imread("girl.jpg");
    Mat Graysrc;
    Mat hist;

    if (!srcImage.data)
    {
        return -1;
    }
    
    cvtColor(srcImage, Graysrc,CV_BGR2GRAY);
    
    //第一步,计算灰度图直方图
    const int channels[1] = { 0 };
    const int histSize[1] = { 256 };
    float hranges[2] = { 0,255 };
    const float* range[1] = { hranges };
    
    calcHist(&Graysrc, 1, channels, Mat(), hist, histSize, range);

    //第二步,根据预设参数统计灰度级变换
    int segThreshold = 50;
    //由低到高进行查找
    int iLow = 0;
    
    for (; iLow < histSize[0]; iLow++)
    {
        if (hist.at<float>(iLow) > segThreshold)
        {
            break;
        }
    }

    //由高到低进行查找
    int iHigh = histSize[0]-1;
    
    for (; iHigh >= 0; iHigh--)
    {
        if (hist.at<float>(iHigh) > segThreshold)
        {
            break;
        }
    }

    //第三步:建立查找表
    cv::Mat lookUpTable(cv::Size(1, 256), CV_8U);
    
    for (int i = 0; i < 256; i++)
    {
        
        if (i < iLow)
        {
            lookUpTable.at<uchar>(i) = 0;
        }

        else if (i > iHigh)
        {
            lookUpTable.at<uchar>(i) = 255;
        }

        else
        {
            lookUpTable.at<uchar>(i) = static_cast<uchar>(255.0 * (i - iLow) / (iHigh - iLow + 0.5));
        }
    }

    //第四步:通过查找表进行映射变换
    cv::Mat histTransResult;
    cv::LUT(Graysrc, lookUpTable, histTransResult);
    cv::imshow("Graysrc", Graysrc);
    cv::imshow("histTransResult", histTransResult);
    cv::waitKey(0);
    return 0;
}

<2>直方图变换——累计

思路:(1)将源图像转换为灰度图,计算图像的灰度直方图(2)建立映射表,对直方图进行像素累计(3)根据映射表进行元素映射得到最终的直方图变换

猜你喜欢

转载自blog.csdn.net/qq_35789421/article/details/88926540