基于局部标准差的图像局部对比度增强算法

来源:互联网 发布:日光月美新域名 编辑:程序博客网 时间:2024/06/05 10:41

  以前用代码实现过的一个算法,算法介绍在这里已经写的非常详细了,我也是根据这里的介绍写的算法代码,可能稍有改动。算法原理大家可以看原文,在这里给出代码供大家参考参考。

利用积分图像计算局部均值与局部标准差

  这个算法需要计算局部均值与局部标准差,我们知道,直接计算局部均值与标准差的效率是非常低的,设图像大小为 W*H, 窗口大小为 n, 那么直接计算的算法复杂度为 O(WHn2),如果我们采用积分图像来计算,算法复杂度为 O(WH),复杂度与窗口大小无关,仅与图像大小有关。

计算图像的积分图像 (单通道 or 三通道):

Mat Intergral_2(const Mat& image){    Mat result;    Mat image_2;    if (image.channels() == 1)    {        image.convertTo(image_2, CV_64FC1);        result.create(image.size(), CV_64FC1);    }    else if (image.channels() == 3)    {        image.convertTo(image_2, CV_64FC3);        result.create(image.size(), CV_64FC3);    }    //cout << image_2 << endl;    int c = image_2.channels();    int nr = image_2.rows;    int nc = image_2.cols*c;    for (int i = 0; i < nr; i++)    {        const double* inData = image_2.ptr<double>(i);        double* outData = result.ptr<double>(i);        if (i != 0)        {            const double* outData_up = result.ptr<double>(i - 1);            for (int j = 0; j < nc; j++)            {                if (j >= c)                {                    outData[j] = inData[j] + outData_up[j] + outData[j - c] - outData_up[j - c];                }                else                {                    outData[j] = inData[j] + outData_up[j];                }            }        }        else        {            for (int j = 0; j < nc; j++)            {                if (j >= c)                {                    outData[j] = inData[j] + outData[j - c];                }                else                {                    outData[j] = inData[j];                }            }        }    }    return result;}

利用积分图象计算图像的局部均值与局部标准差 (单通道 or 三通道,d 为窗口大小的半径):

int Local_MeanStd(const Mat &_image, Mat &_mean, Mat &_std, int d){    if (_image.channels() == 1)    {        _mean.create(_image.size(), CV_64FC1);        _std.create(_image.size(), CV_64FC1);    }    else if (_image.channels() == 3)    {        _mean.create(_image.size(), CV_64FC3);        _std.create(_image.size(), CV_64FC3);    }    //边界填充    Mat image_big;    copyMakeBorder(_image, image_big, d + 1, d + 1, d + 1, d + 1, BORDER_REFLECT_101);    image_big.convertTo(image_big, _mean.type());    Mat image_big_2 = image_big.mul(image_big);    Mat Intergral_image1 = Intergral_2(image_big);    Mat Intergral_image2 = Intergral_2(image_big_2);    int N = (2 * d + 1)*(2 * d + 1);    int c = _image.channels();    int nr = _image.rows;    int nc = _image.cols*c;    //cout << Intergral_image1 << endl;    //cout << Intergral_image2 << endl;    for (int i = 0; i < nr; i++)    {        double* outData1 = _mean.ptr<double>(i);        double* outData2 = _std.ptr<double>(i);        double* inDataUp1 = Intergral_image1.ptr<double>(i);        double* inDataUp2 = Intergral_image2.ptr<double>(i);        double* inDataDown1 = Intergral_image1.ptr<double>(i + 2 * d + 1);        double* inDataDown2 = Intergral_image2.ptr<double>(i + 2 * d + 1);        for (int j = 0; j < nc; j++)        {            double sumi1 = inDataDown1[j + (2 * d + 1)*c] + inDataUp1[j] - inDataUp1[j + (2 * d + 1)*c] - inDataDown1[j];            double sumi2 = inDataDown2[j + (2 * d + 1)*c] + inDataUp2[j] - inDataUp2[j + (2 * d + 1)*c] - inDataDown2[j];            outData1[j] = sumi1 / N;            outData2[j] = (sumi2 - sumi1*outData1[j]) / N;        }    }    cv::sqrt(_std, _std);    return 0;}

对比度增强算法

最后是增强算法的实现:

int ACE(const Mat &_image, Mat &_result, int _d, int _Scale, int _MaxCG){    Mat localmean, localstd;    Local_MeanStd(_image, localmean, localstd, _d);    if (_image.channels() == 1)    {        _result.create(_image.size(), CV_64FC1);    }    else if (_image.channels() == 3)    {        _result.create(_image.size(), CV_64FC3);        }    Mat mean_m, std_m;    meanStdDev(_image, mean_m, std_m);     double std[3];    std[0] = std_m.at<double>(0, 0);    std[1] = std_m.at<double>(1, 0);    std[2] = std_m.at<double>(2, 0);    int c = _image.channels();    int nr = _image.rows;    int nc = _image.cols*c;    double CG;    for (int i = 0; i < nr; i++)    {        double* meanData = localmean.ptr<double>(i);        double* stdData = localstd.ptr<double>(i);        const uchar* imageData = _image.ptr<uchar>(i);        double* outData = _result.ptr<double>(i);        for (int j = 0; j < nc; j++)        {            CG = std[j % 3] / stdData[j];            if (CG > _MaxCG)                CG = _MaxCG;            outData[j] = meanData[j] + _Scale*CG*(int(imageData[j]) - meanData[j]);        }    }    _result.convertTo(_result, CV_8UC3);    return 0;}

算法效果

最后放几张处理前后的图片:

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

阅读全文
0 0
原创粉丝点击