IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 人工智能 -> opencv C艹:图像拼接,尺寸变换,仿射,透视,极坐标变换 -> 正文阅读

[人工智能]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]=?a00?a10??a01?a11??b00?b10???[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;
}

在这里插入图片描述

  人工智能 最新文章
2022吴恩达机器学习课程——第二课(神经网
第十五章 规则学习
FixMatch: Simplifying Semi-Supervised Le
数据挖掘Java——Kmeans算法的实现
大脑皮层的分割方法
【翻译】GPT-3是如何工作的
论文笔记:TEACHTEXT: CrossModal Generaliz
python从零学(六)
详解Python 3.x 导入(import)
【答读者问27】backtrader不支持最新版本的
上一篇文章      下一篇文章      查看所有文章
加:2021-08-12 16:36:04  更:2021-08-12 16:38:40 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/27 21:02:32-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码