您的位置:首页 > 汽车 > 时评 > 5.6对数变换和非对数变换

5.6对数变换和非对数变换

2024/10/19 8:30:11 来源:https://blog.csdn.net/weixin_45794330/article/details/141788732  浏览:    关键词:5.6对数变换和非对数变换

实验原理

在图像处理中,对数变换是一种常用的非线性变换技术,用于增强图像的对比度,尤其是在图像中包含较暗区域或者对比度较低的情况下。对数变换的基本思想是通过扩展图像中较暗像素的值,同时压缩较亮像素的值,从而改善图像的整体对比度。

在OpenCV中,由于图像通常是以8位整数形式存储的(0到255),因此直接应用上述公式可能会导致一些问题,如溢出或精度损失。因此,在实现对数变换时,通常需要先将图像转换为浮点数,进行变换后再转换回整数。

示例代码1

下面是一个使用OpenCV实现对数变换的例子:

#include "pch.h"
#include <opencv2/opencv.hpp>
#include <iostream>using namespace cv;
using namespace std;int main() 
{// 读取图像Mat img = imread("01.png", IMREAD_COLOR);if (img.empty()){cerr << "无法加载图像,请检查文件路径是否正确。" << endl;return -1;}// 定义灰度目标矩阵Mat gray;cvtColor(img, gray, COLOR_BGR2GRAY);//转化为灰度图像// 计算对数变换的比例常数cdouble c = 255 / log(1 + 255.0); // 因为像素值范围是0-255// 定义目标矩阵// 创建输出图像Mat logTransformedImg;// 对图像进行对数变换// 创建一个空的32位浮点数图像Mat img32f;//gray.convertTo(img32f, CV_32F, 1.0 / 255.0); // 将8位图像转换为0.0到1.0之间的浮点数  将图像转换为32位浮点型gray.convertTo(img32f, CV_32F); // 将图像转换为32位浮点型img32f += 1;                   // 避免log(0),将所有像素值加1log(img32f, img32f);              // 应用自然对数img32f *= c;                   // 应用比例常数img32f.convertTo(logTransformedImg, CV_8U); // 转换回8位整数// 显示原始图像和对数变换后的图像namedWindow("原图像", WINDOW_NORMAL);imshow("原图像", img);namedWindow("灰度图像", WINDOW_NORMAL);imshow("灰度图像", gray);namedWindow("对数变换后图像", WINDOW_NORMAL);imshow("对数变换后图像", logTransformedImg);waitKey(0); // 等待按键退出return 0;
}

在这段代码中,我们首先读取了一幅灰度图像,并计算了一个比例常数cc。然后,我们将图像的数据类型从8位整数转换为32位浮点数,这是为了保证后续计算的精度。接着,我们将每个像素值加1,以避免对数函数中的零值(因为log⁡(0)是未定义的),然后应用自然对数变换,并乘以比例常数c。最后,我们将变换后的图像转换回8位整数类型,并显示出来。

这种方法适用于灰度图像。如果您要处理彩色图像,可以分别对每个颜色通道应用相同的变换。

运行结果1

实验代码2

5.6对数变换

#include "pch.h"
#include <iostream>
#include<opencv2/opencv.hpp>
using namespace cv;  //所有opencv类都在命名空间cv下
using namespace std;
//#pragma comment(lib, "opencv_world450d.lib")  //引用引入库 // 对数变换方法1
cv::Mat logTransform1(cv::Mat srcImage, int c)
{// 输入图像判断if (srcImage.empty())std::cout << "No data!" << std::endl;cv::Mat resultImage =cv::Mat::zeros(srcImage.size(), srcImage.type());// 计算 1 + rcv::add(srcImage, cv::Scalar(1.0), srcImage);// 转换为32位浮点数srcImage.convertTo(srcImage, CV_32F);// 计算 log(1 + r)log(srcImage, resultImage);resultImage = c * resultImage;// 归一化处理cv::normalize(resultImage, resultImage,0, 255, cv::NORM_MINMAX);cv::convertScaleAbs(resultImage, resultImage);return resultImage;
}
// 对数变换方法2
cv::Mat logTransform2(Mat srcImage, float c)
{// 输入图像判断if (srcImage.empty())std::cout << "No data!" << std::endl;cv::Mat resultImage =cv::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);}}// 归一化处理cv::normalize(resultImage, resultImage,0, 255, cv::NORM_MINMAX);cv::convertScaleAbs(resultImage, resultImage);return resultImage;
}
// 对数变换方法3
cv::Mat logTransform3(Mat srcImage, float c)
{// 输入图像判断if (srcImage.empty())std::cout << "No data!" << std::endl;cv::Mat resultImage =cv::Mat::zeros(srcImage.size(), srcImage.type());srcImage.convertTo(resultImage, CV_32F);resultImage = resultImage + 1;cv::log(resultImage, resultImage);resultImage = c * resultImage;cv::normalize(resultImage, resultImage, 0, 255, cv::NORM_MINMAX);cv::convertScaleAbs(resultImage, resultImage);return resultImage;
}
int main()
{// 读取灰度图像及验证cv::Mat srcImage = cv::imread("022.jpeg", 0);if (!srcImage.data)return -1;// 验证三种不同方式的对数变换速度namedWindow("原图", WINDOW_NORMAL);cv::imshow("原图", srcImage);float c = 1.2;cv::Mat resultImage;double tTime;tTime = (double)getTickCount();const int nTimes = 10;for (int i = 0; i < nTimes; i++){resultImage = logTransform3(srcImage, c);}tTime = 1000 * ((double)getTickCount() - tTime) /getTickFrequency();tTime /= nTimes;std::cout << "第3种方法耗时:" << tTime << std::endl;namedWindow("效果图", WINDOW_NORMAL);cv::imshow("效果图", resultImage);cv::waitKey(0);system("pause");return 0;
}

实验结果2

实验代码3

5.7非对数变换


#include "pch.h"
#include <iostream>
#include<opencv2/opencv.hpp>
using namespace cv;  //所有opencv类都在命名空间cv下
using namespace std;
//#pragma comment(lib, "opencv_world450d.lib")  //引用引入库 //归一化
//data				进行处理的像素集合
//grayscale			目标灰度级
//rows cols type	目标图像的行,列,以及类型
Mat Normalize(vector<double> data, int grayscale, int rows, int cols, int type)
{double max = 0.0;double min = 0.0;for (int i = 0; i < data.size(); i++){if (data[i] > max)max = data[i];if (data[i] < min)min = data[i];}Mat dst;dst.create(rows, cols, type);int index = 0;for (int r = 0; r < dst.rows; r++){uchar* dstRowData = dst.ptr<uchar>(r);for (int c = 0; c < dst.cols; c++){dstRowData[c] = (uchar)(grayscale * ((data[index++] - min) * 1.0 / (max - min)));}}return dst;
}//反对数变换
Mat NegativeLogTransform(Mat src, double parameter)
{vector<double> value;for(int r = 0;r < src.rows;r++){uchar* srcRowData = src.ptr<uchar>(r);for(int c = 0;c < src.cols;c++){//反对数变换公式为s = ((v + 1) ^ r - 1) / vvalue.push_back((pow(parameter + 1, srcRowData[c]) - 1) / parameter);}}//计算得出的s经过对比拉升(将像素值归一化到0-255)得到最终的图像return Normalize(value, 255, src.rows, src.cols, src.type());
}int main()
{Mat srcImg = imread("021.jpeg",0);if(srcImg.data == NULL){cout << "图像打开失败" << endl;return -1;}namedWindow("原图", WINDOW_NORMAL);imshow("原图",srcImg);//Mat dstImg = LogTransform(srcImg,0.2);Mat dstImg;dstImg = NegativeLogTransform(srcImg, 3);namedWindow("变换后", WINDOW_NORMAL);imshow("变换后",dstImg);waitKey(0);return 0;}

实验结果3

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com