OpenCV学习13_仿射变换与直方图均衡

一、仿射变换

仿射变换(Affine Transformation或Affine Map),又称仿射映射,是指在几何中,一个向量空间进行一次线性变换并接上一个平移,变换为另一个向量空间的过程。它保持了二维图形的“平直性”(直线经过变换之后依然是直线)和“平行性”(二维图形之间的相对位置关系保持不变,平行线依然是平行线,且直线上点的位置顺序不变)。

一个任意的仿射变换都能表示为乘以一个矩阵(线性变换)接着再加上一个向量(平移)的形式。

那么,我们能够用仿射变换来表示如下三种常见的变换形式:

  • 旋转, rotation (线性变换)
  • 平移, translation(向量加)
  • 缩放, scale(线性变换)

进行更深层次的理解,仿射变换代表的是两幅图之间的一种映射关系。而我们通常使用2x3的矩阵来表示仿射变换。

OpenCV仿射变换相关的函数一般涉及到warpAffine和getRotationMatrix2D·这两个函数:

  • 使用OpenCV函数warpAfine来实现一些简单的重映射。
  • 使用OpenCV函数getRotationMatrix2D来获得旋转矩阵。

1.1 warpAfine()函数

warpAffine函数的作用是依据以下公式子,对图像做仿射变换。
在这里插入图片描述

函数原型如下。

C++: void warpAffine (InputArray src,OutputArray dst, InputArray M, Size dsize, int flags=INTER_LINEAR, intborderMode=BORDER_CONSTANT, const Scalar& borderValue=Scalar() )
  • 第一个参数, InputArray类型的src,输入图像,即源图像,填Mat类的对象即可
  • 第二个参数, OutputArray类型的dst,函数调用后的运算结果存在这里,需和源图片有一样的尺寸和类型。
  • 第三个参数, InputArray类型的M, 2x3的变换矩阵。
  • 第四个参数, Size类型的dsize,表示输出图像的尺寸。
  • 第五个参数, int类型的flags,插值方法的标识符。此参数有默认值INTER_LINEAR(线性插值),可选的插值方式如下所示。
    在这里插入图片描述
  • 第六个参数, int类型的borderMode ,边界像素模式,默认值为BORDER_CONSTANT
  • 第七个参数, const Scalar&类型的borderValue,在恒定的边界情况下取的值,默认值为Scalar(),即0。

1.2 getRotationMatrix2D()函数

getRotationMatrix2D()函数用于计算二维旋转变换矩阵。变换会将旋转中心映射到它自身。

C++: Mat qetRotationMatrix2D (Point2fcenter, double angle, double scale)
  • 第一个参数, Point2f类型的center,表示源图像的旋转中心。
  • 第二个参数, double类型的angle,旋转角度。角度为正值表示向逆时针旋转(坐标原点是左上角)。
  • 第三个参数, double类型的scale,缩放系数。

此函数计算以下矩阵:
在这里插入图片描述
其中,
在这里插入图片描述

1.3 示例

int main()
{
	//【0】改变console字体颜色
	system("color 1F");

	//【1】参数准备
	//定义两组点,代表两个三角形
	Point2f srcTriangle[3];
	Point2f dstTriangle[3];
	//定义一些Mat变量
	Mat rotMat(2, 3, CV_32FC1);
	Mat warpMat(2, 3, CV_32FC1);
	Mat srcImage, dstImage_warp, dstImage_warp_rotate;

	//【2】加载源图像并作一些初始化
	srcImage = imread("F:\\CV\\LearnCV\\files\\Zelda.jpg",1);
	if (!srcImage.data) { printf("读取图片错误,请确定目录下是否有imread函数指定的图片存在~! \n"); return false; }
	// 设置目标图像的大小和类型与源图像一致
	dstImage_warp = Mat::zeros(srcImage.rows, srcImage.cols, srcImage.type());

	//【3】设置源图像和目标图像上的三组点以计算仿射变换
	srcTriangle[0] = Point2f(0, 0);
	srcTriangle[1] = Point2f(static_cast<float>(srcImage.cols - 1), 0);
	srcTriangle[2] = Point2f(0, static_cast<float>(srcImage.rows - 1));

	dstTriangle[0] = Point2f(static_cast<float>(srcImage.cols*0.0), static_cast<float>(srcImage.rows*0.33));
	dstTriangle[1] = Point2f(static_cast<float>(srcImage.cols*0.65), static_cast<float>(srcImage.rows*0.35));
	dstTriangle[2] = Point2f(static_cast<float>(srcImage.cols*0.15), static_cast<float>(srcImage.rows*0.6));

	//【4】求得仿射变换
	warpMat = getAffineTransform(srcTriangle, dstTriangle);

	//【5】对源图像应用刚刚求得的仿射变换
	warpAffine(srcImage, dstImage_warp, warpMat, dstImage_warp.size());

	//【6】对图像进行缩放后再旋转
	// 计算绕图像中点顺时针旋转50度缩放因子为0.6的旋转矩阵
	Point center = Point(dstImage_warp.cols / 2, dstImage_warp.rows / 2);
	double angle = -50.0;
	double scale = 0.6;
	// 通过上面的旋转细节信息求得旋转矩阵
	rotMat = getRotationMatrix2D(center, angle, scale);
	// 旋转已缩放后的图像
	warpAffine(dstImage_warp, dstImage_warp_rotate, rotMat, dstImage_warp.size());


	//【7】显示结果
	imshow(WINDOW_NAME1, srcImage);
	imshow(WINDOW_NAME2, dstImage_warp);
	imshow(WINDOW_NAME3, dstImage_warp_rotate);

	// 等待用户按任意按键退出程序
	waitKey(0);

	return 0;
}

在这里插入图片描述

二、直方图均衡化

很多时候,我们用相机拍摄的照片的效果往往会不尽人意。这时,可以对这·些图像进行一些处理,来扩大图像的动态范围。这种情况下最常用到的技术就是直方图均衡化。

直方图均衡化是灰度变换的一个重要应用,它高效且易于实现,广泛应用于,图像增强处理中。图像的像素灰度变化是随机的,直方图的图形高低不齐,直方图均衡化就是用一定的算法使直方图大致平和的方法。

简而言之,直方图均衡化是通过拉伸像素强度分布范围来增强图像对比度的一种方法。

均衡化处理后的图像只能是近似均匀分布。均衡化图像的动态范围扩大了,但其本质是扩大了量化间隔,而量化级别反而减少了,因此,原来灰度不同的象素经处理后可能变的相同,形成了一片相同灰度的区域,各区域之间有明显的边界,从而出现了伪轮廓。在原始图像对比度本来就很高的情况下,如果再均衡化则灰度调和,对比度会降低。在泛白缓和的图像中,均衡化会合并一些象素灰度,从而增大对比度。均衡化后的图片如果再对其均衡化,则图像不会有任何变化。

2.1 equalizeHist()函数

在OpenCV中,直方图均衡化的功能实现由equalizeHist函数完成。我们一起看看它的函数描述。

C++: void equalizeHist (InputArray src, OutputArray dst)
  • 第一个参数, InputArray类型的src,输入图像,即源图像,填Mat类的对象即可,需为8位单通道的图像。
  • 第二个参数, OutputArray类型的dst,函数调用后的运算结果存在这里,需和源图片有一样的尺寸和类型。

采用如下步骤对输入图像进行直方图均衡化。
1)计算输入图像的直方图H。
2)进行直方图归一化,直方图的组距的和为255
3)计算直方图积分:
在这里插入图片描述
4)以H作为查询表进行图像变换:
在这里插入图片描述
言而言之,由equalizeHist函数实现的灰度直方图均衡化算法,就是把直方图的每个灰度级进行归一化处理,求每种灰度的累积分布,得到一个映射的灰度,映射表,然后根据相应的灰度值来修正原图中的每个像素。

2.2 示例


int main()
{
	// 【1】加载源图像
	Mat srcImage, dstImage;
	srcImage = imread("F:\\CV\\LearnCV\\files\\Zelda_Scene.jpg");
	if (!srcImage.data) { return false; }

	// 【2】转为灰度图并显示出来
	cvtColor(srcImage, srcImage, COLOR_BGR2GRAY);
	imshow("原始图", srcImage);

	// 【3】进行直方图均衡化
	equalizeHist(srcImage, dstImage);

	// 【4】显示结果
	imshow("经过直方图均衡化后的图", dstImage);

	// 等待用户按键退出程序
	waitKey(0);
	return 0;

}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值