【图像处理】OpenCV系列十八 --- 几何图像变换函数详解(
一、linearPolar()函数
1、函数原型
void linearPolar(InputArray src,
OutputArray dst,
Point2f center,
double maxRadius,
int flags);
2、函数功能
将一幅图像映射到极坐标空间中。
3、参数详解
-
第一个参数,InputArray src,原图像,即输入图像;
-
第二个参数,OutputArray dst,目标图像,与原图像有一样的尺寸与类型;
-
第三个参数,Point2f center,变换的中心坐标;
-
第四个参数,double maxRadius,逆向变换中的最大变径;
-
第五个参数,int flags,插值方法的组合。
Note:该函数不支持就地操作。
二、logPolar()函数
1、函数原型
void logPolar(InputArray src,
OutputArray dst,
Point2f center,
double M,
int flags);
2、函数功能
将图像映射到半极坐标空间;
3、参数详解
-
第一个参数,InputArray src,原图像,即输入图像;
-
第二个参数,OutputArray dst,目标图像,与原图像具有相同的尺寸和类型;
-
第三个参数,Point2f center,转换的中心坐标,其中输出的精度是最大的;
-
第四个参数,double M,图像幅度的比例参数,决定了用多大的边界圆的半径进行转换;
-
第五个参数,int flags,插值方法与映射模式的组合;
Note:该函数不支持就地操作。
三、warpPolar()函数
1、函数原型
void warpPolar(InputArray src,
OutputArray dst,
Size dsize,
Point2f center,
double maxRadius,
int flags);
2、函数功能
将一幅图像映射到极坐标或者半极坐标空间中;
具体应用的公式如下:
极坐标映射其中,
极坐标映射 极坐标映射极坐标映射与半极坐标映射的比较:
warpPolar函数的映射模式可以是极坐标映射,也可以是半极坐标映射,通过flags参数来进行指定映射的模式!系统默认的模式是极坐标映射模式。半极坐标映射用来模仿人类的中心视觉,在视觉聚焦的地方可以看的很清晰,非聚焦的地方会比较模糊,通过弱化聚焦以外的区域,来简化图像,方便对图像进行处理。
3、参数详解
-
第一个参数,InputArray src,原图像,即输入图像;
-
第二个参数,OutputArray dst,目标图像,与原图像具有相同的类型;
-
第三个参数,Size dsize,目标图像的尺寸,根据这个参数来设计目标图像的大小;
-
第四个参数,Point2f center,图像进行变换的中心坐标;
-
第五个参数,double maxRadius,要进行变换的边界圆的半径,决定了图像逆向幅度的大小;
-
第六个参数,int flags,插值的方式与极坐标变换的模式的组合;
极坐标变换的模式有以下几种:
(1)极坐标变换(WARP_POLAR_LINEAR)
(2)半极坐标变换(WARP_POLAR_LOG)
(3)对图像进行逆向映射(WARP_INVERSE_MAP)
Note:
(1)该函数不支持就地操作;
(2)为了计算角的大小和角度,内部采用了cartToPolar函数,测量角度在0到360之间,精度约为0.3度;
(3)在实现过程中,该函数使用了remap函数,因为当前的实现限制,图像的大小应小于32767x32767。
综合实例
对于linearPolar()函数与logPolar()以及warpPolar()函数的使用
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include <iostream>
using namespace cv;
int main(int argc, char** argv)
{
// 半极坐标转换图像
Mat log_polar_img,
// 极坐标转换图像
lin_polar_img,
// 逆半极坐标转换图像
recovered_log_polar,
// 逆极坐标转换图像
recovered_lin_polar_img;
// 创建窗体
namedWindow("Linear-Polar", WINDOW_AUTOSIZE);
namedWindow("Log-Polar", WINDOW_AUTOSIZE);
namedWindow("Recovered Linear-Polar", WINDOW_AUTOSIZE);
namedWindow("Recovered Log-Polar", WINDOW_AUTOSIZE);
// 移动窗口的显示位置
moveWindow("Linear-Polar", 20, 20);
moveWindow("Log-Polar", 700, 20);
moveWindow("Recovered Linear-Polar", 20, 350);
moveWindow("Recovered Log-Polar", 700, 350);
// INTER_LINEAR 线性插值
// WARP_FILL_OUTLIERS 填充所有目标图像像素。
// 如果其中一些对应于源图像中的异常值,
// 则将其设置为零。
int flags = INTER_LINEAR +
WARP_FILL_OUTLIERS;
// 加载图像
Mat src = imread("lena.png");
if (src.empty())
{
printf("image error!");
return 0;
}
// 原图像的中心坐标
Point2f center((float)src.cols / 2,
(float)src.rows / 2);
// 最大的半径
double maxRadius = 0.7*min(center.y, center.x);
// direct transform
// linear Polar
warpPolar(src,
lin_polar_img,
Size(),
center,
maxRadius,
flags);
// semilog Polar
warpPolar(src,
log_polar_img,
Size(),
center,
maxRadius,
flags + WARP_POLAR_LOG);
// inverse transform
warpPolar(lin_polar_img,
recovered_lin_polar_img,
src.size(),
center,
maxRadius,
flags + WARP_INVERSE_MAP);
// inverse transform
warpPolar(log_polar_img,
recovered_log_polar,
src.size(),
center,
maxRadius,
flags + WARP_POLAR_LOG + WARP_INVERSE_MAP);
// 从极坐标系到直角坐标系
Mat dst;
if (flags & WARP_POLAR_LOG)
dst = log_polar_img;
else
dst = lin_polar_img;
//get a point from the polar image
int rho = cvRound(dst.cols * 0.75);
int phi = cvRound(dst.rows / 2.0);
double angleRad, magnitude;
double Kangle = dst.rows / CV_2PI;
angleRad = phi / Kangle;
if (flags & WARP_POLAR_LOG)
{
double Klog = dst.cols / std::log(maxRadius);
magnitude = std::exp(rho / Klog);
}
else
{
double Klin = dst.cols / maxRadius;
magnitude = rho / Klin;
}
// 极坐标的点转换为直角坐标的点
int x = cvRound(center.x + magnitude * cos(angleRad));
int y = cvRound(center.y + magnitude * sin(angleRad));
drawMarker(src, Point(x, y), Scalar(0, 255, 0));
drawMarker(dst, Point(rho, phi), Scalar(0, 255, 0));
imshow("Src image", src);
imshow("Log-Polar", log_polar_img);
imshow("Linear-Polar", lin_polar_img);
imshow("Recovered Linear-Polar", recovered_lin_polar_img);
imshow("Recovered Log-Polar", recovered_log_polar);
waitKey(0);
return 0;
}
实验结果:
原图 极坐标变换(左)与半极坐标变换(右) 逆极坐标变换(左)与逆半极坐标变换(右)四、resize()函数
1、函数原型
void resize(InputArray src,
OutputArray dst,
Size dsize,
double fx = 0,
double fy = 0,
int interpolation =
INTER_LINEAR);
2、函数功能
对图像的尺寸进行调整,使其缩小或放大为指定的大小;
Note:
(1)如果没有考虑目标图像(dst)初始化的大小和类型,则目标图像的大小和类型由原图像(src),dsize,fx,fy等参数决定,例如:
// 指定fx,fy的值,
//由函数自动计算目标图像的大小
resize(src, dst,
Size(), 0.5, 0.5,
interpolation);
(2)预先创建dst图像的大小与类型,例如:
// 创建一个800x600的8位单通道的图像
Mat dst(800, 600, CV_8UC1);
resize(src, dst, dst.size(), 0, 0, interpolation);
3、参数详解
-
第一个参数,InputArray src,原图,即输入图像;
-
第二个参数,OutputArray dst,目标图像,其类型与原图像一致,尺寸可以进行自定义设置,或者通过参数src.size(),fx,fy等参数自动计算出来;
-
第三个参数,Size dsize,目标图像的尺寸;
如果dsize等于0,则dsize用以下的公式计算:
需要满足dsize或者fx,fy都不为0;
- 第四个参数,double fx = 0,
fx,水平方向的尺寸因子,如果fx=0,则通过下面的公式计算fx:
fx- 第五个参数,double fy = 0,
fy,垂直方向的尺寸因子,如果fy=0,则通过下面的公式计算fy:
fy- 第六个参数,int interpolation =INTER_LINEAR,默认的插值方式位线性插值;
常见的插值方式:
常见的插值方式五、remap()函数
1、函数原型
void remap(InputArray src,
OutputArray dst,
InputArray map1,
InputArray map2,
int interpolation,
int borderMode = BORDER_CONSTANT,
const Scalar& borderValue = Scalar());
2、函数功能
对图像进行几何变换;
3、参数详解
-
第一个参数,InputArray src,原图像,即输入图像;
-
第二个参数,OutputArray dst,目标图像,图像的尺寸的大小与map1相同,图像的类型与原图像一致;
-
第三个参数,InputArray map1, (x,y)点或仅x值的第一个映射,其类型为CV_16SC2、CV_32FC1或CV_32FC2;有关将浮点表示形式转换为固定点以提高速度的详细信息,可以看我上一节所讲的convertMaps函数;
-
第四个参数,InputArray map2,y值的第二个映射,其类型分别为CV_16UC1、CV_32FC1或None(如果map1为(x,y)点,则为空映射);
-
第五个参数,int interpolation,插值的方法,这个函数不支持INTER_AREA插值;
-
第六个参数,int borderMode = BORDER_CONSTANT,边界模式;当边界模式为BORDER_TRANSPARENT时,源图像中的“异常值”的像素在目标图像中不会被函数修改;
-
第七个参数,const Scalar& borderValue = Scalar(), 在常量边界情况下使用的边值;默认情况下,它是0。
六、warpAffine()函数
1、函数原型
void warpAffine(InputArray src,
OutputArray dst,
InputArray M,
Size dsize,
int flags = INTER_LINEAR,
int borderMode = BORDER_CONSTANT,
const Scalar& borderValue = Scalar());
2、函数功能
用指定的卷积核对图像进行仿射变换;
当flag为WARP_INVERSE_MAP时,使用的公式如下:
否则,使用invertAffineTransform函数先进性逆仿射变换,然后用上面的公式代替M;并且该函数不支持就地操作!
3、参数详解
-
第一个参数,InputArray src,原图像,即输入图像;
-
第二个参数,OutputArray dst,目标图像,与原图像具有同样的尺寸与类型;
-
第三个参数,InputArray M,2 x 3的变换矩阵;
-
第四个参数,Size dsize,目标的图像的尺寸大小,根据这个参数来指定目标图像的大小;
-
第五个参数,int flags = INTER_LINEAR,插值的方法,以及可选择的WARP_INVERSE_MAP(使用这个方式,则M是逆仿射变换);
-
第六个参数,int borderMode = BORDER_CONSTANT,边界模式,当边界模式为BORDER_TRANSPARENT时,源图像中的“异常值”的像素在目标图像中不会被函数修改;
-
第七个参数,const Scalar& borderValue = Scalar(), 在常量边界情况下使用的边值;默认情况下,它是0。
七、warpPerspective()函数
1、函数原型
void warpPerspective(InputArray src,
OutputArray dst,
InputArray M,
Size dsize,
int flags = INTER_LINEAR,
int borderMode = BORDER_CONSTANT,
const Scalar& borderValue = Scalar());
2、函数功能
用指定的卷积核对图像进行透视变换;
当flags设置为WARP_INVERSE_MAP时,使用以下的卷积对图像进行透视变换,
透视变换否则,先使用逆变换进行转置,然后用上面的公式代替M,并且此函数不支持就地操作;
3、参数详解
-
第一个参数,InputArray src,原图,即目标图像;
-
第二个参数,OutputArray dst,目标图像,与原图具有同样的尺寸和类型;
-
第三个参数,InputArray M,3 x 3的转换矩阵;
-
第四个参数,Size dsize,目标图像的大小,根据这个参数来设计目标图像的大小;
-
第五个参数,int flags = INTER_LINEAR,将常用的插值方法(INTER_LINEAR、 INTER_NEAREST)与可选标志(WARP_INVERSE_MAP)进行组合,如果与可选标志结合的话,将M设置为逆变换(dst --> src);
-
第六个参数,int borderMode = BORDER_CONSTANT,边界模式(BORDER_CONSTANT、BORDER_REPLICATE);
-
第七个参数,const Scalar& borderValue = Scalar(), 在常量边界情况下使用的边值;默认情况下,它是0。
我是奕双,现在已经毕业将近两年了,从大学开始学编程,期间学习了C需要编程,C++需要编程,Win32编程,MFC编程,毕业之后进入一家图像处理相关领域的公司,掌握了用OpenCV对图像进行处理,如果大家对相关领域感兴趣的话,可以关注我,我这边会为大家进行解答哦!如果大家需要相关学习资料的话,可以私聊我哦!