opencv C艹:图像拼接,尺寸变换,仿射,透视,极坐标变换

图像变换

调整图像尺寸,翻转,旋转

图像拼接

将两个具有相同高度或宽度的图像连接一起,

纵向拼接
void cv::vconcat	(	const Mat * 	src,  // 存放Mat类型的数组,列数相同,数据类型通道数相同
						size_t 	nsrc,  // 数组中含有的Mat类型的数目,
						OutputArray 	dst  // 输出结果
)

void cv::vconcat	(	InputArray 	src1,  // 对两个Mat类型的数据进行连接。
InputArray 	src2,
OutputArray 	dst 
)

横向拼接
void cv::hconcat	(	const Mat * 	src,
						size_t 	nsrc,
						OutputArray 	dst 
)

void cv::hconcat	(	InputArray 	src1,  // 
InputArray 	src2,
OutputArray 	dst 
)	


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

using namespace std;
using namespace cv;

int main()
{
	//矩阵数组的横竖连接
	Mat matArray[] = { Mat(1, 2, CV_32FC1, cv::Scalar(1)),  
								  Mat(1, 2, CV_32FC1, cv::Scalar(2)) };
	Mat vout, hout;
	vconcat(matArray, 2, vout);
	cout << "图像数组竖向连接:" << endl << vout << endl;
	hconcat(matArray, 2, hout);
	cout << "图像数组横向连接:" << endl << hout << endl;

	//矩阵的横竖拼接
	Mat A = (cv::Mat_<float>(2, 2) << 1, 7, 2, 8);
	Mat B = (cv::Mat_<float>(2, 2) << 4, 10, 5, 11);
	Mat vC, hC;
	vconcat(A, B, vC);
	cout << "多个图像竖向连接:" << endl << vC << endl;
	hconcat(A, B, hC);
	cout << "多个图像横向连接:" << endl << hC << endl;

	//读取4个子图像,00表示左上角、01表示右上角、10表示左下角、11表示右下角
	Mat img00 = imread("lena00.png");
	Mat img01 = imread("lena01.png");
	Mat img10 = imread("lena10.png");
	Mat img11 = imread("lena11.png");
	if (img00.empty() || img01.empty() || img10.empty() || img11.empty())
	{
		cout << "请确认图像文件名称是否正确" << endl;
		return -1;
	}
	//显示4个子图像
	imshow("img00", img00);
	imshow("img01", img01);
	imshow("img10", img10);
	imshow("img11", img11);

	//图像连接
	Mat img, img0, img1;
	//图像横向连接
	hconcat(img00, img01, img0);
	hconcat(img10, img11, img1);
	//横向连接结果再进行竖向连接
	vconcat(img0, img1, img);

	//显示连接图像的结果
	imshow("img0", img0);
	imshow("img1", img1);
	imshow("img", img);
	waitKey(0);
	return 0;
}

尺寸变换

改变长和宽,实现图像的缩放。


void cv::resize	(	InputArray 	src,
					OutputArray 	dst,
					Size 	dsize,   // 输出图像的尺寸
					double 	fx = 0,  // 水平的比例因子,两倍就是2
					double 	fy = 0,  // 以dsize为准
					int 	interpolation = INTER_LINEAR  // 插值方法
)	

在这里插入图片描述
缩小图像,用INTER_AREA , 放大图像 INTER_CUBIC OR INTER_LINEAR。

void cv::flip(InputArray src, // 图像翻转
			OutputArray dst,
			int flipCode // 大于0 ,y轴翻转 ,等于0 x轴翻转, 小于0两个轴翻转
			}

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

using namespace std;
using namespace cv;

int main()
{
	Mat gray = imread("lena.png", 0);
	Mat smallImg, bigImg0, bigImg1, bigImg2;
	resize(gray, smallImg, Size(15, 15), 0, 0, INTER_AREA);  // 先缩小
	resize(smallImg, bigImg0, Size(30, 30), 0, 0, INTER_NEAREST);  //最近邻差值
	resize(smallImg, bigImg1, Size(30, 30), 0, 0, INTER_LINEAR);  //双线性差值
	resize(smallImg, bigImg2, Size(30, 30), 0, 0, INTER_CUBIC);  //双三次差值
	namedWindow("smallImg", 0);  //图像尺寸太小,一定要设置可以调节窗口大小标志
	imshow("smallImg", smallImg);
	namedWindow("bigImg0", 0);
	imshow("bigImg0", bigImg0);
	namedWindow("bigImg1", 0);
	imshow("bigImg1", bigImg1);
	namedWindow("bigImg2", 0);
	imshow("bigImg2", bigImg2);

	Mat img_x, img_y, img_xy;
	flip(gray, img_x, 0);       // 图像翻转,x, y, xy轴对称
	flip(gray, img_y, 1);
	flip(gray, img_xy, -1);
	imshow("img_xy", img_xy);
	
	waitKey(0);
	return 0;
}

图像放射变换

图像的旋转,通过仿射实现。首先确定旋转角度和中心,确定旋转矩阵,进行仿射变换。

Mat cv::getRotationMatrix2D	(	Point2f 	center, // 旋转中心位置
								double 	angle, // 角度,单位度,正值逆时针旋转
								double 	scale  // 两个轴的比例因子,实现图像的缩放
)	// 返回旋转矩阵,Mat类型

在这里插入图片描述
得到旋转矩阵后,通过warpAffine() 函数进行仿射变换,实现旋转。


void cv::warpAffine	(	InputArray 	src,
						OutputArray 	dst,  // 结果图,类型与输入相同,尺寸与dsize相同
						InputArray 	M,  // 得到的旋转矩阵
						Size 	dsize,
						int 	flags = INTER_LINEAR, // 插值方式
						int 	borderMode = BORDER_CONSTANT, //像素边界外推方式
						const Scalar & 	borderValue = Scalar() // 填充边界的值,默认0
)	

在这里插入图片描述
仿射变换就是旋转,平移,缩放操作的总称,可以表示为线性变换和平移变换的叠加。数学表达就是先乘以一个线性变换矩阵(2 X 2),然后加上一个平移向量(2X1)。所以输入一个(2X3)的变换矩阵。

M = [ A B ] = ∣ a 00 a 01 b 00 a 10 a 11 b 10 ∣ 像 素 值 [ x , y ] T T = A [ x y ] + B M = [A\quad B]= \left\vert\begin{matrix} a_{00} & a_{01} & b_{00} \\ a_{10} & a_{11} & b_{10} \end{matrix} \right\vert 像素值[x,y]^T \qquad T = A\left[\begin{matrix}x\\y\end{matrix}\right] + B M=[AB]=a00a10a01a11b00b10[x,y]TT=A[xy]+B

如果知道变换后两幅图像中3个像素点坐标的对应关系,就可以求得变换矩阵M,getAffineTransform()利用三个对应的像素点确定M。


Mat cv::getAffineTransform	(	const Point2f 	src[], // 原图像的3个像素坐标,与顺序无关
								const Point2f 	dst[] 
)	


int main()
{
	Mat img = imread("lena.png");

	Mat rotation0, rotation1, img_warp0, img_warp1;
	double angle = 30;  //设置图像旋转的角度
	Size dst_size(img.rows, img.cols);  //设置输出图像的尺寸
	Point2f center(img.rows / 2.0, img.cols / 2.0);  //设置图像的旋转中心
	rotation0 = getRotationMatrix2D(center, angle, 1);  //计算放射变换矩阵
	warpAffine(img, img_warp0, rotation0, dst_size);  //进行仿射变换
	imshow("img_warp0", img_warp0);
	//根据定义的三个点进行仿射变换
	Point2f src_points[3];
	Point2f dst_points[3];
	src_points[0] = Point2f(0, 0);  //原始图像中的三个点,三个角
	src_points[1] = Point2f(0, (float)(img.cols - 1));
	src_points[2] = Point2f((float)(img.rows - 1), (float)(img.cols - 1));
	dst_points[0] = Point2f((float)(img.rows)*0.11, (float)(img.cols)*0.20);  //放射变换后图像中的三个点
	dst_points[1] = Point2f((float)(img.rows)*0.15, (float)(img.cols)*0.70);
	dst_points[2] = Point2f((float)(img.rows)*0.81, (float)(img.cols)*0.85);
	rotation1 = getAffineTransform(src_points, dst_points);  //根据对应点求取仿射变换矩阵
	warpAffine(img, img_warp1, rotation1, dst_size);  //进行仿射变换
	imshow("img_warp1", img_warp1);
	waitKey(0);
	return 0;
}

透视变换

将物体投影到新的平面。透视前后的变换关系可以使用一个 3X3 的变换矩阵表示,这个矩阵可以通过两幅图像中4 个对应点的坐标求取。getPerspectiveTransform() warpPerspective() 分别用于获取矩阵,进行透视变换。



Mat cv::getPerspectiveTransform	(	const Point2f 	src[],
									const Point2f 	dst[],
									int 	solveMethod = DECOMP_LU // 默认就行
)		


void cv::warpPerspective	(	InputArray 	src,
								OutputArray 	dst,
								InputArray 	M,   // 3X3的变换矩阵
								Size 	dsize,   // 输出图像的尺寸
								int 	flags = INTER_LINEAR,  // 与仿射参数一样
								int 	borderMode = BORDER_CONSTANT,
								const Scalar & 	borderValue = Scalar() 
)	
	Point2f src_points[4];
	Point2f dst_points[4];
	//通过Image Watch查看的二维码四个角点坐标
	src_points[0] = Point2f(94.0, 374.0);
	src_points[1] = Point2f(507.0, 380.0);
	src_points[2] = Point2f(1.0, 623.0);
	src_points[3] = Point2f(627.0, 627.0);
	//期望透视变换后二维码四个角点的坐标
	dst_points[0] = Point2f(0.0, 0.0);
	dst_points[1] = Point2f(627.0, 0.0);
	dst_points[2] = Point2f(0.0, 627.0);
	dst_points[3] = Point2f(627.0, 627.0);
	Mat rotation, img_warp;
	rotation = getPerspectiveTransform(src_points, dst_points);  //计算透视变换矩阵
	warpPerspective(img, img_warp, rotation, img.size());  //透视变换投影

极坐标变换

直角坐标系和极坐标系中的变换,可以将一个圆形图像变成一个矩形图像。可以处理钟表,圆盘等,圆形图案边缘上的文字经过极坐标变换后可以垂直的排列在新图像的边缘,便于对文字进行识别和检测。


void cv::warpPolar	(	InputArray 	src,
						OutputArray 	dst,
						Size 	dsize,
						Point2f 	center,  // 极坐标的原点坐标
						double 	maxRadius, // 变换时边界圆的半径,决定了逆变换时的比例参数
						int 	flags // 插值方法,与极坐标映射方法标志,两个方法通过+ |连接
)	

在这里插入图片描述

int main()
{
	Mat img = imread("dial.png");

	Mat img1, img2;
	Point2f center = Point2f(img.cols / 2, img.rows / 2);  //极坐标在图像中的原点
	//正极坐标变换
	warpPolar(img, img1, Size(300, 600), center, center.x, INTER_LINEAR + WARP_POLAR_LINEAR);
	//逆极坐标变换
	warpPolar(img1, img2, Size(img.rows, img.cols), center, center.x, 
				INTER_LINEAR + WARP_POLAR_LINEAR + WARP_INVERSE_MAP);

	imshow("原表盘图", img);
	imshow("表盘极坐标变换结果", img1);
	imshow("逆变换结果", img2);
	waitKey(0);
	return 0;
}

在这里插入图片描述

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要使用OpenCV进行仿射变换校正图像,可以按照以下步骤进行操作。首先,使用cv.warpAffine函数对需要处理的图像进行仿射变换。该函数需要传入参数为:需要处理的图像、旋转变换矩阵、宽高、插值方法和边界填充方式。其中旋转变换矩阵可以通过找到最小矩形框住对象轮廓的函数得到一个角度,然后利用这个角度得到一个旋转的矩形。最后,使用cv.warpAffine函数进行仿射变换,得到校正后的图像。具体代码如下所示: ```python import cv2 as cv # 读取图像 src = cv.imread('imageTextR.png') (h, w) = src.shape[:2] # 将图像转换为灰度图像 gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY) # 进行二值化处理 # 找到对象轮廓的最小矩形框 rect = cv.minAreaRect(contour) # 得到旋转角度 angle = rect<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [Opencv+Python 基于仿射变换进行图像倾斜矫正 实例练习 (超详细备注)](https://blog.csdn.net/qq_42969796/article/details/113448379)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *3* [图像的校正与增强之仿射变换](https://blog.csdn.net/xuzz_498100208/article/details/106041324)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值