第六章 图像变换
1)图像卷积和卷积边界:
卷积就是将图像和提供的核进行卷积,可以设置核的中心等,OpenCV卷积经常遇到图像边界的处理,函数如下:
void cvFilter2D(const CvArr* src,const CvArr* dst,const CvMat* kernel,CvPoint anchor=CvPoint(-1,-1));
void cvCopyMakeBorder(const CvArr* src,CvArr* dst,CvPoint offset,...);//OpenCV卷积操作一般都会调用这个函数进行边界扩展
2)与边缘梯度有关的算子:
cvSobel(const CvArr* src,CvArr* dst,int xorder,int yorder,int aperiture_size);
//索贝尔算子定义在一个离散空间智商,并不是正真的导数,而是多项式的拟合,所以“核”越大,拟合越好
//并且,该算子在水平垂直方向结果不太好,为解决“核”小结果不好,sobel算子内部点有CV_Scharr对应的核,结果较好
cvLaplace(const CvArr* src,CvArr* dst,int aperture=3);
//拉普拉斯可以求二阶导数,二阶导数内部其实调用的sobel算子。可以求物体edges
cvCanny(const CvArr* src,CvArr* edges,double low,double high,int aperture=3);
//原理:先求x,y方向的一阶导数,然后组成4个方向导数,这四个方向导数的局部极值就是边缘候选点,然后设置上下阈值,满足的边缘点拼接成轮廓。
3)霍夫变换:
霍夫变换是一种在图像中寻找直线、圆以及其他简单形状的方法。理论是:2值图像上所有点可能是直线的一部分(一般用极坐标),将直线参数化,然后求每个点的贡献相加,OpenCV中霍夫变换有两种:标准霍夫变换(SHT)和累计概率霍夫变换(PPHT),后一种算法只求部分范围内的贡献相加,时间更快。但是这两种都可以用同一函数访问。
CvSeq* cvHoughLines2(CvArr* image,void* line_storage,int method,double rho,double theta,int threshold...);//二值化图像作为输入
霍夫圆:原理,内部调用cvCanny算子,将所有一阶倒数非零的像素考虑局部梯度,然后又是累加器相加(具体看书,没太明白),设置阈值。缺点,易受噪声影响(cvCanny算子可以看出),同心圆只能选出一个,等。函数如下:
CvSeq* cvHoughCircles(CvArr* image,void* line_storage,int method,...);//可以是灰度图像作为输入
4)仿射变换(拉伸、收缩、扭曲、旋转、投影)
这些都是图像的几何操作,针对图像的尺寸的操作。常见的几何变换有两种:基于2X3的仿射变换,和基于3X3的透视变换或者单应性变换。
首先看一下仿射变换,仿射变换可以写成2X3的矩阵形式,可以讲正方形变化为平行四边形等(放缩等有插值操作),整幅图像的仿射为稠密仿射,对某些点集的仿射为稀疏仿射,函数如下:
void cvWarpAffine(const CvArr* src,CvArr* dst, const CvMat* map_matrix,int flags,...);//稠密仿射变换
void cvGetQuadrangleSubPix(const CvArr* src,CvArr* dst, const CvMat* map_matrix);//这个函数比cvWarpAffine快,参数少,功能一样
//求取 仿射矩阵函数
CvMat* cvGetAffineTransform(const CvPoint2D32f* pts_src,const CvPoint2D32f* pts_dst,CvMat* map_matrix);//只需要三个对应点
CvMat* cv2DRotationMatrix(CvPoint2D32f* center,double angle,double scale,CvMat* map_matrix);//没有平移时求取变换矩阵
//稀疏仿射变换,针对点序列
void cvTransform(const CvArr* src,CvArr* dst,const CvMat* transmat,const CvMat* shiftvec=NULL);
5)透视变换(注意:此处不是三维到二维)
函数原理和放射变换基本一样,只是变换矩阵是3X3的单应性矩阵。如下:
void cvWarpPerspective(const CvArr* src,CvArr* dst, const CvMat* map_matrix,int flags,...);//稠密透视变换
//求取 透视矩阵函数
CvMat* cvGetPerspectiveTransform(const CvPoint2D32f* pts_src,const CvPoint2D32f* pts_dst,CvMat* map_matrix);//需要四个对应点
//稀疏透视变换,针对点序列
void cvPerspectiveTransform(const CvArr* src,CvArr* dst,const CvMat* transmat);
注意:稀疏透视变换的变换矩阵可以是4X4矩阵,就是从四维(增加一维度1)到三维(除以Z就是带深度的二维,类似cvProjectionPoints2函数)。
6)坐标变换(笛卡尔-极坐标-对数坐标等)
用的不多,函数如下:
void cvCartToPolar();//笛卡尔-极坐标,可以用来求边缘-角度直方图
void cvPolarToCart();//极坐标-笛卡尔。
void cvLogPolar();//对数极坐标,具有旋转尺度不变形,如方向不同的正方形,他们的对数极坐标是一样的(比较敏感)。
7)傅立叶变换
有如下函数(详细略):
void cvDFT();//离散傅立叶变换(时间 N*logN)有实数和负数格式,负数格式有某些特殊要求P201,
void cvFFT();//快速傅立叶FFT
void cvDCT();//余弦傅立叶
void cvMulSpectrums();//频谱乘法。
8)积分图像,距离变换和直方图
void cvIntegral();//求积分,即求和(微分就是求差)
void cvDistTransform();//距离变换:输出图像的像素值设置为与输入图像像素值0最近的距离(此处输入为边缘图像,0标识边缘)
//距离变换和一自己选定变换公式(自定义掩码)
void cvEqualizeHist();//直方图均衡化