5.8幂律变换

目录

示例代码1

运行结果1

示例代码2

运行结果2

补充示例原理

示例:使用cv::pow进行图像处理

代码

运行结果

​编辑

补充

实验代码3

运行结果3​编辑


在OpenCV中,幂律变换(Power Law Transformations)是一种常用的图像增强技术,尤其适用于调整图像的对比度。这种变换通过应用一个幂函数来调整图像的亮度,使得图像的细节更加明显。幂律变换通常用于增强图像中的暗区域或亮区域,从而提高图像的整体对比度。

OpenCV中的实现方法

虽然OpenCV并没有直接提供幂律变换的函数,但可以通过简单的数学运算来实现这一变换。具体做法是先将图像转换为浮点数类型,然后应用幂律变换,最后再将结果转换回原来的类型。

示例代码1

转换数据类型

如果原始图像的数据类型为CV_8U,可以先将其转换为CV_32F类型,然后再进行幂运算。

最后再将结果转换回CV_8U类型。// 转换为浮点数类型

cpp 复制代码
cv::Mat floatImage;
image.convertTo(floatImage, CV_32F, 1.0 / 255.0);

// 应用幂运算
cv::pow(floatImage, power, powImage);

// 将结果转换回原始类型
powImage.convertTo(powImage, CV_8U, 255.0);

下面是一个使用OpenCV实现幂律变换的示例代码:

cpp 复制代码
#include "pch.h"

#include <opencv2/opencv.hpp>
#include <iostream>

using namespace cv;
using namespace std;

int main()
{
	// 读取图像
	Mat img = imread("2.jpeg", IMREAD_COLOR);
	if (img.empty())
	{
		cerr << "无法加载图像,请检查文件路径是否正确。" << endl;
		return -1;
	}
	
	// 定义灰度矩阵
	Mat gray;
	cvtColor(img, gray, COLOR_BGR2GRAY);//转化为灰度图像

	// 定义目标矩阵
	Mat imgPowerLawTransformed;

	// 设置幂律变换的参数
	double gamma = 0.5; // 使图像变亮
	double c = 1.0;     // 常数项

	// 应用幂律变换
	//转换浮点数类型
	Mat floatImage;
	gray.convertTo(floatImage, CV_32F,1.0/255.0); // 将图像转换为32位浮点数
	pow(floatImage, gamma,imgPowerLawTransformed);      // 应用幂运算
	imgPowerLawTransformed.convertTo(imgPowerLawTransformed, CV_8U, 255.0); // 将结果转换回8位无符号整数

	// 显示原始图像和变换后的图像
	namedWindow("源图像", WINDOW_NORMAL);
	imshow("源图像", img);
	
	namedWindow("灰度图像", WINDOW_NORMAL);
	imshow("灰度图像", gray);
	
	namedWindow("幂指化后图像", WINDOW_NORMAL);
	imshow("幂指化后图像", imgPowerLawTransformed);

	waitKey(0); // 等待按键退出

	return 0;
}

代码解释
1.读取图像:使用cv::imread读取输入图像,并确保它是灰度图像。
2.获取幂次方值:可从命令行参数中读取幂次方值。
3.设置幂律变换的参数:定义幂指数 gamma 和常数 c。
4.应用幂律变换:
将图像转换为32位浮点数类型,以避免运算过程中的溢出问题。
转换为浮点数类型:将图像转换为浮点数类型CV_32F,以便进行幂运算。
应用幂律变换 s = c⋅r γ,其中 r 是图像中的像素值。
将结果转换回8位无符号整数类型,以适应图像显示的要求。
4.创建输出图像:创建一个新的cv::Mat对象来存储幂运算后的结果。
5.应用幂运算:使用cv::pow函数对图像矩阵中的每个元素进行幂运算。
6.将结果转换回原始类型:将幂运算后的结果转换回原来的类型CV_8U。
7.显示结果:使用cv::imshow函数显示原始图像和幂运算后的图像,并等待用户按键退出。

通过以上步骤,你可以使用cv::pow函数来对图像矩阵中的每个元素进行幂运算,并避免溢出问题。
总结
幂律变换是一种有效的图像增强技术,可以通过调整幂指数𝛾来增强图像的对比度。
在OpenCV中,虽然没有直接提供幂律变换的函数,
但可以通过基本的数学运算和类型转换轻松实现这一变换。
这种方法特别适用于增强图像中的暗区域或亮区域,从而提高图像的整体对比度。

运行结果1

示例代码2

示例代码2下面是一个使用cv::pow函数来计算图像矩阵中每个元素的幂的示例代码

cpp 复制代码
#include "pch.h"

#include <opencv2/opencv.hpp>
#include <iostream>

using namespace cv;
using namespace std;

int main()
{

	// 读取图像
	Mat img = imread("1.png", IMREAD_COLOR);
	if (img.empty())
	{
		cerr << "无法加载图像,请检查文件路径是否正确。" << endl;
		return -1;
	}


	// 定义灰度矩阵
	Mat gray;
	cvtColor(img, gray, COLOR_BGR2GRAY);//转化为灰度图像

	// 定义目标矩阵
	Mat imgPowerLawTransformed;

	// 设置幂律变换的参数
	double power = 2; // 使图像变亮
	//此处数值为0.5 1.5等会报错,请勘探此问题

	// 应用幂律变换
	pow(gray, power, imgPowerLawTransformed);


	// 显示原始图像和变换后的图像
	namedWindow("源图像", WINDOW_NORMAL);
	imshow("源图像", img);

	namedWindow("灰度图像", WINDOW_NORMAL);
	imshow("灰度图像", gray);


	namedWindow("幂指化后图像", WINDOW_NORMAL);
	imshow("幂指化后图像", imgPowerLawTransformed);


	waitKey(0); // 等待按键退出

	return 0;
}

//代码解释
1.读取图像:使用cv::imread读取输入图像,并确保它是灰度图像。
2.获取幂次方值:获取幂次方值。
3.创建输出图像:创建一个新的cv::Mat对象来存储幂运算后的结果。
4.应用幂运算:使用cv::pow函数对图像矩阵中的每个元素进行幂运算。
5.显示结果:使用cv::imshow函数显示原始图像和幂运算后的图像,并等待用户按键退出。

//注意事项
1.数据类型:确保输入图像的数据类型适合进行幂运算。通常情况下,灰度图像的数据类型为CV_8U(无符号8位整型)。如果需要进行浮点数运算,可以将图像转换为CV_32F或CV_64F类型。
2.溢出问题:由于原始图像的数据类型为CV_8U,在进行幂运算时可能会发生溢出。为了避免溢出,可以在进行幂运算前将图像转换为浮点数类型,然后在计算完成后将结果转换回原来的类型。

运行结果2

补充示例原理

在OpenCV中,你可以使用cv::pow函数来计算图像矩阵中每个元素的幂。这个函数可以在OpenCV的core模块中找到,用于对矩阵中的每个元素进行幂运算。

cv::pow函数的基本语法如下:

cpp 复制代码
void pow(InputArray src, double power, OutputArray dst);
参数说明:

src:输入矩阵。
power:指数值。
dst:输出矩阵,与输入矩阵具有相同的大小和类型。

使用cv::pow函数可以帮助你实现各种基于幂运算的图像处理任务,
例如对图像进行伽马校正或其他需要幂运算的图像增强技术。

示例:使用cv::pow进行图像处理

假设你想对图像进行伽马校正,这是一个常见的图像增强技术,可以通过调整图像的亮度和对比度来改善图像质量。伽马校正的基本公式是:

下面是一个使用cv::pow函数进行伽马校正的例子:

代码

cpp 复制代码
#include "pch.h"
#include <opencv2/opencv.hpp>
#include <iostream>

using namespace cv;
using namespace std;

int main() 
{
	// 读取图像
	Mat img = imread("A1.jpeg", IMREAD_GRAYSCALE);
	if (img.empty()) 
	{
		cerr << "无法加载图像,请检查文件路径是否正确。" << endl;
		return -1;
	}

	// 设置伽马值
	double gamma = 0.5; // 增加对比度
	double c = 1.0;     // 比例常数

	// 将图像转换为浮点类型
	Mat imgFloat;
	img.convertTo(imgFloat, CV_32F, c / 255.0);

	

	// 伽马校正
	Mat imgGammaCorrected;
	pow(imgFloat, gamma, imgGammaCorrected);
	imgGammaCorrected *= c * 255.0; // 调整亮度

	// 转换回8位图像
	imgGammaCorrected.convertTo(imgGammaCorrected, CV_8U);

	// 显示原始图像和伽马校正后的图像
	namedWindow("原图像", WINDOW_NORMAL);
	imshow("原图像", img);

	namedWindow("伽马校正后图像", WINDOW_NORMAL);
	imshow("伽马校正后图像", imgGammaCorrected);

	waitKey(0); // 等待按键退出

	return 0;
}



在这个示例中,我们首先将图像转换为浮点类型,
然后使用cv::pow函数对图像进行伽马校正。
注意,伽马校正后的图像需要再次转换回8位整数类型,以便于显示或保存。

如果你需要对图像进行其他基于幂运算的操作,
如对数变换等,也可以使用类似的方法。
对于对数变换,可以直接使用cv::log函数来计算自然对数,
然后再使用cv::pow来计算其他形式的幂运算。

运行结果

补充

在OpenCV中,convertTo函数是一个非常有用的函数,它可以用来执行各种类型的数值转换和缩放操作。convertTo函数可以应用于矩阵(图像),并且能够执行基本的数学运算,比如缩放、偏移等。这对于调整图像的对比度和亮度特别有用。

cpp 复制代码
convertTo函数的基本形式如下:
void convertTo(OutputArray r, int rtype, double alpha=1, double beta=0 ) const;

参数解释
dst: 目标矩阵。如果指定为None,则会自动创建一个新的矩阵。
rtype: 指定输出矩阵的数据类型(例如,cv2.CV_8U, cv2.CV_32F等)。
alpha: 缩放因子,用于调整图像的对比度。如果alpha > 1,则对比度增加;如果alpha < 1,则对比度减小。
beta: 偏移量,用于调整图像的亮度。如果beta > 0,则亮度增加;如果beta < 0,则亮度减小。
  

示例代码

cpp 复制代码
#include "pch.h"
#include <opencv2/opencv.hpp>
#include <iostream>

int main(int argc, char** argv)
{
	// 加载图像
	cv::Mat img = cv::imread("2B.png", cv::IMREAD_GRAYSCALE); // 读取为灰度图像

	if (img.empty())
	{
		std::cout << "Could not open or find the image" << std::endl;
		return -1;
	}

	// 定义变换参数
	double alpha = 1.5; // 对比度增加
	double beta = 10;   // 亮度增加

	// 创建一个空的输出图像
	cv::Mat output;

	// 使用convertTo函数调整图像
	img.convertTo(output, -1, alpha, beta);
//convertTo函数的第一个参数是输出图像,第二个参数-1表示保持输入图像的数据类型不变,第三个参数alpha是缩放因子,第四个参数beta是偏移量。

	//将输出图像转换回8位无符号整型
	//*************可需要 可不要
	//normalize(output, output, 0, 255, cv::NORM_MINMAX);//归一化,将数据归一到0-255之间;


	// 显示结果
	cv::namedWindow("Original Image", cv::WINDOW_NORMAL);
	cv::imshow("Original Image", img);

	cv::namedWindow("Transformed Image", cv::WINDOW_NORMAL);
	cv::imshow("Transformed Image", output);

	cv::waitKey(0);

	return 0;
}

运行结果

实验代码3

cpp 复制代码
#include "pch.h"
#include <iostream>
#include<opencv2/opencv.hpp>
using namespace cv;  //所有opencv类都在命名空间cv下
using namespace std;
//#pragma comment(lib, "opencv_world450d.lib")  //引用引入库 
 

int main()
{
	Mat src;
	src = imread("018.jpeg");
	if(src.empty()) //检验是否成功导入数据;
	{
		cout<<"not open successed!" <<endl;
		return -1;
	}
	//namedWindow("input",0);
	namedWindow("原图", WINDOW_NORMAL);

	imshow("原图",src); // 显示输入的图像src;
	cvtColor(src, src, COLOR_RGB2GRAY);
	Mat grayimg;
	grayimg.create(src.size(),src.type()); //创建一个大小类型相同的图像矩阵序列,也可以用clone()函数;
	int height = src.rows;
	int width = src.cols;
	for(int i=0;i<height;i++)
		for(int j=0;j<width;j++)
		{
			int gray = src.at<uchar>(i,j);
			grayimg.at<uchar>(i,j) = pow(gray, 0.5);//将灰度值开方;
		}
	normalize(grayimg,grayimg,0,255,NORM_MINMAX);//归一化,将数据归一到0-255之间;
	
	namedWindow("目标图像", WINDOW_NORMAL);
	imshow("目标图像",grayimg);//显示图像grayimg;
	waitKey(0);
	return 0;
}
 

运行结果3

相关推荐
晨间晓3 小时前
图片里的高频和低频是什么?用华为云码道开发 OpenCV 傅里叶频谱分析工具
opencv·计算机视觉·华为云
晨间晓3 小时前
图片里的阴影能不能减弱?用华为云码道开发 OpenCV 光照校正工具
人工智能·opencv·华为云
晨间晓18 小时前
图片里的细小噪点怎么平滑?用华为云码道开发 OpenCV 图像滤波对比工具
人工智能·opencv·华为云
偷吃米饭21 小时前
图片特征怎么描述?用华为云码道开发 OpenCV ORB 特征提取工具
人工智能·opencv·华为云
晨间晓1 天前
图片里的关键点怎么找?用华为云码道开发 OpenCV FAST 特征点检测工具
人工智能·opencv·华为云
晨间晓1 天前
二值图里的噪点怎么去掉?用华为云码道开发 OpenCV 形态学操作工具
人工智能·opencv·华为云
晨间晓1 天前
图片里的角点在哪里?用华为云码道开发 OpenCV Harris 角点检测工具
人工智能·opencv·华为云
晨间晓1 天前
图片细节丰富不丰富?用华为云码道开发 OpenCV 纹理复杂度分析工具
人工智能·opencv·华为云
richard_yuu2 天前
OpenCV 实战第 15 篇:G-API 图计算,工业流水线的 CPU/GPU 混合执行
人工智能·opencv·计算机视觉
老唐7772 天前
OpenCV5实测:纯CPU跑YOLO26目标检测
图像处理·人工智能·opencv·yolo·目标检测·计算机视觉