opencv warpAffine()函数详解 -- 图像旋转与平移

简述

仿射变换是二维坐标间的线性变换,故而变换后的图像仍然具有原图的一些性质,包括“平直性”以及“平行性”,常用于图像翻转(Flip)、旋转(Rotations)、平移(Translations)、缩放(Scale operations)等,然而其实现的函数就是cv::warpAffine()

下面我们将对warpAffine()函数进行介绍,并且实现图像的旋转和平移。

warpAffine()--官网介绍

warpAffine

Applies an affine transformation to an image.

C++: void warpAffine(InputArray src, OutputArray dst, InputArray M, Size dsize, int flags=INTER_LINEAR, int borderMode=BORDER_CONSTANT, const Scalar& borderValue=Scalar())

Python: cv2.warpAffine(src, M, dsize[, dst[, flags[, borderMode[, borderValue]]]]) → dst

C: void cvWarpAffine(const CvArr* src, CvArr* dst, const CvMat* mapMatrix, int flags=CV_INTER_LINEAR+CV_WARP_FILL_OUTLIERS, CvScalar fillval=cvScalarAll(0) )

Python: cv.WarpAffine(src, dst, mapMatrix, flags=CV_INTER_LINEAR+CV_WARP_FILL_OUTLIERS, fillval=(0, 0, 0, 0)) → None

C: void cvGetQuadrangleSubPix(const CvArr* src, CvArr* dst, const CvMat* mapMatrix)

Python: cv.GetQuadrangleSubPix(src, dst, mapMatrix) → None

Parameters:
  • src – Source image.
  • dst – Destination image that has the size dsize and the same type as src .
  • M – 2\times 3 transformation matrix.
  • dsize – Size of the destination image.
  • flags – Combination of interpolation methods (see resize() ) and the optional flag WARP_INVERSE_MAP that means that M is the inverse transformation ( \texttt{dst}\rightarrow\texttt{src} ).
  • borderMode – Pixel extrapolation method (see borderInterpolate() ). When borderMode=BORDER_TRANSPARENT , it means that the pixels in the destination image corresponding to the “outliers” in the source image are not modified by the function.
  • borderValue – Value used in case of a constant border. By default, it is 0.

The function warpAffine transforms the source image using the specified matrix:

\texttt{dst} (x,y) =  \texttt{src} ( \texttt{M} _{11} x +  \texttt{M} _{12} y +  \texttt{M} _{13}, \texttt{M} _{21} x +  \texttt{M} _{22} y +  \texttt{M} _{23})

when the flag WARP_INVERSE_MAP is set. Otherwise, the transformation is first inverted with invertAffineTransform() and then put in the formula above instead of M . The function cannot operate in-place.

由此可看出dst的计算公式:\texttt{dst} (x,y) =  \texttt{src} ( \texttt{M} _{11} x +  \texttt{M} _{12} y +  \texttt{M} _{13}, \texttt{M} _{21} x +  \texttt{M} _{22} y +  \texttt{M} _{23}) 

图像的旋转

主要步骤:

1、根据旋转角度和旋转中心获取旋转矩阵;

2、根据旋转矩阵进行仿射变换,即可实现任意角度和任意中心的旋转效果。

旋转矩阵的形式如下:

其中,

代码:

cv::Mat src = cv::imread("lenna.jpg");
cv::Mat dst;

//旋转角度
double angle = 45;

cv::Size src_sz = src.size();
cv::Size dst_sz(src_sz.height, src_sz.width);
int len = std::max(src.cols, src.rows);

//指定旋转中心
cv::Point2f center(len / 2., len / 2.);

//获取旋转矩阵(2x3矩阵)
cv::Mat rot_mat = cv::getRotationMatrix2D(center, angle, 1.0);

//根据旋转矩阵进行仿射变换
cv::warpAffine(src, dst, rot_mat, dst_sz);

//显示旋转效果
cv::imshow("image", src);
cv::imshow("result", dst);

cv::waitKey(0);

return 0;

 旋转结果显示:

图像的平移

主要步骤:

1、定义好图像的平移矩阵;

2、分别指定x方向和y方向上的平移量tx和ty。

平移矩阵的形式如下:

目标值dst计算公式已经在上面介绍过了。

代码:

cv::Mat src = cv::imread("lenna.jpg");
cv::Mat dst;

cv::Size dst_sz = src.size();

//定义平移矩阵
cv::Mat t_mat =cv::Mat::zeros(2, 3, CV_32FC1);

t_mat.at<float>(0, 0) = 1;
t_mat.at<float>(0, 2) = 20; //水平平移量
t_mat.at<float>(1, 1) = 1;
t_mat.at<float>(1, 2) = 10; //竖直平移量

//根据平移矩阵进行仿射变换
cv::warpAffine(src, dst, t_mat, dst_sz);

//显示平移效果
cv::imshow("image", src);
cv::imshow("result", dst);

cv::waitKey(0);

return 0;

平移结果显示:

<think>好的,我现在要解决用户在IAR编译器中遇到的错误:“incomplete type is not allowed”。首先,我需要理解这个错误的含义和常见原因。根据我的知识库,这个错误通常发生在代码中使用了未完全定义的类型,比如结构体或联合体声明了但未定义,或者前向声明了某个类型但没有提供完整的定义。 首先,我应该检查用户代码中是否有结构体或联合体的声明但没有定义的情况。比如,如果有一个结构体声明为`struct MyStruct;`,但没有后续的完整定义,那么在需要该结构体大小或成员的地方,编译器就会报这个错误。这时候,需要用户补全结构体的定义,包括成员变量。 其次,检查是否在头文件中只声明了类型而没有包含定义。例如,如果在头文件中使用前向声明,但在使用该类型的源文件中没有包含实际的定义头文件,这也会导致错误。此时,需要确保在使用类型的地方包含了正确的头文件,或者将前向声明替换为完整的定义。 另外,还要考虑typedef的问题。如果用户使用了typedef创建别名,但原始类型未完全定义,同样会引发错误。例如,`typedef struct MyStruct MyType;`之后,如果尝试使用MyType但MyStruct尚未定义,就会出错。需要确保在使用typedef之前,原始类型已经被完整定义。 此外,数组声明中的类型不完整也是一个常见原因。比如声明数组时,如果元素类型未完全定义,编译器无法确定数组的大小,导致错误。需要检查数组声明中的类型是否已经完整定义。 可能还有其他情况,比如在C和C++混合编程时,如果没有正确使用extern "C",或者在头文件中遗漏了必要的包含,也可能导致类型不完整。需要用户检查这些方面。 接下来,我需要将这些可能的原因整理成清晰的解决步骤,并给出具体的代码示例,帮助用户理解如何修改。同时,根据用户提供的引用内容,虽然引用[1]和引用[2]是关于其他错误的,但用户可能希望看到类似的结构,即分点说明解决方案,并引用相关资源。 最后,生成相关问题,帮助用户进一步了解可能相关的编译错误,比如类型未定义、前向声明问题等。这样用户可以有更全面的认识,预防其他类似错误的发生。</think>### IAR编译器错误'incomplete type is not allowed'解决方案 该错误表示代码中使用了**未完全定义的类型**,编译器无法确定其内存布局或成员信息。以下是具体原因及解决方法: #### 1. 结构体/联合体未定义完整 若声明了结构体但未定义成员,在实例化时会报错: ```c struct MyStruct; // 前向声明不完整 struct MyStruct var; // 错误:使用未完成类型 ``` **解决方案**:补全类型定义 ```c struct MyStruct { int id; char name[20]; }; ``` #### 2. 头文件包含缺失 当跨文件使用类型时,需确保定义可见: ```c // file.h struct Data; // 前向声明 // file.c struct Data { // 实际定义 int value; }; ``` **解决方案**:在使用该类型的文件中包含定义头文件 ```c #include "file.c" // 包含实际定义 ``` #### 3. typedef别名问题 使用typedef时原始类型必须完整: ```c typedef struct Node NodeT; // 前向声明 NodeT* ptr; // 允许指针声明 NodeT instance; // 错误:不完整类型 ``` **解决方案**:先完成类型定义再typedef ```c struct Node { int data; struct Node* next; }; typedef struct Node NodeT; ``` #### 4. 数组声明不完整 数组元素类型必须完全定义: ```c struct Element; struct Element arr[10]; // 错误:元素类型未定义 ``` **解决方案**: ```c struct Element { int type; float value; }; struct Element arr[10]; // 合法 ``` #### 调试建议 1. 在IAR工程中搜索错误行号定位问题代码 2. 使用Go to Definition功能追踪类型定义 3. 检查所有头文件包含链 4. 确认没有循环依赖的头文件 编译器需要知道类型的完整信息才能: - 计算sizeof大小 - 分配内存空间 - 访问成员变量 - 进行类型对齐 [^1]: 类似类型转换错误可参考浮点转整型的类型适配问题。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值