Tuesday, September 13, 2005

 

Some notes on OpenCV - 3

1.
OPENCV用户手册之图像处理部分(之一):梯度、边缘与角点(中文翻译)
From http://blog.csdn.net/hunnish/archive/2004/09/03/93171.aspx

下面是OPENCV用户手册之图像处理部分:梯度、边缘与角点(中文翻译),有错误欢迎指正,原文在:

http://www.assuredigit.com/incoming/sourcecode/opencv/chinese_docs/ref/opencvref_cv.htm

注意:
本章描述图像处理和分析的一些函数。大多数函数是针对二维数组的。所以我们用数组来描述“图像”,而图像不必是 IplImage,还可以是 CvMat's 或 CvMatND。


--------------------------------------------------------------------------------

梯度、边缘和角点
翻译:HUNNISH, 阿须数码



--------------------------------------------------------------------------------


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 滤波器系数是:
| -3 0 3|
|-10 0 10|
| -3 0 3|

对 x-方向 以及转置矩阵对 y-方向。
函数 cvSobel 通过对图像用相应的内核进行卷积操作来计算图像差分:

dst(x,y) = dxorder+yodersrc/dxxorder•dyyorder |(x,y)

Sobel 算子结合 Gaussian 平滑和微分,以提高计算结果对噪声的抵抗能力。通常情况,函数调用采用如下参数 (xorder=1, yorder=0, aperture_size=3) 或 (xorder=0, yorder=1, aperture_size=3) 来计算一阶 x- 或 y- 方向的图像差分。第一种情况对应:

|-1 0 1|
|-2 0 2|
|-1 0 1|

核。第二种对应

|-1 -2 -1|
| 0 0 0|
| 1 2 1|
or
| 1 2 1|
| 0 0 0|
|-1 -2 -1|

核,它依赖于图像原点的定义 (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- 差分求和:

dst(x,y) = d2src/dx2 + d2src/dy2

对 aperture_size=1 则给出最快计算结果,相当于对图像采用如下内核做卷积:

|0 1 0|
|1 -4 1|
|0 1 0|

类似于 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 用来控制边缘连接,大的阈值用来控制强边缘的初始分割。


--------------------------------------------------------------------------------

PreCornerDetect
计算特征图,用于角点检测

void cvPreCornerDetect( const CvArr* image, CvArr* corners, int aperture_size=3 );


image
输入图像.
corners
保存角点坐标的数组
aperture_size
Sobel 算子的核大小(见cvSobel).
函数 cvPreCornerDetect 计算函数 Dx2Dyy+Dy2Dxx - 2DxDyDxy 其中 D? 表示一阶图像差分,D?? 表示二阶图像差分。 角点被认为是函数的局部最大值:

// assuming that the image is 浮点数
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),然后在邻域上计算差分的相关矩阵:

| sumS(p)(dI/dx)2 sumS(p)(dI/dx•dI/dy)|
M = | |
| sumS(p)(dI/dx•dI/dy) sumS(p)(dI/dy)2 |

然后它计算矩阵的特征值和特征向量,并且按如下方式(λ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)


--------------------------------------------------------------------------------

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)。



Sub-pixel accurate corner locator is based on the observation that every vector from the center q to a point p located within a neighborhood of q is orthogonal to the image gradient at p subject to image and measurement noise. Consider the expression:

εi=DIpiT•(q-pi)

where DIpi is the image gradient at the one of the points pi in a neighborhood of q. The value of q is to be found such that εi is minimized. A system of equations may be set up with εi' set to zero:

sumi(DIpi•DIpiT)•q - sumi(DIpi•DIpiT•pi) = 0

where the gradients are summed within a neighborhood ("search window") of q. Calling the first gradient term G and the second gradient term b gives:

q=G-1•b

The algorithm sets the center of the neighborhood window at this new center q and then iterates until the center keeps within a set threshold.


--------------------------------------------------------------------------------

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,则选择整个图像。
函数 cvGoodFeaturesToTrack 在图像中寻找具有大特征值的角点。该函数,首先用cvCornerMinEigenVal 计算输入图像的每一个象素点的最小特征值,并将结果存储到变量 eig_image 中。然后进行非最大值压缩(仅保留3x3邻域中的局部最大值)。下一步将最小特征值小于 quality_level•max(eig_image(x,y)) 排除掉。最后,函数确保所有发现的角点之间具有足够的距离,(最强的角点第一个保留,然后检查新的角点与已有角点之间的距离大于 min_distance )。

2.
OPENCV用户手册之图像处理部分(之二):采样、差值与几何变换(中文翻译)
From http://blog.csdn.net/hunnish/archive/2004/09/03/93174.aspx

采样、差值和几何变换
翻译:HUNNISH, 阿须数码



--------------------------------------------------------------------------------


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
The line 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,
int fill_outliers=0, CvScalar fill_value=cvScalarAll(0) );


src
输入图像.
dst
提取的四边形.
map_matrix
3 × 2 变换矩阵 [A|b] (见讨论).
fill_outliers
该标志位指定是否对原始图像边界外面的象素点使用复制模式(fill_outliers=0)进行差值或者将其设置为指定值(fill_outliers=1)。
fill_value
对原始图像边界外面的象素设定固定值,当 fill_outliers=1.
函数 cvGetQuadrangleSubPix 从图像 src 中提取四边形,使用子象素精度,并且将结果存储于 dst ,计算公式是:

dst(x+width(dst)/2, y+height(dst)/2)= src( A11x+A12y+b1, A21x+A22y+b2),

where A and b are taken from map_matrix
| A11 A12 b1 |
map_matrix = | |
| A21 A22 b2 |

其中在非整数坐标 A•(x,y)T+b 的象素点值通过双线性变换得到。多通道图像的每一个通道都单独计算.

例子:使用 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 - 指定 matrix 是输出图像到输入图像的反变换,因此可以直接用来做象素差值。否则, 函数从 map_matrix 得到反变换。
fillval
用来填充边界外面的值
函数 cvWarpAffine 利用下面指定的矩阵变换输入图像:

dst(x',y')<-src(x,y)
如果没有指定 CV_WARP_INVERSE_MAP , (x',y')T=map_matrix•(x,y,1)T+b ,
否则, (x, y)T=map_matrix•(x',y&apos,1)T+b

函数与 cvGetQuadrangleSubPix 类似,但是不完全相同。 cvWarpAffine 要求输入和输出图像具有同样的数据类型,有更大的资源开销(因此对大图像不太合适)而且输出图像的部分可以保留不变。而 cvGetQuadrangleSubPix 可以精确地从8位图像中提取四边形到浮点数缓存区中,具有比较小的系统开销,而且总是全部改变输出图像的内容。

要变换稀疏矩阵,使用 cxcore 中的函数 cvTransform 。


--------------------------------------------------------------------------------

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)

该变换映射旋转中心到它本身。如果这不是目的的话,应该调整平移(Hunnish: 这段话令人费解:The transformation maps the rotation center to itself. If this is not the purpose, the shift should be adjusted)


--------------------------------------------------------------------------------

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 利用下面指定矩阵变换输入图像:

dst(x',y')<-src(x,y)
若指定 CV_WARP_INVERSE_MAP, (tx',ty',t)T=map_matrix•(x,y,1)T+b
否则, (tx, ty, t)T=map_matrix•(x',y&apos,1)T+b

要变换稀疏矩阵,使用 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

where dst(i)=(x'i,y'i), src(i)=(xi,yi), i=0..3.

3.
OPENCV用户手册之图像处理部分(之三):形态学操作(中文翻译)
From http://blog.csdn.net/hunnish/archive/2004/09/06/95532.aspx

形态学操作
HUNNISH 注:

本翻译是直接根据 OpenCV Beta 4.0 版本的用户手册翻译的,原文件是:/doc/ref/opencvref_cv.htm, 可以从 SOURCEFORG 上面的 OpenCV 项目下载,也可以直接从 阿须数码 中下载:http://www.assuredigit.com/incoming/sourcecode/opencv/chinese_docs/ref/opencvref_cv.htm。

翻译中肯定有不少错误,另外也有些术语和原文语义理解不透导致翻译不准确或者错误,也请有心人赐教。翻译这些英文参考手册的目的是想与国内 OPENCV 的爱好者一起提高 OPENCV 在计算机视觉、模式识别和图像处理方面的实际应用水平。


--------------------------------------------------------------------------------

CreateStructuringElementEx
创建结构元素

IplConvKernel* cvCreateStructuringElementEx( int cols, int rows, int anchor_x, int anchor_y,
int shape, int* values=NULL );


cols
结构元素的列数目
rows
结构元素的行数目
anchor_x
锚点的相对水平偏移量
anchor_y
锚点的相对垂直便宜量
shape
结构元素的形状,可以是下列值:
CV_SHAPE_RECT, 长方形元素;
CV_SHAPE_CROSS, 交错元素 a cross-shaped element;
CV_SHAPE_ELLIPSE, 椭圆元素;
CV_SHAPE_CUSTOM, 用户自定义元素。这种情况下参数 values 定义了 mask,即象素的那个邻域必须考虑。
values
指向结构元素的指针,它是一个平面数组,表示对元素矩阵逐行扫描。非零值的点表示该点属于该元素。如果点为 NULL,那么所有值都被认为是非零,即元素是一个长方形。该参数仅仅当形状是 CV_SHAPE_CUSTOM 时才予以考虑。
函数 cv CreateStructuringElementEx 分配和填充结构 IplConvKernel, 它可作为形态操作中的结构元素。


--------------------------------------------------------------------------------

ReleaseStructuringElement
删除结构元素

void cvReleaseStructuringElement( IplConvKernel** element );


element
被删除的结构元素的指针
函数 cvReleaseStructuringElement 释放结构 IplConvKernel 。如果 *element 为 NULL, 则函数不作用。


--------------------------------------------------------------------------------

Erode
使用结构元素腐蚀图像

void cvErode( const CvArr* src, CvArr* dst, IplConvKernel* element=NULL, int iterations=1 );


src
输入图像.
dst
输出图像.
element
用于腐蚀的结构元素。若为 NULL, 则使用 3×3 长方形的结构元素
iterations
腐蚀的次数
函数 cvErode 对输入图像使用指定的结构元素进行腐蚀,该结构决定每个具有最小值象素点的邻域形状:

dst=erode(src,element): dst(x,y)=min((x',y') in element))src(x+x',y+y')

函数支持(in-place)模式。腐蚀可以重复进行 (iterations) 次. 对彩色图像,每个彩色通道单独处理。


--------------------------------------------------------------------------------

Dilate
使用结构元素膨胀图像

void cvDilate( const CvArr* src, CvArr* dst, IplConvKernel* element=NULL, int iterations=1 );


src
输入图像.
dst
输出图像.
element
用于膨胀的结构元素。若为 NULL, 则使用 3×3 长方形的结构元素
iterations
膨胀的次数
函数 cvErode 对输入图像使用指定的结构元素进行腐蚀,该结构决定每个具有最小值象素点的邻域形状:

函数 cvDilate 对输入图像使用指定的结构元素进行膨胀,该结构决定每个具有最小值象素点的邻域形状:

dst=dilate(src,element): dst(x,y)=max((x',y') in element))src(x+x',y+y')

函数支持(in-place)模式。膨胀可以重复进行 (iterations) 次. 对彩色图像,每个彩色通道单独处理。


--------------------------------------------------------------------------------

MorphologyEx
高级形态变换

void cvMorphologyEx( const CvArr* src, CvArr* dst, CvArr* temp,
IplConvKernel* element, int operation, int iterations=1 );


src
输入图像.
dst
输出图像.
temp
临死图像,某些情况下需要
element
结构元素
operation
形态操作的类型:
CV_MOP_OPEN - 开口
CV_MOP_CLOSE - 闭口
CV_MOP_GRADIENT - 形态梯度
CV_MOP_TOPHAT - "顶帽"
CV_MOP_BLACKHAT - "黑帽"

iterations
膨胀和腐蚀次数.
函数 cvMorphologyEx 在膨胀和腐蚀基本操作的基础上,完成一些高级的形态变换:

开口:
dst=open(src,element)=dilate(erode(src,element),element)

闭口:
dst=close(src,element)=erode(dilate(src,element),element)

形态梯度
dst=morph_grad(src,element)=dilate(src,element)-erode(src,element)

"顶帽":
dst=tophat(src,element)=src-open(src,element)

"黑帽":
dst=blackhat(src,element)=close(src,element)-src

临时图像 temp 在形态梯度以及对“顶帽”和“黑帽”操作时的 in-place 模式下需要。

4.
OPENCV用户手册之图像处理部分(之四):滤波器与色彩转换(中文翻译)
From http://blog.csdn.net/hunnish/archive/2004/09/06/95534.aspx

滤波器与色彩转换
HUNNISH 注:

本翻译是直接根据 OpenCV Beta 4.0 版本的用户手册翻译的,原文件是:/doc/ref/opencvref_cv.htm, 可以从 SOURCEFORG 上面的 OpenCV 项目下载,也可以直接从 阿须数码 中下载:http://www.assuredigit.com/incoming/sourcecode/opencv/chinese_docs/ref/opencvref_cv.htm。

翻译中肯定有不少错误,另外也有些术语和原文语义理解不透导致翻译不准确或者错误,也请有心人赐教。翻译这些英文参考手册的目的是想与国内 OPENCV 的爱好者一起提高 OPENCV 在计算机视觉、模式识别和图像处理方面的实际应用水平


--------------------------------------------------------------------------------

Smooth
各种方法的图像平滑

void cvSmooth( const CvArr* src, CvArr* dst,
int smoothtype=CV_GAUSSIAN,
int param1=3, int param2=0, double param3=0 );


src
输入图像.
dst
输出图像.
smoothtype
平滑方法:
CV_BLUR_NO_SCALE (简单不带尺度变换的模糊) - 对每个象素领域 param1×param2 求和。如果邻域大小是变化的,可以事先利用函数 cvIntegral 计算积分图像。
CV_BLUR (simple blur) - 对每个象素邻域 param1×param2 求和并做尺度变换 1/(param1•param2).
CV_GAUSSIAN (gaussian blur) - 对图像进行核大小为 param1×param2 的高斯卷积
CV_MEDIAN (median blur) - 发现邻域 param1×param1 的中值 (i.e. 邻域是方的).
CV_BILATERAL (双滤波) - 应用双向 3x3 滤波,彩色 sigma=param1,空间 sigma=param2. 关于双向滤波,可参考 http://www.dai.ed.ac.uk/CVonline/LOCAL_COPIES/MANDUCHI1/Bilateral_Filtering.html
param1
平滑操作的第一个参数.
param2
平滑操作的第二个参数. param2 为零对应简单的尺度变换和高斯模糊。
param3
对应高斯参数的 Gaussian sigma (标准差). 如果为零,这由下面的核尺寸计算:
sigma = (n/2 - 1)*0.3 + 0.8, 其中 n=param1 对应水平核,
n=param2 对应垂直核.

对小的卷积核 (3×3 to 7×7) 使用标准 sigma 速度会快。如果 param3 不为零,而 param1 和 param2 为零,则核大小有 sigma 计算 (以保证足够精确的操作).
函数 cvSmooth 可使用上面任何一种方法平滑图像。每一种方法都有自己的特点以及局限。

没有缩放的图像平滑仅支持单通道图像,并且支持8位、16位、32位和32位浮点格式。

简单模糊和高斯模糊支持 1- 或 3-通道, 8-比特 和 32-比特 浮点图像。这两种方法可以(in-place)方式处理图像。

中值和双向滤波工作于 1- 或 3-通道, 8-位图像,但是不能以 in-place 方式处理图像.


--------------------------------------------------------------------------------

Filter2D
对图像做卷积

void cvFilter2D( const CvArr* src, CvArr* dst,
const CvMat* kernel,
CvPoint anchor=cvPoint(-1,-1));
#define cvConvolve2D cvFilter2D


src
输入图像.
dst
输出图像.
kernel
卷积核, 单通道浮点矩阵. 如果想要应用不同的核于不同的通道,先用 cvSplit 函数分解图像到单个色彩通道上,然后单独处理。
anchor
核的锚点表示一个被滤波的点在核内的位置。 锚点应该处于核内部。缺省值 (-1,-1) 表示锚点在核中心。
函数 cvFilter2D 对图像进行线性滤波,支持 In-place 操作。当开孔部分位于图像外面时,函数从最近邻的图像内部象素差值得到边界外面的象素值。


--------------------------------------------------------------------------------

Integral
计算积分图像

void cvIntegral( const CvArr* image, CvArr* sum, CvArr* sqsum=NULL, CvArr* tilted_sum=NULL );


image
输入图像, W×H, 单通道,8位或浮点 (32f 或 64f).
sum
积分图像, W+1×H+1, 单通道,32位整数或 double 精度的浮点数(64f).
sqsum
对象素值平方的积分图像,W+1×H+1, 单通道,32位整数或 double 精度的浮点数 (64f).
tilted_sum
旋转45度的积分图像,单通道,32位整数或 double 精度的浮点数 (64f).
函数 cvIntegral 计算一次或高次积分图像:

sum(X,Y)=sumx
sqsum(X,Y)=sumx
tilted_sum(X,Y)=sumy
利用积分图像,可以方便得到某个区域象素点的和、均值、标准方差或在 0(1) 的选择角度。例如:


sumx1<=x

因此可以在变化的窗口内做快速平滑或窗口相关。


--------------------------------------------------------------------------------

CvtColor
色彩空间转换

void cvCvtColor( const CvArr* src, CvArr* dst, int code );


src
输入的 8-比特 或浮点图像.
dst
输出的 8-比特 或浮点图像.
code
色彩空间转换,通过定义 CV_2 常数 (见下面).
函数 cvCvtColor 将输入图像从一个色彩空间转换为另外一个色彩空间。函数忽略 IplImage 头中定义的 colorModel 和 channelSeq 域,所以输入图像的色彩空间应该正确指定 (包括通道的顺序,对RGB空间而言,BGR 意味着 24-位格式,其排列为 B0 G0 R0 B1 G1 R1 ... 层叠,而 RGB 意味着 24-位格式,其排列为 R0 G0 B0 R1 G1 B1 ... 层叠). 函数做如下变换:

RGB 空间内部的变换,如增加/删除 alpha 通道,反相通道顺序,16位 RGB彩色变换(Rx5:Gx6:Rx5),以及灰度图像的变换,使用:
RGB[A]->Gray: Y=0.212671*R + 0.715160*G + 0.072169*B + 0*A
Gray->RGB[A]: R=Y G=Y B=Y A=0

所有可能的图像色彩空间的相互变换公式列举如下:


RGB<=>XYZ (CV_BGR2XYZ, CV_RGB2XYZ, CV_XYZ2BGR, CV_XYZ2RGB):
|X| |0.412411 0.357585 0.180454| |R|
|Y| = |0.212649 0.715169 0.072182|*|G|
|Z| |0.019332 0.119195 0.950390| |B|

|R| | 3.240479 -1.53715 -0.498535| |X|
|G| = |-0.969256 1.875991 0.041556|*|Y|
|B| | 0.055648 -0.204043 1.057311| |Z|


RGB<=>YCrCb (CV_BGR2YCrCb, CV_RGB2YCrCb, CV_YCrCb2BGR, CV_YCrCb2RGB)
Y=0.299*R + 0.587*G + 0.114*B
Cr=(R-Y)*0.713 + 128
Cb=(B-Y)*0.564 + 128

R=Y + 1.403*(Cr - 128)
G=Y - 0.344*(Cr - 128) - 0.714*(Cb - 128)
B=Y + 1.773*(Cb - 128)


RGB=>HSV (CV_BGR2HSV,CV_RGB2HSV)
V=max(R,G,B)
S=(V-min(R,G,B))*255/V if V!=0, 0 otherwise

(G - B)*60/S, if V=R
H= 180+(B - R)*60/S, if V=G
240+(R - G)*60/S, if V=B

if H<0 then H=H+360

使用上面从 0° 到 360° 变化的公式计算色调(hue)值,确保它们被 2 除后能试用于8位。


RGB=>Lab (CV_BGR2Lab, CV_RGB2Lab)
|X| |0.433910 0.376220 0.189860| |R/255|
|Y| = |0.212649 0.715169 0.072182|*|G/255|
|Z| |0.017756 0.109478 0.872915| |B/255|

L = 116*Y1/3 for Y>0.008856
L = 903.3*Y for Y<=0.008856

a = 500*(f(X)-f(Y))
b = 200*(f(Y)-f(Z))
where f(t)=t1/3 for t>0.008856
f(t)=7.787*t+16/116 for t<=0.008856

上面的公式可以参考 http://www.cica.indiana.edu/cica/faq/color_spaces/color.spaces.html

Bayer=>RGB (CV_BayerBG2BGR, CV_BayerGB2BGR, CV_BayerRG2BGR, CV_BayerGR2BGR,
CV_BayerBG2RGB, CV_BayerRG2BGR, CV_BayerGB2RGB, CV_BayerGR2BGR,
CV_BayerRG2RGB, CV_BayerBG2BGR, CV_BayerGR2RGB, CV_BayerGB2BGR)
Bayer 模式被广泛应用于 CCD 和 CMOS 摄像头. 它允许从一个单独平面中得到彩色图像,该平面中的 R/G/B 象素点被安排如下:

R
G
R
G
R

G
B
G
B
G

R
G
R
G
R

G
B
G
B
G

R
G
R
G
R

G
B
G
B
G



The output RGB components of a pixel are interpolated from 1, 2 or 4 neighbors of the pixel having the same color. There are several modifications of the above pattern that can be achieved by shifting the pattern one pixel left and/or one pixel up. The two letters C1 and C2 in the conversion constants CV_BayerC1C22{BGR|RGB} indicate the particular pattern type - these are components from the second row, second and third columns, respectively. For example, the above pattern has very popular "BG" type.


--------------------------------------------------------------------------------

Threshold
对数组元素进行固定阈值操作

void cvThreshold( const CvArr* src, CvArr* dst, double threshold,
double max_value, int threshold_type );


src
原始数组 (单通道, 8-比特 of 32-比特 浮点数).
dst
输出数组,必须与 src 的类型一致,或者为 8-比特.
threshold
阈值
max_value
使用 CV_THRESH_BINARY 和 CV_THRESH_BINARY_INV 的最大值.
threshold_type
阈值类型 (见讨论)
函数 cvThreshold 对单通道数组应用固定阈值操作。典型的是对灰度图像进行阈值操作得到二值图像。(cvCmpS 也可以达到此目的) 或者是去掉噪声,例如过滤很小或很大象素值的图像点。有好几种对图像取阈值的方法,本函数支持的方法由 threshold_type 确定:

threshold_type=CV_THRESH_BINARY:
dst(x,y) = max_value, if src(x,y)>threshold
0, otherwise

threshold_type=CV_THRESH_BINARY_INV:
dst(x,y) = 0, if src(x,y)>threshold
max_value, otherwise

threshold_type=CV_THRESH_TRUNC:
dst(x,y) = threshold, if src(x,y)>threshold
src(x,y), otherwise

threshold_type=CV_THRESH_TOZERO:
dst(x,y) = src(x,y), if (x,y)>threshold
0, otherwise

threshold_type=CV_THRESH_TOZERO_INV:
dst(x,y) = 0, if src(x,y)>threshold
src(x,y), otherwise

下面是图形化的阈值描述:




--------------------------------------------------------------------------------

AdaptiveThreshold
自适应阈值方法

void cvAdaptiveThreshold( const CvArr* src, CvArr* dst, double max_value,
int adaptive_method=CV_ADAPTIVE_THRESH_MEAN_C,
int threshold_type=CV_THRESH_BINARY,
int block_size=3, double param1=5 );


src
输入图像.
dst
输出图像.
max_value
使用 CV_THRESH_BINARY 和 CV_THRESH_BINARY_INV 的最大值.
adaptive_method
自适应阈值算法使用:CV_ADAPTIVE_THRESH_MEAN_C 或 CV_ADAPTIVE_THRESH_GAUSSIAN_C (见讨论).
threshold_type
取阈值类型:必须是下者之一
CV_THRESH_BINARY,
CV_THRESH_BINARY_INV
block_size
用来计算阈值的象素邻域大小: 3, 5, 7, ...
param1
与方法有关的参数。对方法 CV_ADAPTIVE_THRESH_MEAN_C 和 CV_ADAPTIVE_THRESH_GAUSSIAN_C, 它是一个从均值或加权均值提取的常数(见讨论), 尽管它可以是负数。
函数 cvAdaptiveThreshold 将灰度图像变换到二值图像,采用下面公式:

threshold_type=CV_THRESH_BINARY:
dst(x,y) = max_value, if src(x,y)>T(x,y)
0, otherwise

threshold_type=CV_THRESH_BINARY_INV:
dst(x,y) = 0, if src(x,y)>T(x,y)
max_value, otherwise

其中 TI 是为每一个象素点单独计算的阈值

对方法 CV_ADAPTIVE_THRESH_MEAN_C,它是 block_size × block_size 块中的象素点,被参数 param1 所减,得到的均值,

对方法 CV_ADAPTIVE_THRESH_GAUSSIAN_C 它是 block_size × block_size 块中的象素点,被参数 param1 所减,得到的加权和(gaussian)。

5.
RGB不同彩色空间的转换公式
From http://blog.csdn.net/hunnish/archive/2004/09/01/91325.aspx

RGB不同彩色空间的转换公式


彩图与灰度图的相互转换 RGB <-> GRAY:
RGB[A]->Gray: Y=0.212671*R + 0.715160*G + 0.072169*B
Gray->RGB[A]: R=Y G=Y B=Y A=0

其它的所有可能的图像色彩空间的相互变换公式列举如下:


RGB<=>XYZ :
|X| |0.412411 0.357585 0.180454| |R|
|Y| = |0.212649 0.715169 0.072182|*|G|
|Z| |0.019332 0.119195 0.950390| |B|

|R| | 3.240479 -1.53715 -0.498535| |X|
|G| = |-0.969256 1.875991 0.041556|*|Y|
|B| | 0.055648 -0.204043 1.057311| |Z|
RGB<=>YCrCb
Y=0.299*R + 0.587*G + 0.114*B
Cr=(R-Y)*0.713 + 128
Cb=(B-Y)*0.564 + 128

R=Y + 1.403*(Cr - 128)
G=Y - 0.344*(Cr - 128) - 0.714*(Cb - 128)
B=Y + 1.773*(Cb - 128)


RGB=>HSV
V=max(R,G,B)
S=(V-min(R,G,B))*255/V if V!=0, 0 otherwise

(G - B)*60/S, if V=R
H= 180+(B - R)*60/S, if V=G
240+(R - G)*60/S, if V=B

若 H<0,则 H=H+360

使用上面从 0° 到 360° 变化的公式计算色调( hue)值,确保它们被 2 除后能试用于8位。


RGB=>Lab
|X| |0.433910 0.376220 0.189860| |R/255|
|Y| = |0.212649 0.715169 0.072182|*|G/255|
|Z| |0.017756 0.109478 0.872915| |B/255|

L = 116*Y1/3 for Y>0.008856
L = 903.3*Y for Y<=0.008856

a = 500*(f(X)-f(Y))
b = 200*(f(Y)-f(Z))
其中 f(t)=t1/3 for t>0.008856
f(t)=7.787*t+16/116 for t<=0.008856



<< Home

This page is powered by Blogger. Isn't yours?