数字图像处理8--图像增强之对数变换log,OpenCV C++

对数变换的通用形式为:

对数函数的一般形状的任何曲线,都能完成图像灰度级的扩展/压缩;但幂律变换对于这个目的更为通用;

代码实现:

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>

using namespace cv;
using namespace std;

//注意opencv中的log函数只能处理灰度图片,或单层图片
//基于源图像的方法1
Mat logTransform1(Mat srcImage, int c)
{
    if (srcImage.empty())
        cout << "No data" << endl;
    Mat resultImage = Mat::zeros(srcImage.size(), srcImage.type());
    add(srcImage, Scalar(1.0), srcImage);  //计算 r+1
    srcImage.convertTo(srcImage, CV_32F);  //转化为32位浮点型
    log(srcImage, resultImage);            //计算log(1+r)
    resultImage = c*resultImage;
    //归一化处理
    normalize(resultImage, resultImage, 0, 255, NORM_MINMAX);
    convertScaleAbs(resultImage, resultImage);
    return resultImage;

}
//方法2
Mat logTransform2(Mat srcImage, float c)
{
    if (srcImage.empty())
        cout << "No data" << endl;
    Mat resultImage = Mat::zeros(srcImage.size(), srcImage.type());
    double gray = 0;
    for (int i = 0; i < srcImage.rows; i++)
    {
        for (int j = 0; j < srcImage.cols; j++)
        {
            gray = (double)srcImage.at<uchar>(i, j);
            gray = c*log((double)(1 + gray));
            resultImage.at<uchar>(i, j) = saturate_cast<uchar>(gray);
        }
    }
    //归一化处理
    normalize(resultImage, resultImage, 0, 255, NORM_MINMAX);
    convertScaleAbs(resultImage, resultImage);
    return resultImage;
}

//方法3
Mat logTransform3(Mat srcImage, float c)
{
    if (srcImage.empty())
        cout << "No data" << endl;
    Mat resultImage = Mat::zeros(srcImage.size(), srcImage.type());
    srcImage.convertTo(resultImage, CV_32F);  //图像类型转换
    resultImage = resultImage + 1;            //图像矩阵元素加1
    log(resultImage,resultImage);
    resultImage = c*resultImage;
    //归一化处理
    normalize(resultImage, resultImage, 0, 255, NORM_MINMAX);
    convertScaleAbs(resultImage, resultImage);
    return resultImage;
}

int main()
{
    Mat srcImage = imread("123.tif", IMREAD_GRAYSCALE);
    if (!srcImage.data)
        return -1;
    imshow("srcImage", srcImage);
    float c = 1.2;
    Mat resultImage;
    resultImage = logTransform3(srcImage, c);

扫描二维码关注公众号,回复: 5309692 查看本文章

    imshow("resultImage", resultImage);
    waitKey(0);
    return 0;
}

下图为原图像、log增强后的图像

下面代码可处理彩色图像:

代码如下:

// log.cpp

/*
 * 对数函数的一般形状的任何曲线,都能完成图像灰度级的扩展/压缩;但幂律变换对于这个目的更为通用;
 * s = c*log(1+r)
 * 注意Opencv 中的log函数只能处理灰度图片,或单层图片
 */
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>

using namespace std;
using namespace cv;

Mat logTransform(Mat srcImage, float c_log)
{
    if (srcImage.empty())
        cout << "No data" << endl;
    CV_Assert(srcImage.channels() == 3);
    Mat imageLog = Mat::zeros(srcImage.size(), srcImage.type());
    srcImage.convertTo(imageLog, CV_32F);  //图像类型转换

    for (int i = 0; i < srcImage.rows; i++) {
        for (int j = 0; j < srcImage.cols; j++){
            imageLog.at<Vec3f>(i, j)[0] = c_log*log(1 + srcImage.at<Vec3b>(i, j)[0]);
            imageLog.at<Vec3f>(i, j)[1] = c_log*log(1 + srcImage.at<Vec3b>(i, j)[1]);
            imageLog.at<Vec3f>(i, j)[2] = c_log*log(1 + srcImage.at<Vec3b>(i, j)[2]);
        }
    }
    //归一化到0~255
    normalize(imageLog, imageLog, 0, 255, CV_MINMAX);
    //转换成8bit图像显示
    convertScaleAbs(imageLog, imageLog);
    return imageLog;
}

int main(int argc, char *argv[])
{
    Mat image = imread("image.jpg", IMREAD_COLOR);
    Mat dst =logTransform(image, 1);
    imshow("Soure", image);
    imshow("after", dst);
    waitKey();

    return 0;
}
 

结果如下:

猜你喜欢

转载自blog.csdn.net/cyf15238622067/article/details/87710740