分享

2012年7月24日 随笔档案

 清风明月0391 2014-01-01

atexit()函数

       在程序退出时经常需要做一些诸如释放资源的操作,但程序退出的方式有很多种。因此需要一种与程序退出方式无关的方法来进行程序退出时的必要处理。atexit()函数用来注册程序正常终止时要被调用的函数。

       atexit()函数的参数是一个函数指针,函数指针指向一个没有参数也没有返回值的函数。其原型如下所示:

       atexit(void(*)(void));

       在一个程序中做多可以用atexit()函数注册32个处理函数,这些处理函数的调用顺序与其注册顺序相反,即最先注册的最后调用,最后注册的最先调用。

如下所示:

#include <STDIO.H>
#include <STDLIB.H>

void fn1()
{
 printf("calling fn1*****\n");
}

void fn2()
{
 printf("calling fn2*****\n");
}

int main()
{

 atexit(fn1);
 atexit(fn2);
 printf("calling main *****\n");

 return 0;
}

结果输出:

calling main *****

calling fn2*****

calling fn1*****

 

 

 

posted @ 2012-07-24 22:27 xingma0910 阅读(34) 评论(0) 编辑

变量之间交换数据(不用第三变量)

编程之中却有诸多美妙之处。

#include <STDIO.H>

int main()
{

 int a,b;
 printf("input the value of a and b:\n");
 scanf("%d%d",&a,&b);

 printf("before exchange:");
 printf("a=%d\tb=%d\n",a,b);

 a=a+b;
 b=a-b;
 a=a-b;

 printf("after the 1st:");
 printf("a=%d\tb=%d\n",a,b);

 a=a^b;
 b=b^a;
 a=a^b;

 printf("after the 2nd:");
 printf("a=%d\tb=%d\n",a,b);

 return 0;
}

posted @ 2012-07-24 21:37 xingma0910 阅读(12) 评论(0) 编辑

图像处理和图像识别中常用的OpenCV函数 (转)

1、cvLoadImage:将图像文件加载至内存;

2、cvNamedWindow:在屏幕上创建一个窗口;

3、cvShowImage:在一个已创建好的窗口中显示图像;

4、cvWaitKey:使程序暂停,等待用户触发一个按键操作;

5、cvReleaseImage:释放图像文件所分配的内存;

6、cvDestroyWindow:销毁显示图像文件的窗口;

7、cvCreateFileCapture:通过参数设置确定要读入的AVI文件;

8、cvQueryFrame:用来将下一帧视频文件载入内存;

9、cvReleaseCapture:释放CvCapture结构开辟的内存空间;

10、cvCreateTrackbar:创建一个滚动条;

11、cvSetCaptureProperty:设置CvCapture对象的各种属性;

12、cvGetCaptureProperty:查询CvCapture对象的各种属性;

13、cvGetSize:当前图像结构的大小;

14、cvSmooth:对图像进行平滑处理;

15、cvPyrDown:图像金字塔,降采样,图像缩小为原来四分之一;

16、cvCanny:Canny边缘检测;

17、cvCreateCameraCapture:从摄像设备中读入数据;

18、cvCreateVideoWriter:创建一个写入设备以便逐帧将视频流写入视频文件;

19、cvWriteFrame:逐帧将视频流写入文件;

20、cvReleaseVideoWriter:释放CvVideoWriter结构开辟的内存空间;

21、CV_MAT_ELEM:从矩阵中得到一个元素;

22、cvAbs:计算数组中所有元素的绝对值;

23、cvAbsDiff:计算两个数组差值的绝对值;

24、cvAbsDiffS:计算数组和标量差值的绝对值;

25、cvAdd:两个数组的元素级的加运算;

26、cvAddS:一个数组和一个标量的元素级的相加运算;

27、cvAddWeighted:两个数组的元素级的加权相加运算(alpha运算);

28、cvAvg:计算数组中所有元素的平均值;

29、cvAvgSdv:计算数组中所有元素的绝对值和标准差;

30、cvCalcCovarMatrix:计算一组n维空间向量的协方差;

31、cvCmp:对两个数组中的所有元素运用设置的比较操作;

32、cvCmpS:对数组和标量运用设置的比较操作;

33、cvConvertScale:用可选的缩放值转换数组元素类型;

34、cvCopy:把数组中的值复制到另一个数组中;

35、cvCountNonZero:计算数组中非0值的个数;

36、cvCrossProduct:计算两个三维向量的向量积(叉积);

37、cvCvtColor:将数组的通道从一个颜色空间转换另外一个颜色空间;

38、cvDet:计算方阵的行列式;

39、cvDiv:用另外一个数组对一个数组进行元素级的除法运算;

40、cvDotProduct:计算两个向量的点积;

41、cvEigenVV:计算方阵的特征值和特征向量;

42、cvFlip:围绕选定轴翻转;

43、cvGEMM:矩阵乘法;

44、cvGetCol:从一个数组的列中复制元素;

45、cvGetCols:从数据的相邻的多列中复制元素;

46、cvGetDiag:复制数组中对角线上的所有元素;

47、cvGetDims:返回数组的维数;

48、cvGetDimSize:返回一个数组的所有维的大小;

49、cvGetRow:从一个数组的行中复制元素值;

50、cvGetRows:从一个数组的多个相邻的行中复制元素值;

51、cvGetSize:得到二维的数组的尺寸,以CvSize返回;

52、cvGetSubRect:从一个数组的子区域复制元素值;

53、cvInRange:检查一个数组的元素是否在另外两个数组中的值的范围内;

54、cvInRangeS:检查一个数组的元素的值是否在另外两个标量的范围内;

55、cvInvert:求矩阵的逆;

56、cvMahalonobis:计算两个向量间的马氏距离;

57、cvMax:在两个数组中进行元素级的取最大值操作;

58、cvMaxS:在一个数组和一个标量中进行元素级的取最大值操作;

59、cvMerge:把几个单通道图像合并为一个多通道图像;

60、cvMin:在两个数组中进行元素级的取最小值操作;

61、cvMinS:在一个数组和一个标量中进行元素级的取最小值操作;

62、cvMinMaxLoc:寻找数组中的最大最小值;

63、cvMul:计算两个数组的元素级的乘积(点乘);

64、cvNot:按位对数组中的每一个元素求反;

65、cvNormalize:将数组中元素进行归一化;

66、cvOr:对两个数组进行按位或操作;

67、cvOrs:在数组与标量之间进行按位或操作;

68、cvReduce:通过给定的操作符将二维数组简为向量;

69、cvRepeat:以平铺的方式进行数组复制;

70、cvSet:用给定值初始化数组;

71、cvSetZero:将数组中所有元素初始化为0;

72、cvSetIdentity:将数组中对角线上的元素设为1,其他置0;

73、cvSolve:求出线性方程组的解;

74、cvSplit:将多通道数组分割成多个单通道数组;

75、cvSub:两个数组元素级的相减;

76、cvSubS:元素级的从数组中减去标量;

77、cvSubRS:元素级的从标量中减去数组;

78、cvSum:对数组中的所有元素求和;

79、cvSVD:二维矩阵的奇异值分解;

80、cvSVBkSb:奇异值回代计算;

81、cvTrace:计算矩阵迹;

82、cvTranspose:矩阵的转置运算;

83、cvXor:对两个数组进行按位异或操作;

84、cvXorS:在数组和标量之间进行按位异或操作;

85、cvZero:将所有数组中的元素置为0;

86、cvConvertScaleAbs:计算可选的缩放值的绝对值之后再转换数组元素的类型;

87、cvNorm:计算数组的绝对范数, 绝对差分范数或者相对差分范数;

88、cvAnd:对两个数组进行按位与操作;

89、cvAndS:在数组和标量之间进行按位与操作;

90、cvScale:是cvConvertScale的一个宏,可以用来重新调整数组的内容,并且可以将参数从一种数据类型转换为另一种;

91、cvT:是函数cvTranspose的缩写;

92、cvLine:画直线;

93、cvRectangle:画矩形;

94、cvCircle:画圆;

95、cvEllipse:画椭圆;

96、cvEllipseBox:使用外接矩形描述椭圆;

97、cvFillPoly、cvFillConvexPoly、cvPolyLine:画多边形;

98、cvPutText:在图像上输出一些文本;

99、cvInitFont:采用一组参数配置一些用于屏幕输出的基本个特定字体;

100、cvSave:矩阵保存;

101、cvLoad:矩阵读取;

102、cvOpenFileStorage:为读/写打开存储文件;

103、cvReleaseFileStorage:释放存储的数据;

104、cvStartWriteStruct:开始写入新的数据结构;

105、cvEndWriteStruct:结束写入数据结构;

106、cvWriteInt:写入整数型;

107、cvWriteReal:写入浮点型;

108、cvWriteString:写入字符型;

109、cvWriteComment:写一个XML或YAML的注释字串;

110、cvWrite:写一个对象;

111、cvWriteRawData:写入多个数值;

112、cvWriteFileNode:将文件节点写入另一个文件存储器;

113、cvGetRootFileNode:获取存储器最顶层的节点;

114、cvGetFileNodeByName:在映图或存储器中找到相应节点;

115、cvGetHashedKey:为名称返回一个惟一的指针;

116、cvGetFileNode:在映图或文件存储器中找到节点;

117、cvGetFileNodeName:返回文件的节点名;

118、cvReadInt:读取一个无名称的整数型;

119、cvReadIntByName:读取一个有名称的整数型;

120、cvReadReal:读取一个无名称的浮点型;

121、cvReadRealByName:读取一个有名称的浮点型;

122、cvReadString:从文件节点中寻找字符串;

123、cvReadStringByName:找到一个有名称的文件节点并返回它;

124、cvRead:将对象解码并返回它的指针;

125、cvReadByName:找到对象并解码;

126、cvReadRawData:读取多个数值;

127、cvStartReadRawData:初始化文件节点序列的读取;

128、cvReadRawDataSlice:读取文件节点的内容;

129、cvGetModuleInfo:检查IPP库是否已经正常安装并且检验运行是否正常;

130、cvResizeWindow:用来调整窗口的大小;

131、cvSaveImage:保存图像;

132、cvMoveWindow:将窗口移动到其左上角为x,y的位置;

133、cvDestroyAllWindow:用来关闭所有窗口并释放窗口相关的内存空间;

134、cvGetTrackbarPos:读取滑动条的值;

135、cvSetTrackbarPos:设置滑动条的值;

136、cvGrabFrame:用于快速将视频帧读入内存;

137、cvRetrieveFrame:对读入帧做所有必须的处理;

138、cvConvertImage:用于在常用的不同图像格式之间转换;

139、cvErode:形态腐蚀;

140、cvDilate:形态学膨胀;

141、cvMorphologyEx:更通用的形态学函数;

142、cvFloodFill:漫水填充算法,用来进一步控制哪些区域将被填充颜色;

143、cvResize:放大或缩小图像;

144、cvPyrUp:图像金字塔,将现有的图像在每个维度上都放大两倍;

145、cvPyrSegmentation:利用金字塔实现图像分割;

146、cvThreshold:图像阈值化;

147、cvAcc:可以将8位整数类型图像累加为浮点图像;

148、cvAdaptiveThreshold:图像自适应阈值;

149、cvFilter2D:图像卷积;

150、cvCopyMakeBorder:将特定的图像轻微变大,然后以各种方式自动填充图像边界;

151、cvSobel:图像边缘检测,Sobel算子;

152、cvLaplace:拉普拉斯变换、图像边缘检测;

153、cvHoughLines2:霍夫直线变换;

154、cvHoughCircles:霍夫圆变换;

155、cvRemap:图像重映射,校正标定图像,图像插值;

156、cvWarpAffine:稠密仿射变换;

157、cvGetQuadrangleSubPix:仿射变换;

158、cvGetAffineTransform:仿射映射矩阵的计算;

159、cvCloneImage:将整个IplImage结构复制到新的IplImage中;

160、cv2DRotationMatrix:仿射映射矩阵的计算;

161、cvTransform:稀疏仿射变换;

162、cvWarpPerspective:密集透视变换(单应性);

163、cvGetPerspectiveTransform:计算透视映射矩阵;

164、cvPerspectiveTransform:稀疏透视变换;

165、cvCartToPolar:将数值从笛卡尔空间到极坐标(极性空间)进行映射;

166、cvPolarToCart:将数值从极性空间到笛卡尔空间进行映射;

167、cvLogPolar:对数极坐标变换;

168、cvDFT:离散傅里叶变换;

169、cvMulSpectrums:频谱乘法;

170、cvDCT:离散余弦变换;

171、cvIntegral:计算积分图像;

172、cvDistTransform:图像的距离变换;

173、cvEqualizeHist:直方图均衡化;

174、cvCreateHist:创建一新直方图;

175、cvMakeHistHeaderForArray:根据已给出的数据创建直方图;

176、cvNormalizeHist:归一化直方图;

177、cvThreshHist:直方图阈值函数;

178、cvCalcHist:从图像中自动计算直方图;

179、cvCompareHist:用于对比两个直方图的相似度;

180、cvCalcEMD2:陆地移动距离(EMD)算法;

181、cvCalcBackProject:反向投影;

182、cvCalcBackProjectPatch:图块的方向投影;

183、cvMatchTemplate:模板匹配;

184、cvCreateMemStorage:用于创建一个内存存储器;

185、cvCreateSeq:创建序列;

186、cvSeqInvert:将序列进行逆序操作;

187、cvCvtSeqToArray:复制序列的全部或部分到一个连续内存数组中;

188、cvFindContours:从二值图像中寻找轮廓;

189、cvDrawContours:绘制轮廓;

190、cvApproxPoly:使用多边形逼近一个轮廓;

191、cvContourPerimeter:轮廓长度;

192、cvContoursMoments:计算轮廓矩;

193、cvMoments:计算Hu不变矩;

194、cvMatchShapes:使用矩进行匹配;

195、cvInitLineIterator:对任意直线上的像素进行采样;

196、cvSampleLine:对直线采样;

197、cvAbsDiff:帧差;

198、cvWatershed:分水岭算法;

199、cvInpaint:修补图像;

200、cvGoodFeaturesToTrack:寻找角点;

201、cvFindCornerSubPix:用于发现亚像素精度的角点位置;

202、cvCalcOpticalFlowLK:实现非金字塔的Lucas-Kanade稠密光流算法;

203、cvMeanShift:mean-shift跟踪算法;

204、cvCamShift:camshift跟踪算法;

205、cvCreateKalman:创建Kalman滤波器;

206、cvCreateConDensation:创建condensation滤波器;

207、cvConvertPointsHomogenious:对齐次坐标进行转换;

208、cvFindChessboardCorners:定位棋盘角点;

209、cvFindHomography:计算单应性矩阵;

210、cvRodrigues2:罗德里格斯变换;

211、cvFitLine:直线拟合算法;

212、cvCalcCovarMatrix:计算协方差矩阵;

213、cvInvert:计算协方差矩阵的逆矩阵;

214、cvMahalanobis:计算Mahalanobis距离;

215、cvKMeans2:K均值;

216、cvCloneMat:根据一个已有的矩阵创建一个新矩阵;

217、cvPreCornerDetect:计算用于角点检测的特征图;

218、cvGetImage:CvMat图像数据格式转换成IplImage图像数据格式;

219、cvMatMul:两矩阵相乘;

220、cvRound:返回和参数最接近的整数值;

221、cvFloor:返回不大于参数的最大整数值;

222、cvCeil:返回不小于参数的最小整数值;

223、cvCreateImage:创建图像;

224cvSetMouseCallback:用鼠标获取确定窗口上的矩形;

225cvContourArea:计算整个或部分轮廓的面积;

226cvArcLength:计算轮廓周长或曲线长度;

227cvBoundingRect:计算点集的最外面矩形边界(获取轮廓的外接矩形)

228cvSeqRemove:删除序列中指定位置的元素(轮廓)

229cvRNG:随机生成一个64位随机数;

230cvGetTickCount:返回64位长整数的时间数据;

231、cvGetTickFrequency:返回系统时钟频率;

232、cvRandInt:返回均匀分布32位的随机数;

233、cvRandReal: 返回均匀分布0~1之间的随机小数;

234、cvInitMatHeader:初始化矩阵头,不分配存储空间;

235、cvTermCriteria:迭代算法终止准则;

236CvSVMParamsSVM训练参数,该结构需要初始化,并传递给CvSVM训练函数;

237、CvSVM::train:训练SVM;

238、CvSVM::predict:预测一个新样本的响应值,在分类问题中,这个函数返回类别编号,在回归问题中,返回函数值;

239、cvSet2D:修改指定的数组;

240、CvSVM::get_support_vector_count:获得支持向量的个数;

241、CvSVM::get_support_vector:获得对应索引编号的支持向量;

242、CvSVM::save:将SVM训练完的数据保存到指定的文件中(save来源于cvStatModel为ML库的通用类);

243、CvSVM::load:将指定的文件装载到SVM指定的对象中;

244、cvCreateBGCodeBookModel:codebook方法中,初始化;

245、cvBGCodeBookUpdate:codebook方法中,更新背景模型;

246、cvBGCodeBookClearStale:codebook方法中,清除消极的codebook;

247、cvBGCodeBookDiff:codebook方法中,背景减除;

248、cvReleaseBGCodeBookModel:codebook方法中,释放资源;

posted @ 2012-07-24 16:44 xingma0910 阅读(540) 评论(0) 编辑

图像处理的基本知识(转)

调色板
调色板(Palette)也叫颜色查找表,是指在16色(每个像素4个bit,总共有16种颜色)或256色(每个像素8个bit,即一个字节,总共有256种颜色)显示系统中由图像中出现最频繁的16种或256种颜色所组成的查找表。对这些颜色按4位(16色)或8位(256色),即0-15或0-255进行编号,每一个编号(索引值)代表R,G,B,3个分量24位的颜色值.使用调色板的图像叫做调色板图像.对于调色板图像而言,它们的像素值并不是颜色值,而是颜色在调色板查找表中的索引号.

图像的颜色处理
自然界的颜色可以简单地分为黑白色(包括灰度级)和彩色两种.
彩色图像处理分为3个主要处理领域,即真彩色,假彩色和伪彩色处理领域.在真彩色处理中,被处理的图像一般从真彩色传感器中获得,例如彩色摄像头或彩色扫描仪;假彩色处理时一种尽量接近真彩色的人工彩色处理技术;伪彩色处理时将彩色分配给某种灰度(强度或强度范围),以增强辨识能力.
1.将256色位图转换为灰度图
位映像
图像显示时是采用扫描方式,即电子枪每次从左到右扫描一行,为每个像素着色,然后再从上倒下扫描整个屏幕,利用人眼的视觉残留效应就可以显示出一屏完整的图像.我们常说的屏幕分辨率是1024X768,刷新频率为85Hz,意思为每行扫描1024个像素,一共要扫描768行,每秒重复85次.一般刷新频率大于80Hz时.人眼感受不到屏幕刷新引起的闪烁,这种显示器就成为位映像设备.因而所谓的位映像,实质上就是一个二维(行和列)的像素矩阵.
位图:
位图就是采用位映像方法显示和存储的图像.
256色位图
自然界的任何颜色都可以通过RGB三原色合成.有的颜色含红色成分多些,其他成分少些.针对含有红色成分的多少,可以将颜色分为0至255共256个等级.0级表示不含红色成分,255表示含有100%的红色成分.同样,绿色和蓝色也可以分为256个等级.这样,R,G,B的各种不同的组合就能表示256X256X256(约1600万)种颜色.当从大约1600万的颜色中选用最常用的256中颜色给位图的像素进行着色时,就得到256色位图.因而,256色位图是一种很具有吸引的彩色位图.
灰度图
灰度图(Grayscale)是数字图像处理中的一个比较简单但却非常重要的概念.它只含有亮度信息,不含色彩信息.从YIQ或YUV色彩系统转换公式可以看出,当R=G=B时,除了Y值不为0外,I,Q值和U,V值都为0,即只有亮度信息,没有色彩信息.灰度图就是这样一种特殊位图,他每个像素的R,G,B分量都相等.通常把R,G,B颜色分量量化为0至255共256个级别,0表示最暗(黑),255表示最亮(白).经过这样的量化之后,灰度图成了一种特殊的256色位图,其调色板的每一个选项的RGB分量都是相同的,即从(0,0,0),(1,1,1)一直到(255,255,255).(0,0,0)是全黑色,(255,255,255)是全白色,中间是灰色.
256色到灰度图的转换
1.最大值法 是R,G,B的值等于他们中的最大值
即 R=G=B=max(R,G,B)
2.平均值法 求 R,G,B的平均值
即 R=G=B=(R+G+B)/3
3.加权平均法 对R,G,B三值球加权平均值
即 R=G=B=(wr * R + wg * G + wb* B)/3
其中,wr,wg,wb分贝为R,G,B的权值
4.色彩系统变换法 由 RGB与YIQ色彩系统变换公式可知,当R=G=B时,即得到相应的灰度值为
Y=0.299 * R + 0.587 * G + 0.114 * B
将灰度图像转换为256色位图
这种将灰度图转换为彩色图像的方法通常称之为图像的伪彩色处理.
对灰度图像进行伪彩色变换,只需要指定伪彩色的调色板替换为原来的调色板即可.
目前常用的伪彩色的调色板有以下几种,红饱和度编码,绿饱和度编码,蓝饱和度编码,黄饱和度编码,青色饱和度编码,紫色饱和度编码,彩虹编码,热金属编码

将真彩色图像转换为256色位图
真彩色图像指的是能真实地反映自然物体本来颜色的图像.大多数彩色图像采集系统都采用24位的真彩色(每个像素12个bit)来存储图像,以便最大限度地保证图像信息的完整性.将24位真彩色图像转化为8位的256色图像,通常称为对图像进行减色处理.
将真彩色图像转化为256色位图的关键是要生成一个合适的调色板,因为要显示256色位图必须使用调色板.该调色板是否合适是以用调色板显示图像时是否能最大限度地反映真彩色图像的彩色信息为标准.由于256色位图调色板仅能显示256种颜色,因此,当真彩色图像转化为256色位图时,就必须从真彩色所能表现的大约16M中颜色中选取最代表性或出现频率最高的256中颜色.在前面提到,在这256种调色板颜色中,有20中颜色是windows预留的.因此,实际只需要选出236中颜色.确定了用来填写调色板的256中颜色后,其余的颜色就用与选定的256中颜色最相似的颜色来代替,这也是不得已而为之,因为256色位图的表现能力有限.
要想从真彩色图像所能表现的大约16M中颜色中选取最代表性或者出现频率最高的256中颜色,目前广泛的采用的方法主要有以下3种 :
流行色算法(popularity algorithm)
是对彩色图像中所有颜色出现的次数所统计分析,即创建一个数组记录各种颜色和该颜色出现的频率,然后把出现次数最多(频率最大)的236中颜色作为调色板的颜色.该算法实现起来比较简单,但该算法可能丢失一些出现频率较低但是视觉效果明显的信息.
中位切分算法(median-cut algorithm)
在RGB彩色空间中,R,G,B三基色对应于空间的3个坐标轴,并将每一个坐标轴都量化到0-255.0对应全黑,255对应全白.这样就形成了一个边长256的彩色立方体.所有可能的颜色都对应于立方体上的一个点.将彩色立方体切分成236个小立方体(每个小立方体中都包含了相同数量的图像中出现的颜色点.求出每一哦小立方体的中心点,这些中心点所表示的颜色就是最能代表图像颜色特征的236种颜色).中位切分法被广泛引用,但该算法设计复杂的排序工作,而且内存开销较大.
八叉树颜色量化算法
将图像的R,G,B颜色值分布到层状的八叉树中.八叉树的深度最多为9层,即根节点层和分别表示8位的R,G,B值的8个节点层.较及其不重要的R,G,B值的位(R,G,B右边的位).因此,为了提高效率和节省内存,通常并不把8位R,G,B分量值都用上.......

2010.03.27
图像增强
图像增强的目的:1.人眼看着更舒服;2.适合机器进行分析处理.
空域处理法:
数字图像f(x,y)经增强处理后,得到一幅新的数字图像g(x,y),这种方法就叫做空域处理法.在二维图像空间进行增强处理,主要是在灰度级上做文章,即利用灰度对比度增强的方法,进行灰度级映射变换.
频域处理法:
将离散图像f(x,y)进行傅立叶变换F(u,v),在空间频率进行滤波处理后得到新的图像G(u,v),再经过傅立叶逆变换得到图像g(x,y),这种方法就做频域法处理.卷积定理是频域法处理的基础.
一般情况下,用空域法增强图像是较有效的方法,而频域法则有可能产生交叠误差,造成图像失真.同时,频域法处理图像时占用内存多,计算比较费时,因而能用空域法就不采用频域法.使用频域法可以进行正,逆变换,将乘除运算变为加减运算.

灰度变换法:
灰度变换法是一种空间域图像增强的方法,也是图像增强中技术比较简单的方法.它是将图像f(x,y)的灰度级按照一定的映射关系变换为新图像g(x,y)的灰度级.通常有线性灰度变换,分段线性变换,非线性灰度变换等方法.当图像由于成像时曝光不充分或过度,成像设备的非线性或图像计量设备动态范围小等因素造成图像对比度不知,细节分辨率不清时,对图像进行灰度线性扩展常能显著改善图像质量.为了突出图像中感兴趣的灰度区间或图像中的目标,相对抑制图像中不感兴趣的灰度区间,可采用分度线性法.
线性灰度变换:
线性灰度变换的基本思想是把原图像的灰度值按照固定的比例关系进行放大或缩小.例如:原图像的像素灰度值的范围为[20,100],如果我们把所有的灰度值同时扩大两倍,则得到新图像的灰度值的范围是[40,200].
分段线性灰度变换
分段灰度线性变换的基本思想是对原图像中不同灰度范围的像素值放大或缩小不同的倍数.一般采用三段线性变换.
非线性灰度变换:
一般采用对数变换和指数变换两种形式.
对数变换:当希望对图像的低灰度区有较大的扩展而对高灰度区进行压缩时,一般采用该变换.
指数变换:这种变换对图像的高灰度区有较大的扩展.

直方图均值法:
灰度直方图简介:
灰度级直方图是一种函数,它表示数字图像中每一灰度级与该灰度级出现的频率之间的对应关系.
假设数字图像总的像素为n,某一灰度r的像素的数目为m,曾m/n就是相对频率.也就是灰度级为r的像素出现的频率.灰度直方图是由若干根线条组成的图形,每一根线条代表了某一灰度级像素在整个图像中出现的频率.
如果能使图像的直方图是平直的,即各灰度级基于相同的出现频率,那么,由于灰度级具有均匀的概率分布,腿昂看起来就比较清晰.真正增强方法称为直方图均衡法.
方差均衡法:
方差均衡法多用于指纹识别中.计算图像的方差和均值,再根据期望的均值和方差计算.
图像平滑技术:
主要目的是减少由于图像采样系统的质量因素而产生的噪音.一般情况下,在空域内可以用邻域平均来减少噪音;在频率内,邮件噪音频谱通常在高频段,因此可以采用各种形式的第通道滤波方法来减少噪音.
图像平滑一般有两种方法:一种是加权平均法,一种是低通滤波法.其中低波滤波法属于频域法图像增强技术.
加权平均法是取一个nxn的窗口,并取窗口内的n^2个像素的灰度级的加权平均值取代中心像素原来的灰度级.加给每一个像素的灰度级的权值是该像素在灰度级上接近程度的一种度量.
模板的选取:相等加权,锥形加权,灰度差倒数加权.

种植滤波法:
中值滤波是一种非线性的滤波技术,与其对应的中值滤波器当然也就是一种非线性滤波器.中值滤波在一定条件下可以克服线性滤波器如最小均方滤波,均值滤波等带来的图像细节模糊,而且对抑制图像中的脉冲干扰和椒盐噪音特别有效.因为这些噪音在图像中往往以鼓励点的形式出现,与之对应的像素又比较少,所有采用中值滤波能有效的去除这些噪音,达到图像增强的目的.
中值滤波法一般采用一个含有奇数个点的滑动窗口,对该窗口内的诸像素灰度排序,用其中值代替窗口中心像素原来的灰度值,或者说用局部中值代图像模糊替局部平均值.

图像的锐化
图像模糊的实质是图像受到平均或积分造成的,因此可对图像进行逆运算如做微分运算来是图像清晰化.从频谱角度来看,图像模糊的实质是其高频分量被衰减,因而可以通过高通滤波清晰图像.值得一提的是,对图像进行锐化处理时,图像必须具有较高的信噪比,否则锐化处理后,图像的信噪比反而更低,从而使噪声的增加比信号还要多.因此,一般是先去除或减弱噪声后再进行锐化处理.
图像的锐化方法一般有两种方法:一种是微分法,一种是高通滤波法.
常用的微分锐化方法主要有两种,即梯度锐化和拉普拉斯锐化.

低通滤波法:
在二维数字图像中,干扰和噪声经傅立叶变换后多反映在高频分量中.因此,对图像进行傅立叶变换后,在频域进行低通滤波,是低频分量无损通过,对高频分量进行抑制和衰减,即可达到图像增强的目的.
常用的集中低通滤波器:理想低通滤波器,巴特奥斯低通滤波器,指数低通滤波器,梯度低通滤波器.

高通滤波法:
由于图像中边缘与灰度级的急剧变化都与图像的高频分量有关,因而在频域中用高通滤波器滤波能够使图像尖锐化.高通滤波器可以衰减图像傅立叶变化中的低频分量,而无损傅立叶变换中的高频信息.
常用高通滤波器:理想高通滤波器,巴特奥斯高通滤波器,指数高通滤波器,梯度高通滤波器.

图像的边缘检测:
图像的边缘检测(或叫边缘增强)是使图像的轮廓更加突出的图像处理方法.在对图像进行特征提取之前,一般都进行边缘检测,然后再进行二值化处理.边缘检测将突出图像的边缘,边缘以外的图像区域通常被削弱甚至被完全去掉.处理后边界的亮度与原图中边缘周围的亮度变化率成正比.

微分算子边缘检测:
边缘的检测常借助空域微分算子进行,通过将其模板与图像卷积完成.两个具有不同灰度值的相邻区域之间总会存在灰度边缘.这种不连续的灰度边缘常可利用求导数的方法检测到.一般用一阶和二阶导数来检测边缘,这是因为在边缘地带导数值达,而非边缘地方导数值小.
图像中目标的边缘可通过求导数来确定.但是数字图像是离散的,不能求导数.那该怎么办?方法很简单,离散的数字图像不能求导数,求差分却是可以的,那么我们就用求差分来近似求导数.

哈夫变换
哈夫变换方法是利用图像全局特性直接检测目标轮廓,即可将边缘像素连接起来组成区域封闭边界的一种常用方法.在预知区域形状的条件下,利用哈夫变换可以方便地得到边界曲线二净不连续的边缘像素点连接起来.哈夫变换的主要优点是受噪声和曲线间断的影响较小.
梯度算子:梯度对应一阶导数,因而梯度算子是一阶导数算子.
Roberts边缘检测算子:利用局部差分方法寻找边缘的算子,是一种平方根运算.对具有陡峭的低噪声图像影响最好.
Sobel边缘检测算子:采用两个卷积核.对灰度级渐变和噪声较多的图像处理得较好.
Prewitt边缘检测算子:采用两个卷积核.
梯度算子虽然简单,但都对噪声有一定的敏感性.由于噪声的影响,常需要对梯度算子的结果进一步选取阈值做二值化处理,以区分真假边缘点.

方向算子:
方向算子也能用来检测图像的边缘.方向算子利用一组模板分别计算不同方向上的差分值,取其中的最大值作为边缘强度,而将与之对应的方向作为边缘方向.
平移和差分算子:
平移和差分算子可分为垂直边缘算子,水平边缘算子和水平与垂直边缘算子3中,他们采用不同的卷积核.
该方法的实现思路是首先将图像平移一个像素,然后用原图像减去平移后的图像.用相减后的结果来反映原图像亮度变化率的大小.如果原图像某个区域中的像素保持不变,相减的结果当然为零,即像素为黑;如果图像中某个区域的像素变化剧烈,相减后的结果就会较大,即得到较大的变化率,对应的像素很亮.值得注意的是,如果相减后的像素为负值,则应取其绝对值,以保证原图像像素比平移后图像像素更亮或更黑时,都能得到有效的增强.当要检测垂直边缘时使用垂直方向的卷积核,其结果是先将图像向左平移一个像素,再用原图像减去平移后的图像;当要增强水平边缘是使用水平方向卷积核,其结果是先将图像向左上移一个像素,再用原图像减去平移后的图像;当要同时增强水平和垂直方向的边缘时,利用水平与垂直方向卷积核,其结果是先将图像向左上移一个像素,再向左平移一个像素,然后用原图像减去平移后的图像.

梯度方向算子:
梯度方向算子增强根据边缘检测方向不同可以有8个不同的卷积核,分别是北,东北,东,东南,南,西南,西和西北方向.
如果在卷积核方向上存在着正的像素亮度变化率,则输出图像上的像素变量.变化率越大,则图像越亮.由于卷积核中所有卷积系数至和为0,因此,图像中基本不变的区域(空域频率较低的区域)的结果像素值很小,即这些部分经处理后将变黑.

Krisch边缘检测算子:
Nevitia算子:

拉普拉斯算子:
Laplace边缘检测算子是一种二阶导数算子,它具有各向同性的性质,即其对边缘的检测与边缘的方向无关.而且Laplace算子比前述的算子计算量要小,因为它只需要一个模板,因而不必综合各个模板的值,所以比较省事.计算数字图像的拉普拉斯值也是借助各种模板实现.这里对模板的基本要求是对应中心像素的系数应是正的,对应中心像素临近的系数应是负的,且所有系数的和应该是0,这样就不会产生灰度偏移.

综合正交算子:
边缘的存在是图像中灰度值不连续的一般表现,按照这个观点,图像中的孤立点和直线也可以看成边缘.直线段可看作是由两个相邻的边缘组成(相当于脉冲边缘),所以也可以很方便地用特殊设计的正交模板来检测.综合正交模板就是这样一个具有特殊功能的算子.

边界闭合:
当图像中有噪声时,用各种边缘算子检测到的边缘像素常常是孤立的或分小段连续的.也就是说,在检测得到的边缘图中,有些是真正的边缘像素,有些实际上是噪声点.
为将图像中不同的区域分开,需要将边缘像素连接起来组成区域的封闭边界,既要对检测到的图像的边缘进行边界闭合.边界闭合的方法分为并行和串行两种.
要对图像的边缘像素点进行边界闭合,前提是这些边界像素点要有共同点,就像两个人要想在一起,就要有共同语言一样.边缘像素连接的基础即使他们的梯度之间有一定的相似性.

posted @ 2012-07-24 16:14 xingma0910 阅读(563) 评论(0) 编辑

cvRectangle 用法

Rectangle
绘制简单、指定粗细或者带填充的 矩形 

void cvRectangle( CvArr* img, CvPoint pt1, CvPoint pt2, CvScalar color,
                  int thickness=1, int line_type=8, int shift=0 );
img 
图像. 
pt1 
矩形的一个顶点。 
pt2 
矩形对角线上的另一个顶点 
color 
线条颜色 (RGB) 或亮度(灰度图像 )(grayscale image)。 
thickness 
组成矩形的线条的粗细程度。取负值时(如 CV_FILLED)函数绘制填充了色彩的矩形。 
line_type 
线条的类型。见cvLine的描述 
shift 
坐标点的小数点位数。 
  
函数 cvRectangle 通过对角线上的两个顶点绘制矩形。
如:
cvRectangle( ResImage, cvPoint(x1,y1), cvPoint(x2,y2), CV_RGB(255,250,250), 2, 8, 0 );
其中(x1,y1)是坐标为x1,y1的点。这里要注意,x1对应Width,y1代表Height.具体应用的时候不要搞反了。

posted @ 2012-07-24 15:18 xingma0910 阅读(85) 评论(0) 编辑

手势识别方法综述(hand detect) 肤色(转)

看了一天的论文,总结出手势识别的三种方法

1、通过肤色识别
2、通过haar-like基
3、通过HandUv
说下各个优缺点
1、通过肤色识别
设定人的肤色的范围,监测在这个范围内的 肤色InRange,然后画出给定的区域。
例子:

#include "cv.h"
#include "cxcore.h"
#include "highgui.h"
#include "math.h"
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <conio.h>
#include <sstream>
#include <time.h>
using namespace std;
int main()
{
int c = 0;
CvSeq* a = 0;
CvCapture* capture = cvCaptureFromCAM(0);//从对摄像头的初始化捕获
if(!cvQueryFrame(capture)) cout<<"Video capture failed, please check the camera."<<endl;
else cout<<"Video camera capture status: OK"<<endl;
CvSize sz = cvGetSize(cvQueryFrame( capture));//得到摄像头图像大小
IplImage* src = cvCreateImage( sz, 8, 3 );//3通道,每个通道8位
IplImage* hsv_image = cvCreateImage( sz, 8, 3);//
IplImage* hsv_mask = cvCreateImage( sz, 8, 1);
IplImage* hsv_mask2 = cvCreateImage( sz, 8, 1);
IplImage* hsv_edge = cvCreateImage( sz, 8, 1);
CvScalar hsv_min = cvScalar(0, 30, 80, 0);//最小像素的RGB值
CvScalar hsv_max = cvScalar(20, 150, 255, 0);//最大像素的RGB值

//CvScalar hsv_min = cvScalar(30, 30, 30, 0);//最小像素的RGB值
//CvScalar hsv_max = cvScalar(200, 200, 200, 0);//最大像素的RGB值
//
CvMemStorage* storage = cvCreateMemStorage(0);//分配大小为0的内存空间
CvMemStorage* areastorage = cvCreateMemStorage(0);
CvMemStorage* minStorage = cvCreateMemStorage(0);
CvMemStorage* dftStorage = cvCreateMemStorage(0);
CvSeq* contours = NULL;
//
cvNamedWindow( "src",1);
//在屏幕上创建一个窗口,第一个参数为窗口标题,第二个参数为窗口属性,
//设置为0(默认值),或者CV_WINDOW_AUTOSIZE,设置为0,则窗口不会因图像的大小而改变
//图像只能在窗口中根据窗口的大小进行拉伸或缩放;设置为CV_WINDOW_AUTOSIZE时,窗口会根据图像
//的实际大小进行自动拉伸或缩放。
//cvNamedWindow( "hsv-msk",1);
//cvNamedWindow( "contour",1);
//////
IplImage * background=cvLoadImage("c:\\002.jpg");
if (background==0)
{
cout<<"open background error"<<endl;
}
else
cout<<"open background ok!"<<endl;
CvRect rect=cvRect(0,0,background->width,background->height);
cvSetImageROI(background,rect);
IplImage * src3=cvCreateImage(cvGetSize(background),background->depth,background->nChannels);
while( c != 27)//27为ASCII键值(ESC),
{
IplImage* bg = cvCreateImage( sz, 8, 3);//
cvRectangle( bg, cvPoint(0,0), cvPoint(bg->width,bg->height), CV_RGB( 255, 255, 255), -1, 8, 0 );//画矩形,参数:Image,两个顶点坐标,线的颜色,线的厚度
bg->origin = 1;
for(int b = 0; b< int(bg->width/10); b++)//画网格
{
cvLine( bg, cvPoint(b*20, 0), cvPoint(b*20, bg->height), CV_RGB( 200, 200, 200), 1, 8, 0 );//画竖线
cvLine( bg, cvPoint(0, b*20), cvPoint(bg->width, b*20), CV_RGB( 200, 200, 200), 1, 8, 0 );//画横线
}
src = cvQueryFrame( capture);//得到一帧图像
cvSaveImage("c:\\src.bmp",src);
cvCvtColor(src, hsv_image, CV_BGR2HSV);//色彩空间转换,HSV
cvSaveImage("c:\\hsv.bmp",hsv_image);
cvInRangeS (hsv_image, hsv_min, hsv_max, hsv_mask);//检查数组元素是否在两个数量之间,输出新图像hsv_mask,从3通道到1通道
//hsv_mask的数据要么为0,要么为1,在min和max范围内为1,得到ROI区域,找到在像素RGB范围内的数据
//cvSmooth( hsv_mask, hsv_mask, CV_MEDIAN, 27, 0, 0, 0 );
cvSaveImage("c:\\mask.bmp",hsv_mask);
//cvSmooth( hsv_mask, hsv_mask2, CV_MEDIAN, 27, 0, 0);//图像平滑,
cvSmooth( hsv_mask, hsv_mask2, CV_MEDIAN, 3, 0, 0, 0 );
//CV_MEDIAN (median blur) - 对图像进行核大小为param1×param1 的中值滤波 (i.e. 邻域是方的).
cvCanny(hsv_mask2, hsv_edge, 1, 3, 5);
//cvCanny(hsv_mask, hsv_edge, 1, 3, 5);//采用 Canny 算法做边缘检测
cvFindContours( hsv_mask, storage, &contours, sizeof(CvContour), CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE, cvPoint(0,0) );
//对单通道图像检索轮廓,返回第一个轮廓的指针
CvSeq* contours2 = NULL;
double result = 0, result2 = 0;
while(contours)//得到最大的两个感兴趣区
{
result = fabs( cvContourArea( contours, CV_WHOLE_SEQ ) );//计算感兴趣区域的像素点数
if ( result > result2) {result2 = result; contours2 = contours;};
contours = contours->h_next;
}
if ( contours2 )//最大的感兴趣区,ROI
{
//cout << "contours2: " << contours2->total << endl;
CvRect rect = cvBoundingRect( contours2, 0 );//返回一个2d矩形的点集合
cvRectangle( bg, cvPoint(rect.x, rect.y + rect.height), cvPoint(rect.x + rect.width, rect.y), CV_RGB(200, 0, 200), 1, 8, 0 );
//在bg的矩形区域中画rect的图形
//cout << "Ratio: " << rect.width << ", " << rect.height << ", " << (float)rect.width / rect.height << endl;
int checkcxt = cvCheckContourConvexity( contours2 );//检测输入的轮廓是否是凸的
//cout << checkcxt <<endl;
CvSeq* hull = cvConvexHull2( contours2, 0, CV_CLOCKWISE, 0 );//二维凸包
CvSeq* defect = cvConvexityDefects( contours2, hull, dftStorage );//凸包中的缺陷
if( defect->total >=40 ) {cout << " Closed Palm " << endl;}
else if( defect->total >=30 && defect->total <40 ) {cout << " Open Palm " << endl;}
else{ cout << " Fist " << endl;}
cout << "defet: " << defect->total << endl;
CvBox2D box = cvMinAreaRect2( contours2, minStorage );//包围所有点的轮廓的最小矩形
//cout << "box angle: " << (int)box.angle << endl;
cvCircle( bg, cvPoint(box.center.x, box.center.y), 3, CV_RGB(200, 0, 200), 2, 8, 0 );//画圆
cvEllipse( bg, cvPoint(box.center.x, box.center.y), cvSize(box.size.height/2, box.size.width/2), box.angle, 0, 360, CV_RGB(220, 0, 220), 1, 8, 0 );//椭圆
//cout << "Ratio: " << (float)box.size.width/box.size.height <<endl;
}
//cvShowImage( "hsv-msk", hsv_mask); hsv_mask->origin = 1;
//IplImage* contour = cvCreateImage( sz, 8, 3 );
cvDrawContours( bg, contours2, CV_RGB( 0, 200, 0), CV_RGB( 0, 100, 0), 1, 1, 8, cvPoint(0,0));//绘制轮廓的图像到bg图像中
cvShowImage( "src", src);
//cvShowImage("src",src3);
//contour->origin = 1; cvShowImage( "contour", contour);
//cvReleaseImage( &contour);
cvNamedWindow("bg",0);
cvShowImage("bg",bg);
cvNamedWindow( "ROI",0);
cvShowImage("ROI",hsv_mask2);
//cvShowImage("ROI",hsv_mask2);
cvReleaseImage( &bg);
c = cvWaitKey( 100);
}
//////
cvReleaseCapture( &capture);
cvDestroyAllWindows();
}
缺陷在于不能区分脸的颜色和手的颜色,而且识别出来的是全部在这个范围内的东西,难以满足要求。
比较有特点的是http://vinjn.spaces./
他提供的是“虚拟鼓”比较有特色,是
原理
  1.原始视频->人脸识别
  2.根据人脸的颜色分布,找到手
  3.去除手和脸以外的区域
   3.1 对手和脸进行连通区域划分
   3.2 对双手进行运动分析,满足条件则击鼓
他的方法从部分上克服了上述缺陷,但是从他提供的视频可以看出来他穿的一个长袖的衣服,而且衣服颜色和肤色差距很大,如果是短袖的衣服效果估计不会怎么样了。

posted @ 2012-07-24 11:29 xingma0910 阅读(256) 评论(0) 编辑

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多