二、图像的几何变换
1、 图像缩放
图像缩放需要使用插值,图像插值通常有三种方式:最近邻插值、双线性插值、双立方插值。
OpenCV提供的函数:
函数
IplImage* cvCreateImage(CvSize size,int depth,int channels)
创建一幅图像并返回存储图像的首地址。
参数CvSize cvSize( int width, int height )
图像的高宽
参数depth
,表示图像的量化深度
#define IPL_DEPTH_1U 1
#define IPL_DEPTH_8U 8
#define IPL_DEPTH_16U 16
#define IPL_DEPTH_32F 32
#define IPL_DEPTH_8S (IPL_DEPTH_SIGN| 8)
#define IPL_DEPTH_16S (IPL_DEPTH_SIGN|16)
#define IPL_DEPTH_32S (IPL_DEPTH_SIGN|32)
参数 channels 表示图像的通道
函数 void cvResize( const CvArr* src, CvArr* dst, int interpolation CV_DEFAULT( CV_INTER_LINEAR ))
参数 src
原图像首地址
参数 dst
目的图像首地址
参数 interpolation
表示缩放的插值方式
CV_INTER_NN =0, 最近邻插值
CV_INTER_LINEAR =1, 双线性插值
CV_INTER_CUBIC =2, 立方插值
CV_INTER_AREA =3, 基于像素区域关系
CV_INTER_LANCZOS4 =4 兰索斯插值
代码如下:
IplImage* dst = cvCreateImage(cvSize(nWidth, nHeight), IPL_DEPTH_8U, 3);
cvResize(m_ipl, dst, CV_INTER_LINEAR);
cvNamedWindow("缩放后图像");
cvShowImage("缩放后图像", dst);
cvWaitKey(0);
cvReleaseImage(&dst);
2、图像旋转
图像的几何变换可以看作原图像的每个像素点乘以一个变换矩阵:
当
表示旋转变换。
表示平移变换。
仿射变换函数(void) cvWarpAffine( const CvArr* src, CvArr* dst, const CvMat* map_matrix, int flags CV_DEFAULT(CV_INTER_LINEAR+CV_WARP_FILL_OUTLIERS), CvScalar fillval CV_DEFAULT(cvScalarAll(0)) )
参数src
表示原图像
参数 dst
表示输出图像
参数 map_matrix
表示变换矩阵;CvMat cvMat( int rows, int cols, int type, void* data CV_DEFAULT(NULL))
参数flags
默认插值方式与填充方式
参数 fillval
填充边界外的值
确定图像旋转后的外接矩形的边界大小,如下图:
注意:上述旋转变换是以左上角为中心逆时针旋转,在旋转过程中会出现图像坐标为负的情况,如下图:
解决方案:
1、 用库函数将旋转中心换至图像中心,再进行调整。
用到函数:
(CvMat*) cv2DRotationMatrix( CvPoint2D32f center, double angle, double scale, CvMat* map_matrix );
参数 center
表示重新设定图像旋转中心,用cvPoint2D32f(width / 2, height / 2)
将旋转点设置为图像中心
参数 angle
表示旋转的角度
参数 scale
表示缩放的倍率
参数 map_matrix
返回变换矩阵
2、 直接将旋转后的图像平移
通过几何计算可以得到,比较繁琐,下面直接给出相关代码:
ca = (float)cos((double)(nAngle)*CV_PI / 180);
sa = (float)sin((double)(nAngle)*CV_PI / 180);
// 获取图像高宽
nx = m_ipl->width;
ny = m_ipl->height;
// 设置旋转后图像的大小
sx = nx*fabs(sa) + ny*fabs(ca) + 1;
sy = nx*fabs(ca) + ny*fabs(sa) + 1;
// 根据旋转角度来确定平移量
if ((nAngle % 360) <= 90)
{
xleft = 0;
ydown = nx*sa;
}
else if ((nAngle % 360) > 90 && (nAngle % 360) <= 180)
{
xleft = -nx*ca;
ydown = nx*sa - ny*ca;
}
else if ((nAngle % 360) > 180 && (nAngle % 360) <= 270)
{
xleft = -ny*sa-nx*ca;
ydown = -ny*ca;
}
else
{
xleft = -ny*sa;
ydown = 0;
}
// 创建输出图像
IplImage* dst;
dst = cvCreateImage(cvSize(sx, sy), m_ipl->depth, m_ipl->nChannels);
// 设定变换矩阵
float m[6] = { ca,sa,(float)xleft,-sa,ca,(float)ydown };
CvMat M = cvMat(2, 3, CV_32F, m);
// 衍射变换
cvWarpAffine(m_ipl, dst, &M, CV_INTER_LINEAR + CV_WARP_FILL_OUTLIERS, cvScalarAll(0));
cvNamedWindow("旋转后的图像");
cvShowImage("旋转后的图像", dst);
cvWaitKey(0);
cvReleaseImage(&dst);
程序结果如下: