资源描述
目录
· 1 梯度、边缘和角点
o 1.1 Sobel
o 1.2 Laplace
o 1.3 Canny
o 1.4 PreCornerDetect
o 1.5 CornerEigenValsAndVecs
o 1.6 CornerMinEigenVal
o 1.7 CornerHarris
o 1.8 FindCornerSubPix
o 1.9 GoodFeaturesToTrack
· 2 采样、插值和几何变换
o 2.1 InitLineIterator
o 2.2 SampleLine
o 2.3 GetRectSubPix
o 2.4 GetQuadrangleSubPix
o 2.5 Resize
o 2.6 WarpAffine
o 2.7 GetAffineTransform
o 2.8 2DRotationMatrix
o 2.9 WarpPerspective
o 2.10 WarpPerspectiveQMatrix
o 2.11 GetPerspectiveTransform
o 2.12 Remap
o 2.13 LogPolar
· 3 形态学操作
o 3.1 CreateStructuringElementEx
o 3.2 ReleaseStructuringElement
o 3.3 Erode
o 3.4 Dilate
o 3.5 MorphologyEx
· 4 滤波器与色彩空间变换
o 4.1 Smooth
o 4.2 Filter2D
o 4.3 CopyMakeBorder
o 4.4 Integral
o 4.5 CvtColor
o 4.6 Threshold
o 4.7 AdaptiveThreshold
· 5 金字塔及其应用
o 5.1 PyrDown
o 5.2 PyrUp
· 6 连接部件
o 6.1 CvConnectedComp
o 6.2 FloodFill
o 6.3 FindContours
o 6.4 StartFindContours
o 6.5 FindNextContour
o 6.6 SubstituteContour
o 6.7 EndFindContours
o 6.8 PyrSegmentation
o 6.9 PyrMeanShiftFiltering
o 6.10 Watershed
· 7 图像与轮廓矩
o 7.1 Moments
o 7.2 GetSpatialMoment
o 7.3 GetCentralMoment
o 7.4 GetNormalizedCentralMoment
o 7.5 GetHuMoments
· 8 特殊图像变换
o 8.1 HoughLines
o 8.2 HoughCircles
o 8.3 DistTransform
o 8.4 Inpaint
· 9 直方图
o 9.1 CvHistogram
o 9.2 CreateHist
o 9.3 SetHistBinRanges
o 9.4 ReleaseHist
o 9.5 ClearHist
o 9.6 MakeHistHeaderForArray
o 9.7 QueryHistValue_1D
o 9.8 GetHistValue_1D
o 9.9 GetMinMaxHistValue
o 9.10 NormalizeHist
o 9.11 ThreshHist
o 9.12 CompareHist
o 9.13 CopyHist
o 9.14 CalcHist
o 9.15 CalcBackProject
o 9.16 CalcBackProjectPatch
o 9.17 CalcProbDensity
o 9.18 EqualizeHist
· 10 匹配
o 10.1 MatchTemplate
o 10.2 MatchShapes
o 10.3 CalcEMD2
梯度、边缘和角点
Sobel
使用扩展 Sobel 算子计算一阶、二阶、三阶或混合图像差分
void cvSobel( const CvArr* src, CvArr* dst, int xorder, int yorder, int aperture_size=3 );
src
输入图像.
dst
输出图像.
xorder
x 方向上的差分阶数
yorder
y 方向上的差分阶数
aperture_size
扩展 Sobel 核的大小,必须是 1, 3, 5 或 7。 除了尺寸为 1, 其它情况下, aperture_size ×aperture_size 可分离内核将用来计算差分。对 aperture_size=1的情况, 使用 3x1 或 1x3 内核 (不进行高斯平滑操作)。这里有一个特殊变量 CV_SCHARR (=-1),对应 3x3 Scharr 滤波器,可以给出比 3x3 Sobel 滤波更精确的结果。Scharr 滤波器系数是:
对 x-方向 或矩阵转置后对 y-方向。
函数 cvSobel 通过对图像用相应的内核进行卷积操作来计算图像差分:
由于Sobel 算子结合了 Gaussian 平滑和微分,所以,其结果或多或少对噪声有一定的鲁棒性。通常情况,函数调用采用如下参数 (xorder=1, yorder=0, aperture_size=3) 或 (xorder=0, yorder=1, aperture_size=3) 来计算一阶 x- 或 y- 方向的图像差分。第一种情况对应:
核。
第二种对应:
或者
核的选则依赖于图像原点的定义 (origin 来自 IplImage 结构的定义)。由于该函数不进行图像尺度变换,所以和输入图像(数组)相比,输出图像(数组)的元素通常具有更大的绝对数值(译者注:即像素的位深)。为防止溢出,当输入图像是 8 位的,要求输出图像是 16 位的。当然可以用函数 cvConvertScale 或 cvConvertScaleAbs 转换为 8 位的。除了 8-位 图像,函数也接受 32-位 浮点数图像。所有输入和输出图像都必须是单通道的,并且具有相同的图像尺寸或者ROI尺寸。
Laplace
计算图像的 Laplacian 变换
void cvLaplace( const CvArr* src, CvArr* dst, int aperture_size=3 );
src
输入图像.
dst
输出图像.
aperture_size
核大小 (与 cvSobel 中定义一样).
函数 cvLaplace 计算输入图像的 Laplacian变换,方法是先用 sobel 算子计算二阶 x- 和 y- 差分,再求和:
对 aperture_size=1 则给出最快计算结果,相当于对图像采用如下内核做卷积:
类似于 cvSobel 函数,该函数也不作图像的尺度变换,所支持的输入、输出图像类型的组合和cvSobel一致。
Canny
采用 Canny 算法做边缘检测
void cvCanny( const CvArr* image, CvArr* edges, double threshold1,
double threshold2, int aperture_size=3 );
image
单通道输入图像.
edges
单通道存储边缘的输出图像
threshold1
第一个阈值
threshold2
第二个阈值
aperture_size
Sobel 算子内核大小 (见 cvSobel).
函数 cvCanny 采用 CANNY 算法发现输入图像的边缘而且在输出图像中标识这些边缘。threshold1和threshold2 当中的小阈值用来控制边缘连接,大的阈值用来控制强边缘的初始分割。
· 注意事项:cvCanny只接受单通道图像作为输入。
· 外部链接:经典的canny自调整阈值算法的一个opencv的实现见在OpenCV中自适应确定canny算法的分割门限
PreCornerDetect
计算用于角点检测的特征图,
void cvPreCornerDetect( const CvArr* image, CvArr* corners, int aperture_size=3 );
image
输入图像.
corners
保存候选角点的特征图
aperture_size
Sobel 算子的核大小(见cvSobel).
函数 cvPreCornerDetect 计算函数
其中D表示一阶图像差分, 表示二阶图像差分。 角点被认为是函数的局部最大值:
// 假设图像格式为浮点数
IplImage* corners = cvCloneImage(image);
IplImage* dilated_corners = cvCloneImage(image);
IplImage* corner_mask = cvCreateImage( cvGetSize(image), 8, 1 );
cvPreCornerDetect( image, corners, 3 );
cvDilate( corners, dilated_corners, 0, 1 );
cvSubS( corners, dilated_corners, corners );
cvCmpS( corners, 0, corner_mask, CV_CMP_GE );
cvReleaseImage( &corners );
cvReleaseImage( &dilated_corners );
CornerEigenValsAndVecs
计算图像块的特征值和特征向量,用于角点检测
void cvCornerEigenValsAndVecs( const CvArr* image, CvArr* eigenvv,
int block_size, int aperture_size=3 );
image
输入图像.
eigenvv
保存结果的数组。必须比输入图像宽 6 倍。
block_size
邻域大小 (见讨论).
aperture_size
Sobel 算子的核尺寸(见 cvSobel).
对每个象素,函数 cvCornerEigenValsAndVecs 考虑 block_size × block_size 大小的邻域 S(p),然后在邻域上计算图像差分的相关矩阵:
然后它计算矩阵的特征值和特征向量,并且按如下方式(λ1, λ2, x1, y1, x2, y2)存储这些值到输出图像中,其中
λ1, λ2 - M 的特征值,没有排序
(x1, y1) - 特征向量,对 λ1
(x2, y2) - 特征向量,对 λ2
CornerMinEigenVal
计算梯度矩阵的最小特征值,用于角点检测
void cvCornerMinEigenVal( const CvArr* image,
CvArr* eigenval, int block_size, int aperture_size=3 );
image
输入图像.
eigenval
保存最小特征值的图像. 与输入图像大小一致
block_size
邻域大小 (见讨论 cvCornerEigenValsAndVecs).
aperture_size
Sobel 算子的核尺寸(见 cvSobel). 当输入图像是浮点数格式时,该参数表示用来计算差分固定的浮点滤波器的个数.
函数 cvCornerMinEigenVal 与 cvCornerEigenValsAndVecs 类似,但是它仅仅计算和存储每个象素点差分相关矩阵的最小特征值,即前一个函数的 min(λ1, λ2)
CornerHarris
哈里斯(Harris)角点检测
void cvCornerHarris( const CvArr* image, CvArr* harris_responce,
int block_size, int aperture_size=3, double k=0.04 );
image
输入图像。
harris_responce
存储哈里斯(Harris)检测responces的图像。与输入图像等大。
block_size
邻域大小(见关于cvCornerEigenValsAndVecs的讨论)。
aperture_size
扩展 Sobel 核的大小(见 cvSobel)。格式. 当输入图像是浮点数格式时,该参数表示用来计算差分固定的浮点滤波器的个数。
k
harris 检测器的自由参数。参见下面的公式。
函数 cvCornerHarris 对输入图像进行 Harris 边界检测。类似于 cvCornerMinEigenVal 和 cvCornerEigenValsAndVecs。对每个像素,在 block_size*block_size 大小的邻域上,计算其2*2梯度共变矩阵(或相关异变矩阵)M。然后,将
det(M) - k*trace(M)2 (这里2是平方)
保存到输出图像中。输入图像中的角点在输出图像中由局部最大值表示。
FindCornerSubPix
精确角点位置
void cvFindCornerSubPix( const CvArr* image, CvPoint2D32f* corners,
int count, CvSize win, CvSize zero_zone,
CvTermCriteria criteria );
image
输入图像.
corners
输入角点的初始坐标,也存储精确的输出坐标
count
角点数目
win
搜索窗口的一半尺寸。如果 win=(5,5) 那么使用 5*2+1 × 5*2+1 = 11 × 11 大小的搜索窗口
zero_zone
死区的一半尺寸,死区为不对搜索区的中央位置做求和运算的区域。它是用来避免自相关矩阵出现的某些可能的奇异性。当值为 (-1,-1) 表示没有死区。
criteria
求角点的迭代过程的终止条件。即角点位置的确定,要么迭代数大于某个设定值,或者是精确度达到某个设定值。 criteria 可以是最大迭代数目,或者是设定的精确度,也可以是它们的组合。
函数 cvFindCornerSubPix 通过迭代来发现具有子象素精度的角点位置,或如图所示的放射鞍点(radial saddle points)。
子象素级角点定位的实现是基于对向量正交性的观测而实现的,即从中央点q到其邻域点p 的向量和p点处的图像梯度正交(服从图像和测量噪声)。考虑以下的表达式:
εi=DIpiT•(q-pi)
其中,DIpi表示在q的一个邻域点pi处的图像梯度,q的值通过最小化εi得到。通过将εi设为0,可以建立系统方程如下:
sumi(DIpi•DIpiT)•q - sumi(DIpi•DIpiT•pi) = 0
其中q的邻域(搜索窗)中的梯度被累加。调用第一个梯度参数G和第二个梯度参数b,得到:
q=G-1•b
该算法将搜索窗的中心设为新的中心q,然后迭代,直到找到低于某个阈值点的中心位置。
GoodFeaturesToTrack
确定图像的强角点
void cvGoodFeaturesToTrack( const CvArr* image, CvArr* eig_image, CvArr* temp_image,
CvPoint2D32f* corners, int* corner_count,
double quality_level, double min_distance,
const CvArr* mask=NULL );
image
输入图像,8-位或浮点32-比特,单通道
eig_image
临时浮点32-位图像,尺寸与输入图像一致
temp_image
另外一个临时图像,格式与尺寸与 eig_image 一致
corners
输出参数,检测到的角点
corner_count
输出参数,检测到的角点数目
quality_level
最大最小特征值的乘法因子。定义可接受图像角点的最小质量因子。
min_distance
限制因子。得到的角点的最小距离。使用 Euclidian 距离
mask
ROI:感兴趣区域。函数在ROI中计算角点,如果 mask 为 NULL,则选择整个图像。 必须为单通道的灰度图,大小与输入图像相同。mask对应的点不为0,表示计算该点。
函数 cvGoodFeaturesToTrack 在图像中寻找具有大特征值的角点。该函数,首先用cvCornerMinEigenVal 计算输入图像的每一个象素点的最小特征值,并将结果存储到变量 eig_image 中。然后进行非最大值抑制(仅保留3x3邻域中的局部最大值)。下一步将最小特征值小于 quality_level•max(eig_image(x,y)) 排除掉。最后,函数确保所有发现的角点之间具有足够的距离,(最强的角点第一个保留,然后检查新的角点与已有角点之间的距离大于 min_distance )。
采样、插值和几何变换
InitLineIterator
初始化线段迭代器
int cvInitLineIterator( const CvArr* image, CvPoint pt1, CvPoint pt2,
CvLineIterator* line_iterator, int connectivity=8 );
image
带采线段的输入图像.
pt1
线段起始点
pt2
线段结束点
line_iterator
指向线段迭代器状态结构的指针
connectivity
被扫描线段的连通数,4 或 8.
函数 cvInitLineIterator 初始化线段迭代器,并返回两点之间的象素点数目。两个点必须在图像内。当迭代器初始化后,连接两点的光栅线上所有点,都可以连续通过调用 CV_NEXT_LINE_POINT 来得到。线段上的点是使用 4-连通或8-连通利用 Bresenham 算法逐点计算的。
例子:使用线段迭代器计算彩色线上象素值的和
CvScalar sum_line_pixels( IplImage* image, CvPoint pt1, CvPoint pt2 )
{
CvLineIterator iterator;
int blue_sum = 0, green_sum = 0, red_sum = 0;
int count = cvInitLineIterator( image, pt1, pt2, &iterator, 8 );
for( int i = 0; i < count; i++ ){
blue_sum += iterator.ptr[0];
green_sum += iterator.ptr[1];
red_sum += iterator.ptr[2];
CV_NEXT_LINE_POINT(iterator);
/* print the pixel coordinates: demonstrates how to calculate the coordinates */
{
int offset, x, y;
/* assume that ROI is not set, otherwise need to take it into account. */
offset = iterator.ptr - (uchar*)(image->imageData);
y = offset/image->widthStep;
x = (offset - y*image->widthStep)/(3*sizeof(uchar) /* size of pixel */);
printf("(%d,%d)\n", x, y );
}
}
return cvScalar( blue_sum, green_sum, red_sum );
}
SampleLine
将图像上某一光栅线上的像素数据读入缓冲区
int cvSampleLine( const CvArr* image, CvPoint pt1, CvPoint pt2,
void* buffer, int connectivity=8 );
image
输入图像
pt1
光栅线段的起点
pt2
光栅线段的终点
buffer
存储线段点的缓存区,必须有足够大小来存储点 max( |pt2.x-pt1.x|+1, |pt2.y-pt1.y|+1 ) :8-连通情况下,或者 |pt2.x-pt1.x|+|pt2.y-pt1.y|+1 : 4-连通情况下.
connectivity
线段的连通方式, 4 or 8.
函数 cvSampleLine 实现了线段迭代器的一个特殊应用。它读取由 pt1 和 pt2 两点确定的线段上的所有图像点,包括终点,并存储到缓存中。
GetRectSubPix
从图像中提取象素矩形,使用子象素精度
void cvGetRectSubPix( const CvArr* src, CvArr* dst, CvPoint2D32f center );
src
输入图像.
dst
提取的矩形.
center
提取的象素矩形的中心,浮点数坐标。中心必须位于图像内部.
函数 cvGetRectSubPix 从图像 src 中提取矩形:
dst(x, y) = src(x + center.x - (width(dst)-1)*0.5, y + center.y - (height(dst)-1)*0.5)
其中非整数象素点坐标采用双线性插值提取。对多通道图像,每个通道独立单独完成提取。尽管函数要求矩形的中心一定要在输入图像之中,但是有可能出现矩形的一部分超出图像边界的情况,这时,该函数复制边界的模识(hunnish:即用于矩形相交的图像边界线段的象素来代替矩形超越部分的象素)。
GetQuadrangleSubPix
提取象素四边形,使用子象素精度
void cvGetQuadrangleSubPix( const CvArr* src, CvArr* dst, const CvMat* map_matrix );
src
输入图像.
dst
提取的四边形.
map_matrix
3 × 2 变换矩阵 [A|b] (见讨论).
函数 cvGetQuadrangleSubPix 以子象素精度从图像 src 中提取四边形,使用子象素精度,并且将结果存储于 dst ,计算公式是:
dst(x + width(dst) / 2,y + height(dst) / 2) = src(A11x + A12y + b1,A21x + A22y + b2)
其中 A和 b 均来自映射矩阵(译者注:A, b为几何形变参数) ,映射矩阵为:
其中在非整数坐标 的象素点值通过双线性变换得到。当函数需要图像边界外的像素点时,使用重复边界模式(replication border mode)恢复出所需的值。多通道图像的每一个通道都单独计算。
例子:使用 cvGetQuadrangleSubPix 进行图像旋转
#include "cv.h"
#include "highgui.h"
#include "math.h"
int main( int argc, char** argv )
{
IplImage* src;
/* the first command line parameter must be image file name */
if( argc==2 && (src = cvLoadImage(argv[1], -1))!=0)
{
IplImage* dst = cvCloneImage( src );
int delta = 1;
int angle = 0;
cvNamedWindow( "src", 1 );
cvShowImage( "src", src );
for(;;)
{
float m[6];
double factor = (cos(angle*CV_PI/180.) + 1.1)*3;
CvMat M = cvMat( 2, 3, CV_32F, m );
int w = src->width;
int h = src->height;
m[0] = (float)(factor*cos(-angle*2*CV_PI/180.));
m[1] = (float)(factor*sin(-angle*2*CV_PI/180.));
m[2] = w*0.5f;
m[3] = -m[1];
m[4] = m[0];
m[5] = h*0.5f;
cvGetQuadrangleSubPix( src, dst, &M, 1, cvScalarAll(0));
cvNamedWindow( "dst", 1 );
cvShowImage( "dst", dst );
if( cvWaitKey(5) == 27 )
break;
angle = (angle + delta) % 360;
}
}
return 0;
}
Resize
图像大小变换
void cvResize( const CvArr* src, CvArr* dst, int interpolation=CV_INTER_LINEAR );
src
输入图像.
dst
输出图像.
interpolation
插值方法:
· CV_INTER_NN - 最近邻插值,
· CV_INTER_LINEAR - 双线性插值 (缺省使用)
· CV_INTER_AREA - 使用象素关系重采样。当图像缩小时候,该方法可以避免波纹出现。当图像放大时,类似于 CV_INTER_NN 方法..
· CV_INTER_CUBIC - 立方插值.
函数 cvResize 将图像 src 改变尺寸得到与 dst 同样大小。若设定 ROI,函数将按常规支持 ROI.
WarpAffine
对图像做仿射变换
void cvWarpAffine( const CvArr* src, CvArr* dst, const CvMat* map_matrix,
int flags=CV_INTER_LINEAR+CV_WARP_FILL_OUTLIERS,
CvScalar fillval=cvScalarAll(0) );
src
输入图像.
dst
输出图像.
map_matrix
2×3 变换矩阵
flags
插值方法和以下开关选项的组合:
· CV_WARP_FILL_OUTLIERS - 填充所有输出图像的象素。如果部分象素落在输入图像的边界外,那么它们的值设定为 fillval.
· CV_WARP_INVERSE_MAP - 指定 map_matrix 是输出图像到输入图像的反变换,因此可以直接用来做象素插值。否则, 函数从 map_matrix 得到反变换。
fillval
用来填充边界外面的值
函数 cvWarpAffine 利用下面指定的矩阵变换输入图像:
· 如果没有指定 CV_WARP_INVERSE_MAP ,
· 否则,
函数与 cvGetQuadrangleSubPix 类似,但是不完全相同。 cvWarpAffine 要求输入和输出图像具有同样的数据类型,有更大的资源开销(因此对小图像不太合适)而且输出图像的部分可以保留不变。而 cvGetQuadrangleSubPix 可以精确地从8位图像中提取四边形到浮点数缓存区中,具有比较小的系统开销,而且总是全部改变输出图像的内容。
要变换稀疏矩阵,使用 cxcore 中的函数 cvTransform 。
GetAffineTransform
由三对点计算仿射变换
CvMat* cvGetAffineTransform( const CvPoint2D32f* src,
const CvPoint2D32f* dst, CvMat* map_matrix );
src
输入图像的三角形顶点坐标。
dst
输出图像的相应的三角形顶点坐标。
map_matrix
指向2×3输出矩阵的指针。
函数cvGetAffineTransform计算满足以下关系的仿射变换矩阵:
这里,dst(i) = (x'i,y'i),src(i) = (xi,yi),i = 0..2.
2DRotationMatrix
计算二维旋转的仿射变换矩阵
CvMat* cv2DRotationMatrix( CvPoint2D32f center, double angle,
double scale, CvMat* map_matrix );
center
输入图像的旋转中心坐标
angle
旋转角度(度)。正值表示逆时针旋转(坐标原点假设在左上角).
scale
各项同性的尺度因子
map_matrix
输出 2×3 矩阵的指针
函数 cv2DRotationMatrix 计算矩阵:
[ α β | (1-α)*center.x - β*center.y ]
[ -β α | β*center.x + (1-α)*center.y ]
where α=scale*cos(angle), β=scale*sin(angle)
该变换并不改变原始旋转中心点的坐标,如果这不是操作目的,则可以通过调整平移量改变其坐标(译者注:通过简单的推导可知,仿射变换的实现是首先将旋转中心置为坐标原点,再进行旋转和尺度变换,最后重新将坐标原点设定为输入图像的左上角,这里的平移量是center.x, center.y).
WarpPerspective
对图像进行透视变换
void cvWarpPerspective( const CvArr* src, CvArr* dst, const CvMat* map_matrix,
int flags=CV_INTER_LINEAR+CV_WARP_FILL_OUTLIERS,
CvScalar fillval=cvScalarAll(0) );
src
输入图像.
dst
输出图像.
map_matrix
3×3 变换矩阵
flags
插值方法和以下开关选项的组合:
· CV_WARP_FILL_OUTLIERS - 填充所有缩小图像的象素。如果部分象素落在输入图像的边界外,那么它们的值设定为 fillval.
· CV_WARP_INVERSE_MAP - 指定 matrix 是输出图像到输入图像的反变换,因此可以直接用来做象素插值。否则, 函数从 map_matrix 得到反变换。
fillval
用来填充边界外面的值
函数 cvWarpPerspective 利用下面指定矩阵变换输入图像:
· 如果没有指定 CV_WARP_INVERSE_MAP ,,
· 否则,
要变换稀疏矩阵,使用 cxcore 中的函数 cvTransform 。
WarpPerspectiveQMatrix
用4个对应点计算透视变换矩阵
CvMat* cvWarpPerspectiveQMatrix( const CvPoint2D32f* src,
const CvPoint2D32f* dst,
CvMat* map_matrix );
src
输入图像的四边形的4个点坐标
dst
输出图像的对应四边形的4个点坐标
map_matrix
输出的 3×3 矩阵
函数 cvWarpPerspectiveQMatrix 计算透视变换矩阵,使得:
(tix'i,tiy'i,ti)T=matrix•(xi,yi,1)T
其中 dst(i)=(x'i,y'i), src(i)=(xi,yi), i=0..3.
GetPerspectiveTransform
由四对点计算透射变换
CvMat* cvGetPerspectiveTransform( const CvPoint2D32f* src, const CvPoint2D32f* dst,
CvMat*
展开阅读全文