OpenCV成长之路(8)直线、轮廓的提取与描述

OpenCV成长之路(8)直线、轮廓的提取与描述
OpenCV成长之路(8)直线、轮廓的提取与描述

OpenCV成长之路(8):直线、轮廓的提取与描述

分类:OpenCV成长之路2014-01-04 18:35 689人阅读评论(0) 收藏举报

直线、轮廓的提取与描述基于内容的图像分析的重点是提取出图像中具有代表性的特征,而线条、轮廓、块往往是最能体现特征的几个元素,这篇文章就针对于这几个重要的图像特征,研究它们在OpenCV中的用法,以及做一些简单的基础应用。

一、Canny检测轮廓

在上一篇文章中有提到sobel边缘检测,并重写了soble的C++代码让其与matlab中算法效果一致,而soble边缘检测是基于单一阈值的,我们不能兼顾到低阈值的丰富边缘和高阈值时的边缘缺失这两个问题。而canny算子则很好的弥补了这一不足,从目前看来,canny边缘检测在做图像轮廓提取方面是最优秀的边缘检测算法。

canny边缘检测采用双阈值值法,高阈值用来检测图像中重要的、显著的线条、轮廓等,而低阈值用来保证不丢失细节部分,低阈值检测出来的边缘更丰富,但是很多边缘并不是我们关心的。最后采用一种查找算法,将低阈值中与高阈值的边缘有重叠的线条保留,其他的线条都删除。

本篇文章中不对canny的算法原理作进一步说明,稍后会在图像处理算法相关的文章中详细介绍。

下面我们用OpenCV中的Canny函数来检测图像边缘

1.int main()

2.{

3. Mat I=imread("../cat.png");

4. cvtColor(I,I,CV_BGR2GRAY);

5.

6. Mat contours;

7. Canny(I,contours,125,350);

8. threshold(contours,contours,128,255,THRESH_BINARY);

9.

10. namedWindow("Canny");

11. imshow("Canny",contours);

12. waitKey();

13.return 0;

14.}

显示效果如下:

二、直线检测

直线在图像中出现的频率非常之高,而直线作为图像的特征对于基本内容的图像分析有着很重要的作用,本文通过OpenCV中的hough变换来检测图像中的线条。

我们先看最基本的Hough变换函数HoughLines,它的原型如下:

1.void HoughLines(InputArray image, OutputArray lines, double rho,

2.double theta, int threshold, double srn=0, double stn=0 );

它的输出是一个二值的轮廓图像,往往是边缘检测得到的结果图像;它的输出是一个包含多个Vec2f点的数组,数组中的每个元素是一个二元浮点数据对,rou 代表直线离坐标原点的距离,theta代表角度。第3和第4个参数代表步长,因为Hough变换实际上是一个穷举的算法,rho表示距离的步长,theta代表角度的步长。

第5个参数是一个阈值设置直接的最低投票个数,知道Hough原理的,这个参数应该很容易理解。

从这个函数的输出结果我们可以看出,得到的直线并没有指定在图像中的开始点与结束点,需要我们自己去计算,如果我们想把直接显示在图像中就会比较麻烦,而且会有很多角度接近的直线,其实它们是重复的,为了解决上面这些问题,OpenCV又提供了一个函数HoughLinesP()。它的输出是一个Vector of Vec4i。Vector每一个元素代表一条直线,是由一个4元浮点数组构成,前两个点一组,后两个点一组,代表了在图像中直线的起始和结束点。

1.void HoughLinesP(InputArray image, OutputArray lines, double rho, double theta,

2.int threshold, double minLineLength=0, double maxLineGap=0 );

解释一下最后两个参数,minLineLength指定了检测直线中的最小宽度,如果低于最小宽度则舍弃掉,maxLineGap指定通过同一点的直线,如果距离小于maxLineGap就会进行合并。

下面是一个用HoughLinesP检测直线的例子:

1.int main()

2.{

3. Mat image=imread("../car.png");

4. Mat I;

5. cvtColor(image,I,CV_BGR2GRAY);

6.

7. Mat contours;

8. Canny(I,contours,125,350);

9. threshold(contours,contours,128,255,THRESH_BINARY);

10.

11. vector lines;

12.// 检测直线,最小投票为90,线条不短于50,间隙不小于10

13. HoughLinesP(contours,lines,1,CV_PI/180,80,50,10);

14. drawDetectLines(image,lines,Scalar(0,255,0));

15.

16. namedWindow("Lines");

17. imshow("Lines",image);

18. waitKey();

19.return 0;

20.}

上面程序将检测到的线条保存在lines变量内,我们需要进一步将它们画在图像上:

1.void drawDetectLines(Mat& image,const vector& lines,Scalar & color)

2.{

3.// 将检测到的直线在图上画出来

4. vector::const_iterator it=lines.begin();

5.while(it!=lines.end())

6. {

7. Point pt1((*it)[0],(*it)[1]);

8. Point pt2((*it)[2],(*it)[3]);

9. line(image,pt1,pt2,color,2); // 线条宽度设置为2

10. ++it;

11. }

12.}

实际上Hough变换可以检测很多固定的形状,比如:圆、正方形等。它们的原理基本相同,都是构造一个投票矩阵。OpenCV里提供了检测圆的函数HoughCircles,它的输出是一个Vector of Vec3i,Vector的每个元素包含了3个浮点数,前2个是圆的中心坐标,最后一个是半径。

三、轮廓的提取与描述

在目标识别中我们首先要把感兴趣的目标提取出来,而一般常见的步骤都是通过颜色或纹理提取出目标的前景图(一幅黑白图像,目标以白色显示在图像中),接下来我们要对前景图进行分析进一步地把目标提取出来,而这里常常用到的就是提取目标的轮廓。

OpenCV里提取目标轮廓的函数是findContours,它的输入图像是一幅二值图像,输出的是每一个连通区域的轮廓点的集合:vector>。外层vector的size代表了图像中轮廓的个数,里面vector的size代表了轮廓上点的个数。下面我们通过实例来看函数的用法。

1.int main()

2.{

https://www.360docs.net/doc/03488981.html,ing namespace cv;

4.

5. Mat image=imread("../shape.png");

6. cvtColor(image,image,CV_BGR2GRAY);

7. vector> contours;

8.// find

9. findContours(image,contours,CV_RETR_EXTERNAL,CV_CHAIN_APPROX_NONE);

10.// draw

11. Mat result(image.size(),CV_8U,Scalar(0));

12. drawContours(result,contours,-1,Scalar(255),2);

13.

14. namedWindow("contours");

15. imshow("contours",result);

16. waitKey();

17.return 0;

18.}

上面程序中包含了2个函数,第一个是查找轮廓函数,它的第三个参数说明查找轮廓的类型,这里我们使用的是外轮廓,还可以查找所有轮廓,即包括一些孔洞的部分,像图像人物胳膊与腰间形成的轮廓。第4个参数说明了轮廓表示的方法,程序中的参数说明轮廓包括了所有点,也可以用其他参数让有点直线的地方,只保存直线起始与终点的位置点,具体参数用法可以参考手册里函数的介绍。

第二个函数drawContours是一个画轮廓的函数,它的第3个参数程序里设置-1表示所有的轮廓都画,你也可以指定要画的轮廓的序号。

提取到轮廓后,其实我们更关心的是如果把这些轮廓转换为可以利用的特征,也就是涉及到轮廓的描述问题,这时就有多种方法可以选择,比如矢量化为多边形、矩形、椭圆等。OpenCV里提供了一些这样的函数。

1.// 轮廓表示为一个矩形

2. Rect r=boundingRect(Mat(contours[0]));

3. rectangle(result,r,Scalar(255),2);

4.

5.// 轮廓表示为一个圆

6.float radius;

7. Point2f center;

8. minEnclosingCircle(Mat(contours[1]),center,radius);

9. circle(result,Point(center),static_cast(radius),Scalar(255),2);

10.

11.// 轮廓表示为一个多边形

12. vector poly;

13. approxPolyDP(Mat(contours[2]),poly,5,true);

14. vector::const_iterator itp=poly.begin();

15.while(itp!=(poly.end()-1))

16. {

17. line(result,*itp,*(itp+1),Scalar(255),2);

18. ++itp;

19. }

20. line(result,*itp,*(poly.begin()),Scalar(255),2);

21.// 轮廓表示为凸多边形

22. vector hull;

23. convexHull(Mat(contours[3]),hull);

24. vector::const_iterator ith=hull.begin();

25.while(ith!=(hull.end()-1))

26. {

27. line(result,*ith,*(ith+1),Scalar(255),2);

28. ++ith;

29. }

30. line(result,*ith,*(hull.begin()),Scalar(255),2);

程序中我们依次画了矩形、圆、多边形和凸多边形。最终效果如下:

对连通区域的分析到此远远没有结束,我们可以进一步计算每一个连通区域的其他属性,比如:重心、中心矩等特征,这些内容以后有机会展开来写。

以下几个函数可以尝试:minAreaRect:计算一个最小面积的外接矩形,contourArea可以计算轮廓内连通区域的面积;pointPolygenTest可以用来判断一个点是否在一个多边形内。mathShapes可以比较两个形状的相似性,相当有用的一个函数。

OpenCV成长之路(8)直线、轮廓的提取与描述

OpenCV成长之路(8):直线、轮廓的提取与描述 分类:OpenCV成长之路2014-01-04 18:35 689人阅读评论(0) 收藏举报 直线、轮廓的提取与描述基于内容的图像分析的重点是提取出图像中具有代表性的特征,而线条、轮廓、块往往是最能体现特征的几个元素,这篇文章就针对于这几个重要的图像特征,研究它们在OpenCV中的用法,以及做一些简单的基础应用。 一、Canny检测轮廓 在上一篇文章中有提到sobel边缘检测,并重写了soble的C++代码让其与matlab中算法效果一致,而soble边缘检测是基于单一阈值的,我们不能兼顾到低阈值的丰富边缘和高阈值时的边缘缺失这两个问题。而canny算子则很好的弥补了这一不足,从目前看来,canny边缘检测在做图像轮廓提取方面是最优秀的边缘检测算法。 canny边缘检测采用双阈值值法,高阈值用来检测图像中重要的、显著的线条、轮廓等,而低阈值用来保证不丢失细节部分,低阈值检测出来的边缘更丰富,但是很多边缘并不是我们关心的。最后采用一种查找算法,将低阈值中与高阈值的边缘有重叠的线条保留,其他的线条都删除。 本篇文章中不对canny的算法原理作进一步说明,稍后会在图像处理算法相关的文章中详细介绍。 下面我们用OpenCV中的Canny函数来检测图像边缘 1.int main() 2.{ 3. Mat I=imread("../cat.png"); 4. cvtColor(I,I,CV_BGR2GRAY); 5. 6. Mat contours; 7. Canny(I,contours,125,350); 8. threshold(contours,contours,128,255,THRESH_BINARY); 9. 10. namedWindow("Canny"); 11. imshow("Canny",contours);

opencv 椭圆检测识别并画出轮廓

*#include "stdafx.h" #include "cv.h" #include "highgui.h" using namespace cv; using namespace std; //标示符的可见范围 CvPoint2D32f GetCPoint(IplImage* imageFg,int maxX); void FitEllipseBlob(IplImage* imageFg); int main( int argc, char** argv ) { IplImage* pImg; //声明IplImage指针 //载入图像 pImg = cvLoadImage( "C:\\Users\\BB\Desktop\\bec\\OPENCV椭圆拟合定位椭圆中心点以及重心法定位程序\\OPENCV椭圆拟合定位椭圆中心点以及重心法定位程序\\特征中心点提取误差分析\\image.bmp", 1);//[[此处的argc==2是否需要改成argc==1?我改了之后才能运行成功。求大牛解惑]] // wmzzzz : 在"属性"|"debug"|里的command arguments 里加入参数(一个路径:要打开的文件路径) 这时argc==2 就合理了...可以试试多加几个 int pointX = 0; for (int i=0;i<19;i++) { pointX=60*i+30; cvEllipse(pImg,cvPoint(pointX,80),cvSize(19,20),-200,0,360,CV_RGB(255,255,255),-1,CV _AA,0); } IplImage* m_imageGray = cvCreateImage(cvSize(pImg->width,pImg->height),IPL_DEPTH_8U,1); IplImage* m_imageBw = cvCreateImage(cvSize(pImg->width,pImg->height),IPL_DEPTH_8U,1); cvCvtColor(pImg,m_imageGray,CV_RGB2GRAY); cvThreshold(m_imageGray,m_imageBw,128,255,CV_THRESH_BINARY); CvPoint2D32f pointXX; float XXX,YYY; for (int i = 0;i<19;i++) {

人脸检测算法原理及OPENCV人脸检测程序分析

人脸检测算法原理及OpenCV 人脸检测程序分析 罗海风 2011-3-30 人脸检测研究背景:人脸检测 基于肤色特征基于灰度特征 启发模型统计模型 肤色区域分割方法人脸模板方法等特征空间方法PCA 、fisherfaces 方法等ANN SVM 概率模型方法 贝叶斯概率模型HMM 集成机器学习 以上所列方法中,基于统计模型的方法是目前比较流行的方法[1],具有较大的优越性。其优点有: 1.不依赖于人脸的先验知识和参数模型,可以避免不精确或不完整的知识造成的错误; 2.采用实例学习的方法获取模型的参数,统计意义上更加可靠; 3.通过增加学习的实例可以扩种检测模式范围,提高鲁棒性。 在统计模型方法中,2001年左右由Viola 和Jones 提出的基于集成机器学习的人脸检测算法相对于其他方法具有明显优势[123]。近期文献也表明目前尚未发现优于Viola &Jones 方法的其他人脸检测方法[4]。该方法不仅检测精度高,最关键的是其运算速度大大快于其他方法。Viola &Jones 人脸检测方法原理: 该方法中几个关键性概念[5]: 1.Haar-like 特征 Haar-like 型特征是Viola 等人提出的一种简单矩形特征,因为类似Haar 小波而得名。Haar

型特征的定义是黑色矩形和白色矩形在图像子窗口中对应的区域的权重灰度级总和之差。上图显示了两种最简单的特征算子。在上述图中,可以看到,在人脸特定结构处,算子计算得到较大的值。 2.积分图 算子数量庞大时上述计算量显得太大,Viola等人发明了积分图方法,使得计算速度大大加快。积分图如上所示,点1处的值为A区域的像素积分,点2处的值为AB区域的像素积分。对整张图片进行一次积分操作,便可以方便的计算出任一区域D像素积分值为4+1-2-3。 3.Adaboost训练算法 在离散Adaboost算法中,Haar-like特征算子计算结果减去某阈值,便可视为一个人脸检测器。因为其准确率不高,称为弱分类器。Adaboost算法的循环中,首先利用各种弱分类器对训练图片库进行分类,准确度最高的弱分类器保留下来,同时提高判断错误的图片的权重,进入下一循环。最终将每次循环所保留的弱分类器组合起来,成为一个准确的人脸检测器,称为强分类器。具体计算流程见[35]。 4.瀑布型级联检测器 瀑布型级联检测器是针对人脸检测速度问题提出的一种检测结构。瀑布的每一层是一个由adaboost算法训练得到的强分类器。设置每层的阈值,是的大多数人脸能够通过,在此基础上尽量抛弃反例。位置越靠后的层越复杂,具有越强的分类能力。 这样的检测器结构就想一系列筛孔大小递减的筛子,每一步都能筛除一些前面筛子楼下的反例,最终通过所有筛子的样本被接受为人脸。瀑布型检测器训练算法见[3]。 OpenCV人脸检测程序流程[6]: OpenCV的人脸检测程序采用了Viola&Jones人脸检测方法,主要是调用训练好的瀑布级联分类器cascade来进行模式匹配。 cvHaarDetectObjects,先将图像灰度化,根据传入参数判断是否进行canny边缘处理(默认不

OPENCV实现的轮廓检测与处理

// // The full "Square Detector" program. // It loads several images subsequentally and tries to find squares in // each image // #ifdef _CH_ #pragma package #endif #ifndef _EiC #include "cv.h" #include "highgui.h" #include #include #include #endif int thresh = 50; IplImage* img = 0; IplImage* img0 = 0; CvMemStorage* storage = 0; CvPoint pt[4]; const char* wndname = "Square Detection Demo"; // helper function: // finds a cosine of angle between vectors // from pt0->pt1 and from pt0->pt2 double angle( CvPoint* pt1, CvPoint* pt2, CvPoint* pt0 ) { double dx1 = pt1->x - pt0->x; double dy1 = pt1->y - pt0->y; double dx2 = pt2->x - pt0->x; double dy2 = pt2->y - pt0->y; return (dx1*dx2 + dy1*dy2)/sqrt((dx1*dx1 + dy1*dy1)*(dx2*dx2 + dy2*dy2) + 1e-10); } // returns sequence of squares detected on the image. // the sequence is stored in the specified memory storage CvSeq* findSquares4( IplImage* img, CvMemStorage* storage ) { CvSeq* contours; int i, c, l, N = 11; CvSize sz = cvSize( img->width & -2, img->height & -2 ); IplImage* timg = cvCloneImage( img ); // make a copy of input image

opencv adaboost人脸检测训练程序阅读笔记(LBP特征)

1、训练程序整体流程 (1)读输入参数并打印相关信息 (2)进入训练程序最外层入口classifier.train 1)读正负样本,将正负样本放入imgLiast中,先读正样本,后读负样本 2)load( dirName )判断之前是否有已训练好的xml文件,若有,不在重新训练该stage的xml文件,没有返回false,初始化参数 3)计算requiredLeafFARate = pow(maxFalseAlarm,numStages)/max_depth,该参数是stage停止条件(利用训练样本集来计算tempLeafFARate,若 tempLeafFARate小于这一参数,则退出stage训练循环); 4)Stage训练循环 5)更新训练样本集,计算tempLeafFARate(负样本被预测为正样本的个数除以读取负样本的次数,第一次没有训练之前,这个比值为1,因为没训练之前, 所有负样本都被预测成了正样本,当第一层训练好以后,负样本采集时会先 用第一层的分类器预测一次,若能分类,则不选用,选用负样本的数目是固 定的,但选用这么多负样本总共要选的次数会随着层数的增多而加大,因为 层数越大,分类器的分类能力也要求越大,说需要的样本就是前面分类器所 不恩呢该识别的,故在采集时也比较困难。) 6)判断stage是否退出训练,若tempLeafFARatetrain() a.建立训练数据data = new CvCascadeBoostTrainData(主要是一些参 数的设置,还有特征值的计算) b.初始化样本权重update_weights( 0 ); c.弱分类器训练循环 i)tree->train—》do_train ai) 根节点的初始root = data->subsample_data( _subsample_idx ); (主要是对根节点的一些参数进行初始化,parent 0,count 1, split 0,value 0,class_idx 0,maxlr 0,left = right = 0,等等) bi) CV_CALL( try_split_node(root)),根据根节点计算整颗数的各 节点的参数配置 aii) calc_node_value( node );计算节点的回归值,类似于分类 投票值sum(w*class_lable),正样本的class_lable取,负样 本的class_lable取-1;计算节点的风险值node_risk,node risk is the sum of squared errors: sum_i((Y_i - )^2) bii) 判断节点是否可以分裂(判断依据:样本值和设计的节点最 大深度);再利用node_risk与regression_accuracy,如 果这个节点的所有训练样本的节点估计值的绝对差小 于这个参数,节点不再进行分裂 cii) 找出最佳分裂best_split = find_best_split(node); aiii) 定义DTreeBestSplitFinder finder( this, node ); biii) parallel_reduce(cv::BlockedRange(0, data->var_count), finder); 此时调用DTreeBestSplitFinder类的操作符 DTreeBestSplitFinder::operator()(constBlockedRange

基于OpenCV的边缘检测算法在车身尺寸检测中的应用

万方数据

万方数据

万方数据

2010年6月中同制造、Ip信息化第39卷第11期 图2汽车车身部分原始图像1图4基于本文算法的处理结果1 图3汽车车身部分原始图像2图5基于本文算法的处理结果2 方便,具有广阔的应用前景。本文针对灰度分布不 均匀的图像,首先,通过对图像开窗后进行局部灰参考文献: 碱∞∞Pan肌AnalysisandM8ch妇1n‘e11igence,1986,度变换来改进边缘检测的效果,对窗口交界处再开hiCannyJA.Ccmaputationalapproachtoedgedetection[J].IEEE 设几个很小的窗口实现拼接来去除窗口交界处的 皇假边缘;其次,詈用自适璺阈值的改进型Canny[2]8章(6毓)晋:67.图9-像69处8理.与分析[M】.|匕京:清华大学出版社,1999:算法动态地随图像梯度幅值变化而变化。通过试懈一枷 验证明,本文的方法对于不同噪声干扰和光照背景[3]杨枝灵,王开.WLsualc++数字图像获取、处理及实践应下的图像,能够获得较好的处理效果,其抗噪性能用[M].北京:人民邮电出版社,2003:553—572. 好,定位精度高。利用该算法对汽车图像进行边缘[4]刑果?戚文芽,李萍,等?灰度图像的自适应边缘检测 [J].计算机工程与应用,2007,43(5):63—66? 检测,检测出的汽车边缘连续、清晰。 ApplicationofOpenCV——basedEdgeDetectionAgorithm intheVehicle——bodyDimensionDetection CHENWei—li,TANG/-Ion,GENGYah—biao (NorthwesternPolytechnicalUniversity,ShaanxiXi’aJl,710072,China) Abstract:Itmainlyintroducesthesolutiontoimprovetheefficiencyoftheedgedetection,whichcombinesthe detectionalgorithmofthestatisticalimagewindowcalculationwiththeenhancedCannyedgedetectionalgo—rithm.ItusesOpenCVdatabase雒basicfunctionlibraryandappliesthisagorithmtothevehicle—bodydi—mensiondetection.Thetestresultsshowthattheprocessingofedgedetectionismoreeffectiveandquicker.Keywords:Edge——detection;ImageProcess;Vehicle——bodyDimension 万方数据

视觉里程计原理(一)特征提取(SURF算法)

MPIG Seminar0045 Feature Extraction 陈伟杰 Machine Perception and Interaction Group (MPIG) https://www.360docs.net/doc/03488981.html, cwj@https://www.360docs.net/doc/03488981.html,

Feature Extraction Refined based on the book: Mastering OpenCV with Practical Computer Vision Projects_full.pdf and Bay H, Tuytelaars T, Van Gool L. Surf: Speeded up robust features [M]. Computer vision–ECCV 2006. Springer. 2006: 404-417.

or F for [R|t]Drawing path The main steps of Visual Odometry images parameters Feature Extraction Feature matching Compute E

First Feature Extraction What feature is? Characteristics can be easily identified in images Edges Corners Blobs lines points

Harris SIFT SURF Commonly used algorithm: ?Corner extractor ?Fast operation ?Poor resolution ?Not applicable when scale changes ?Blobs extractor ?Slow operation ?Good resolution ?Scale invariance ?Upgrade from SIFT ?Speed up ?More robust

最新Canny边缘检测与轮廓提取汇总

C a n n y边缘检测与轮 廓提取

摘要................................................................................................................................................... Abstract.......................................................................................................................................... I 1 绪论 0 2 设计内容与OpenCV简介 (1) 2.1 设计任务内容 (1) 2.2 OpenCV简介 (1) 3 理论分析 (2) 3.1 边缘检测 (2) 3.1.1 图像的边缘 (2) 3.1.2 边缘检测的基本步骤 (2) 3.2 轮廓提取 (3) 4 边缘检测的算法比较 (4) 4.1 Reborts算子 (4) 4.2 Sobel算子 (5) 4.3 Prewitt 算子 (5) 4.4 Kirsch 算子 (7) 4.5 LOG算子 (7) 4.6 Canny算子 (8) 5 实验仿真 (10) 5.1算法设计 (10) 5.2 实验结果 (11) 6 分析与总结 (12) 参考文献 (13) 附录 (14)

边缘检测是图像处理和计算机视觉中的基本问题,它的目的是标识出数字图像中亮度变化明显的点。图像经过边沿检测处理之后,不仅大幅度地减少了数据量,并且剔除了可以认为不相关的信息,保留了图像重要的结构属性。 事实上,边缘存在于图像的不规则结构和不平稳现象中,也即存在于信号的突变点处,这些点给出了图像轮廓的位置。这些轮廓常常是我们在图像边缘检测时,所需要的非常重要的一些特征条件,这就需要我们对一幅图像检测并提取出它的边缘。 可用于图像边缘检测和轮廓提取的方法有很多,其中包括有常见的Robert边缘算子、Prewitt 边缘算子、Sobel边缘算子等等。本文首先将会从数字图像处理的角度,对几种边缘检测算法进行详细的分析,然后会并选择其中一种边缘检测算法进行实验。考虑到以后进一步的学习,本文将会使用openCV对算法进行实现。最后,本文将会把实验获得的实际效果,与理论分析的结果进行比对,并以此对本次实验进行总结。 关键字:边缘检测轮廓提取图像处理openCV

opencv特征提取解析

特征提取是计算机视觉和图像处理中的一个概念。它指的是使用计算机提取图像信息,决定每个图像的点是否属于一个图像特征。特征提取的结果是把图像上的点分为不同的子集,这些子集往往属于孤立的点、连续的曲线或者连续的区域。 特征的定义 至今为止特征没有万能和精确的定义。特征的精确定义往往由问题或者应用类型决定。特征是一个数字图像中“有趣”的部分,它是许多计算机图像分析算法的起点。因此一个算法是否成功往往由它使用和定义的特征决定。因此特征提取最重要的一个特性是“可重复性”:同一场景的不同图像所提取的特征应该是相同的。 特征提取是图象处理中的一个初级运算,也就是说它是对一个图像进行的第一个运算处理。它检查每个像素来确定该像素是否代表一个特征。假如它是一个更大的算法的一部分,那么这个算法一般只检查图像的特征区域。作为特征提取的一个前提运算,输入图像一般通过高斯模糊核在尺度空间中被平滑。此后通过局部导数运算来计算图像的一个或多个特征。 有时,假如特征提取需要许多的计算时间,而可以使用的时间有限制,一个高层次算法可以用来控制特征提取阶层,这样仅图像的部分被用来寻找特征。 由于许多计算机图像算法使用特征提取作为其初级计算步骤,因此有大量特征提取算法被发展,其提取的特征各种各样,它们的计算复杂性和可重复性也非常不同。 边缘 边缘是组成两个图像区域之间边界(或边缘)的像素。一般一个边缘的形状可以是任意的,还可能包括交叉点。在实践中边缘一般被定义为图像中拥有大的梯度的点组成的子集。一些常用的算法还会把梯度高的点联系起来来构成一个更完善的边缘的描写。这些算法也可能对边缘提出一些限制。

局部地看边缘是一维结构。 角 角是图像中点似的特征,在局部它有两维结构。早期的算法首先进行边缘检测,然后分析边缘的走向来寻找边缘突然转向(角)。后来发展的算法不再需要边缘检测这个步骤,而是可以直接在图像梯度中寻找高度曲率。后来发现这样有时可以在图像中本来没有角的地方发现具有同角一样的特征的区域。 区域 与角不同的是区域描写一个图像中的一个区域性的结构,但是区域也可能仅由一个像素组成,因此许多区域检测也可以用来监测角。一个区域监测器检测图像中一个对于角监测器来说太平滑的区域。区域检测可以被想象为把一张图像缩小,然后在缩小的图像上进行角检测。 脊 长条形的物体被称为脊。在实践中脊可以被看作是代表对称轴的一维曲线,此外局部针对于每个脊像素有一个脊宽度。从灰梯度图像中提取脊要比提取边缘、角和区域困难。在空中摄影中往往使用脊检测来分辨道路,在医学图像中它被用来分辨血管。 特征抽取 特征被检测后它可以从图像中被抽取出来。这个过程可能需要许多图像处理的计算机。其结果被称为特征描述或者特征向量。 常用的图像特征有颜色特征、纹理特征、形状特征、空间关系特征。 一、颜色特征 (一)特点:颜色特征是一种全局特征,描述了图像或图像区域所对应的景物的表面性质。一般颜色特征是基于像素点的特征,此时所有属于图像或图像区

图像处理经典算法及OpenCV程序

基于opencv的use摄像头视频采集程序 (1) 基于opencv的两个摄像头数据采集 (3) 能激发你用代码做视频的冲动程序 (6) 图像反转(就是把黑的变白,白的变黑) (11) 图像格式的转换 (12) 从摄像头或者A VI文件中得到视频流,对视频流进行边缘检测 (13) 采用Canny算子进行边缘检测 (15) 角点检测 (18) 图像的旋转加缩放(效果很拽,用地球做就像谷歌地球似的) (21) Log-Polar极坐标变换 (22) 对图像进行形态学操作(图像的开闭,腐蚀和膨胀运算) (24) 用不同的核进行图像的二维滤波 (27) 图像域的填充 (30) 寻找轮廓实现视频流的运动目标检测(超推荐一下) (35) 采用金字塔方法进行图像分割 (40) 图像的亮度变换 (43) 单通道图像的直方图 (46) 计算和显示彩色图像的二维色调-饱和度图像 (48) 图像的直方图均匀化 (50) 用Hongh变换检测线段 (52) 利用Hough变换检测圆(是圆不是椭圆) (57) 距离变换 (59) 椭圆曲线拟合 (64) 由点集序列或数组创建凸外形 (68) Delaunay三角形和V oronoi划分的迭代式构造 (71) 利用背景建模检测运动物体(推荐) (78) 运动模板检测(摄像头) (81) 显示如何利用Camshift算法进行彩色目标的跟踪 (86) 基于opencv的use摄像头视频采集程序 准备工作:你得把opencv库装到电脑上,并把各种头文件,源文件,lib库都连到vc上,然后设置一下系统环境变量,这里这方面就不说了,好像我前面的文章有说过,不懂也可百度一下。 建立一个基于WIN32控制台的工程CameraUSB,在新建一个c++元文件,写代码: #include "cxcore.h" #include "cvcam.h" #include "windows.h" #include "highgui.h"

opencv 人脸识别 (二)训练和识别

?转为灰度和对齐是后面做训练时EigenFaceRecognizer的要求; ?归一化是防止光照带来的影响 在上一篇的 2.2 Prehelper.cpp文件中加入函数 void resizeandtogray(char* dir,int k, vector &images, vector &labels, vector &testimages, vector &testlabels); [cpp]view plaincopyprint?

1.void resizeandtogray(char* dir,int K, vector &images, vector &l abels, 2. vector &testimages, vector &testlabels) 3.{ 4. IplImage* standard = cvLoadImage("D:\\privacy\\picture\\photo\\2.jpg" ,CV_LOAD_IMAGE_GRAYSCALE); 5. string cur_dir; 6.char id[5]; 7.int i,j; 8. for(int i=1; i<=K; i++) 9. { 10. cur_dir = dir; 11. cur_dir.append("gray\\"); 12. _itoa(i,id,10); 13. cur_dir.append(id); 14. const char* dd = cur_dir.c_str(); 15. CStatDir statdir; 16. if (!statdir.SetInitDir(dd)) 17. { 18. puts("Dir not exist"); 19. return; 20. } 21. cout<<"Processing samples in Class "<file_vec = statdir.BeginBrowseFilenames("*.*"); 23. for (j=0;j

OpenCV Haar人脸检测的代码分析

OpenCV Haar人脸检测的代码分析 /* cascade or tree of stage classifiers */ int flags; /* signature */ int count; /* number of stages */ CvSize orig_window_size; /* original object size (the cascade is trained for) */ /* these two parameters are set by cvSetImagesForHaarClassifierCascade */ CvSize real_window_size; /* current object size */ double scale; /* current scale */ CvHaarStageClassifier* stage_classifier; /* array of stage classifiers */ CvHidHaarClassifierCascade* hid_cascade; /* hidden optimized representation of the cascade, created by cvSetImagesForHaarClassifierCascade */ 所有的结构都代表一个级联boosted Haar分类器。级联有下面的等级结构: Cascade: Stage1: Classifier11: Feature11 Classifier12:

Feature12 ... Stage2: Classifier21: Feature21 ... ... 全部等级可以手农构修,也可以应用函数cvLoadHaarClassifierCascade从已有的磁盘文件或嵌进式基中导进。特征检测用到的函数: cvLoadHaarClassifierCascade 从文件中装载练习佳的级联分类器或者从OpenCV中嵌入的分类器数据库中导入 CvHaarClassifierCascade* cvLoadHaarClassifierCascade( const char* directory, CvSize orig_window_size ); directory :练习的级联分类器的门路 orig_window_size:级联分类器训练中采取的检测目标的尺寸。由于这个信息没有在级联分类器中存储,所有要共同指出。 函数cvLoadHaarClassifierCascade 用于从文件中装载训练赖的利用海尔特点的级联分类器,或者从OpenCV中嵌入的分类器数据库中导入。分类器的训练可以利用函数haartraining(具体观察

opencv成长之路:特征点检测与图像匹配

OpenCV成长之路(9):特征点检测与图像匹配 特征点检测与图像匹配 称兴趣点、关键点,它是在图像中突出且具有代表意义的一些点,通过这些点我们可以用来识别图像、进行图像配准、进行3D重建等。本文主要介绍OpenCV中几种定位与表示关键点的函数。 一、Harris角点 角点是图像中最基本的一种关键点,它是由图像中一些几何结构的关节点构成,很多都是线条之间产生的交点。Harris 角点是一类比较经典的角点类型,它的基本原理是计算图像中每点与周围点变化率的平均值。 (1) (2) 其中I(x+u,y+u)代表了点(x,y)邻域点的灰度值。通过变换可以将上式变化为一个协方差矩阵求特征值的问题(2),具体数学原理本文不过多描述。 OpenCV的Hairrs角点检测的函数为cornerHairrs(),但是它的输出是一幅浮点值图像,浮点值越高,表明越可能是特征角点,我们需要对图像进行阈值化。我们使用一张建筑图像

来显示: int main() { Mat image=imread("../buliding.png"); Mat gray; cvtColor(image,gray,CV_BGR2GRAY); Mat cornerStrength; cornerHarris(gray,cornerStrength,3,3,0.01); threshold(cornerStrength,cornerStrength,0.001,255,THRESH_B INARY); return 0; } 首先我们来说明一下cornerHairrs()这个函数参数的意思: 前2参数是输入与输出,输入是一个灰度图像,输出是一个浮点图像,第三个参数指定角点分析的邻域,第4个参数实际上在角点求取过程中计算梯度图像的核窗口大小,第5个参数是它原理公式(2)中的一个系数。 从上面的例子的结果我们可以看到,有很多角点都是粘连在一起的,我们下面通过加入非极大值抑制来进一步去除一些粘在一起的角点。 非极大值抑制原理是,在一个窗口内,如果有多个角点则用值最大的那个角点,其他的角点都删除,窗口大小这里我们用3*3,程序中通过图像的膨胀运算来达到检测极大值的目的,因为默认参数的膨胀运算就是用窗口内的最大值替代当前的灰度值。程序的最后使用了一个画角点的函数将角点显示在图像中,这个函数与本系列第5篇中画角点的函数是一致的。

opencv实现canny边缘检测

实验二 OpenCv实现Canny边缘检测 一、实验目的 1、了解如何在VC++6.0上安装与配置opencv 2、了解canny边缘检测的原理与opencv的实现 二、实验引言 边缘是一幅图像最重要的特征之一,图像边缘部分集中了图像的大部分信息。因此,边缘的确定对于图像场景的识别与理解非常重要;同时在图像分割中也有重要应用。可以利用边缘对图像进行区域分析。边缘在图像体现为局部区域亮度的显著变化,可见这种变化是为灰度面的阶跃。有很多种方法可以用来对图像边缘进行检测。本实验中采用Canny边缘检测。 三、实验原理 检测阶跃边缘的基本思想是在图像中找出具有局部最大梯度值的像素点,其大部分的工作集中在寻找能够用于实际图像的梯度数字逼近。 图像梯度逼近必须满足要求: 1、逼近必须能够抑制噪声效应 2、必须尽量精确的确定边缘的位置 Canny检测的基本过程 平滑与计算 Canny边缘检测器就是高斯函数的一阶导数,是对信噪比与定位之间最优化的逼近算子。高斯平滑和梯度逼近结合的算子不是旋转对称的。高斯平滑和梯度逼近结合的算子不是旋转对称的。 在边缘方向是对称的,在垂直边缘方向是反对称的(梯度方向)。该算子在对最急剧变化方向上的边缘很敏感,沿边缘方向不敏感。 非极大值抑制

前面的计算得到梯度的幅度图像阵列为M[i,j],此值的值越大,其对应的图像梯度值也越大。但还不能精确的确定边缘。为了确定边缘,必须细化幅度值图像中的屋脊带(ridge ),即只保留幅度值局部变化最大的点。此过程称为非极大值抑制(non-maxima suppression,NMS ),其结果会产生细化的边缘。非极大值抑制通过抑制梯度线上所有的非屋脊峰值的幅度值来细化[,]M i j 中的梯度幅值屋脊。算法使用一个3×3邻域作用在幅值阵列[,]M i j 的所有点上;每一个点上,邻域的中心像素[,]M i j 与沿着梯度线的两个元素进行比较,其中梯度线是由邻域的中心点处的扇区值ζ[i,j ]给出。如果在邻域中心点处的幅值[,]M i j 不比梯度线方向上的两个相邻点幅值大,则[,]M i j 赋值为零,否则维持原值;此过程可以把M[i,j]宽屋脊带细化成只有一个像素点宽,即保留屋脊的高度值。 非极大值抑制公式为: [,]([,],[,])N i j NMS M i j i j z = [,]N i j 中的非零值对应着图像强度阶跃变化处对比度,其坐标对应着图像梯度值经过非极大值抑制后细化得到的边缘。 虽然在边缘检测前经过了图像的高斯平滑,但是经过NMS 后仍然会包含许多噪声和细纹理引起的假边缘段。所以要经过阈值化处理。 阈值化 去除假边缘的方法是对[,]N i j 使用阈值处理,将低于某一阈值的所有值赋值零,得到图像边缘阵列[,]I i j 。 单阈值τ太低造成的假阳性以及阴影会使边缘对比度减弱; 单阈值t 太高造成的假阴性会使部分轮廓丢失; 常用双阈值1t 和212t t =对非极大值抑制图像[,]N i j 处理得到两个边缘图像1[,]T i j 和2[,]T i j 。2[,]T i j 用高阈值得到,所以含有较少的假边缘,但其中有轮廓的间断。双阈值要在2[,]T i j 中把边缘连接成轮廓,当到达轮廓端点时,就在1[,]T i j 的8邻点位置寻找可以连接到轮廓上的边缘。综述整个算法的主要步骤是:不断的在1[,]T i j 中收集边缘,直到2[,]T i j 中的所有间隙连接起来位置。 从而得出Canny 算法的具体实现步骤: Step1:用高斯滤波器平滑图像,去除图像噪声。一般选择方差为1.4的高斯函数模板和图像进行卷积运算。 Step2:用一阶偏导的有限差分来计算梯度的幅值和方向。使用 的梯度算子计算x 和y 方向的偏导数 和 ,方向角 ,梯度幅值 。 Step3:对梯度幅值应用非极大值抑制。幅值M 越大,其对应的图像梯度值也越大,但这

opencv之HOG特征详解与行人检测

HOG(Histogram of Oriented Gradient)特征在对象检测与模式匹配中是一种常见的特征提取算法,是基于本地像素块进行特征直方图提取的一种算法,对象局部的变形与光照影响有很好的稳定性,最初是用HOG特征来来识别人像,通过HOG特征提取+SVM训练,可以得到很好的效果,OpenCV已经有了。HOG特征提取的大致流程如下: 详细步骤 第一步:灰度化 对HOG特征提取来说第一步是对输入的彩色图像转换为灰度图像,图像灰度化的方法有很多,不同灰度化方法之间有一些微小的差异,从彩色到灰度的图像转换可以表示如下: 第二步:计算图像梯度 计算图像的X方向梯度dx与Y方向梯度dy,根据梯度计算mag与角度,计算梯度时候可以先高斯模糊一下(可选步骤),然后使用sobel或者其它一阶导数算子计算梯度值dx、dy、mag、angle:

第三步:Cell分割与Block 对于图像来说,分成8x8像素块,每个块称为一个Cell,每个2x2大小的 Cell称为一个Block,每个Cell根据角度与权重建立直方图,每20度为一 个BIN,每个Cell得到9个值、每个Block得到36个值(4x9), 图像如下: 每个Block为单位进行L2数据归一化,作用是抵消光照/迁移影响,L2的归一化的公式如下: 第四步:生成描述子 对于窗口64x128范围大小的像素块,可以得到8x16个Cell,使用Block 在窗口移动,得到输出的向量总数为7x15x36=3780特征向量,每次Block 移动步长是八个像素单位,一个Cell大小。

使用HOG特征数据 HOG特征本身是不支持旋转不变性与多尺度检测的,但是通过构建高斯金字塔实现多尺度的开窗检测就会得到不同分辨率的多尺度检测支持。OpenCV中HOG多尺度对象检测API如下: virtual void cv::HOGDescriptor::detectMultiScale( InputArray img, std::vector< Rect > & foundLocations, double hitThreshold = 0, Size winStride = Size(), Size padding = Size(), double scale = 1.05, double finalThreshold = 2.0, bool useMeanshiftGrouping = false ) Img-表示输入图像 foundLocations-表示发现对象矩形框 hitThreshold-表示SVM距离度量,默认0表示,表示特征与SVM分类超平面之间 winStride-表示窗口步长 padding-表示填充 scale-表示尺度空间 finalThreshold-最终阈值,默认为2.0 useMeanshiftGrouping-不建议使用,速度太慢拉 使用OpenCV预训练SVM行人HOG特征分类器实现多尺度行人检测的代码如下: import cv2 as cv if __name__ == '__main__': src = cv.imread("D:/images/pedestrian.png") cv.imshow("input", src)

Canny边缘检测与轮廓提取

摘要...................................................................................I Abstract ..............................................................................II 1 绪论 (1) 2 设计内容与OpenCV简介 (2) 2.1 设计任务内容 (2) 2.2 OpenCV简介 (2) 3 理论分析 (3) 3.1 边缘检测 (3) 3.1.1 图像的边缘 (3) 3.1.2 边缘检测的基本步骤 (3) 3.2 轮廓提取 (4) 4 边缘检测的算法比较 (5) 4.1 Reborts算子 (5) 4.2 Sobel算子 (5) 4.3 Prewitt 算子 (6) 4.4 Kirsch 算子 (7) 4.5 LOG算子 (7) 4.6 Canny算子 (8) 5 实验仿真 (10) 5.1算法设计 (10) 5.2 实验结果 (11) 6 分析与总结 (12) 参考文献 (13) 附录 (14)

边缘检测是图像处理和计算机视觉中的基本问题,它的目的是标识出数字图像中亮度变化明显的点。图像经过边沿检测处理之后,不仅大幅度地减少了数据量,并且剔除了可以认为不相关的信息,保留了图像重要的结构属性。 事实上,边缘存在于图像的不规则结构和不平稳现象中,也即存在于信号的突变点处,这些点给出了图像轮廓的位置。这些轮廓常常是我们在图像边缘检测时,所需要的非常重要的一些特征条件,这就需要我们对一幅图像检测并提取出它的边缘。 可用于图像边缘检测和轮廓提取的方法有很多,其中包括有常见的Robert边缘算子、Prewitt 边缘算子、Sobel边缘算子等等。本文首先将会从数字图像处理的角度,对几种边缘检测算法进行详细的分析,然后会并选择其中一种边缘检测算法进行实验。考虑到以后进一步的学习,本文将会使用openCV对算法进行实现。最后,本文将会把实验获得的实际效果,与理论分析的结果进行比对,并以此对本次实验进行总结。 关键字:边缘检测轮廓提取图像处理openCV

相关文档
最新文档