Opencv提取轮廓(去掉面积小于某个值的轮廓)
#include
#include "cv.h"
#include "cxcore.h"
#include "highgui.h"
#include
using namespace std;
#pragma comment(lib,"cv.lib")
#pragma comment(lib,"cxcore.lib")
#pragma comment(lib,"highgui.lib")
struct Position
{
int x,y;
};
double per[256];// 保存灰度概率
IplImage *FindCountours(IplImage* src,IplImage *pContourImg);
int ImageStretchByHistogram(IplImage *src,IplImage *dst);
IplImage* Hist_Equalization(IplImage *srcimg);
void proBorder(IplImage *src); // 边界的处理
void GetBackImage(IplImage* src,IplImage* src_back);
void Threshold(IplImage *src);
int GetThreshold(double *const prob);
void Getprobability(IplImage *src);
double Eccentricity(IplImage *src);
void main()
{
//IplImage * src = cvLoadImage("C:\\image19\\A634.jpg",-1);//灰度图的方式载入IplImage * src = cvLoadImage("C:\\image19\\A857.jpg",-1);
IplImage * dst = cvCreateImage(cvGetSize(src),IPL_DEPTH_8U,3);
IplImage *src_back = cvCreateImage(cvGetSize(src),IPL_DEPTH_8U,src->nChannels); GetBackImage(src,src_back);
dst = FindCountours(src_back,dst);
cvNamedWindow("test",CV_WINDOW_AUTOSIZE);
cvShowImage("test",dst);
cvWaitKey(0);
cvReleaseImage(&src);
cvReleaseImage(&dst);
}
void GetBackImage(IplImage* src,IplImage* src_back)
{
//cvCvtColor(src,src,CV_RGB2GRAY);//灰度化
IplImage *tmp = cvCreateImage(cvGetSize(src),IPL_DEPTH_8U,3);
// 创建结构元素
IplConvKernel *element = cvCreateStructuringElementEx( 2, 2, 0, 0,
CV_SHAPE_ELLIPSE,0);
//用该结构对源图象进行数学形态学的开操作后,估计背景亮度
cvErode(src,tmp,element,9);
//使用任意结构元素腐蚀图像
cvDilate(tmp,src_back, element,9);
//使用任意结构元素膨胀图像
}
IplImage *FindCountours(IplImage* src,IplImage *pContourImg)
{
CvMemStorage *storage = cvCreateMemStorage(0); //提取轮廓需要的储存容量0为默认64KB
CvSeq * pcontour = 0; //提取轮廓的序列指针
IplImage *temp = cvCreateImage(cvGetSize(src),src->depth,1);
//cvSmooth(src,temp,CV_GAUSSIAN,3,1,0);
cvSmooth(src,src,CV_GAUSSIAN,3,1,0);//平滑处理
cvCvtColor(src,temp,CV_RGB2GRAY);//灰度化
Getprobability(temp);
printf("最好的阈值:%d\n",GetThreshold(per));
//Threshold(temp);
proBorder(temp);
cvThreshold(temp,temp,GetThreshold(per),255,CV_THRESH_BINARY_INV);
int contoursNum = 0; // 轮廓数量
//int mode = CV_RETR_LIST;
int mode = CV_RETR_EXTERNAL;// 提取最外层轮廓
contoursNum =
cvFindContours(temp,storage,&pcontour,sizeof(CvContour),mode,CV_CHAIN_APPROX_NO NE);
// contoursNum =
cvFindContours(temp,storage,&pcontour,sizeof(CvContour),CV_RETR_LIST,CV_CHAIN_A PPROX_SIMPLE,cvPoint(0,0));
//二值图, 得到轮廓存储,轮廓指针序列,header_size,提取模式,逼近方法
CvScalar externalColor;// 保存颜色值
CvScalar holeColor;
//--------------画轮廓----------------//
for (; pcontour != 0; pcontour=pcontour -> h_next)
{
//holeColor=CV_RGB(rand()&255,rand()&255,rand()&255);
//externalColor=CV_RGB(rand()&255,rand()&255,rand()&255);
CvRect r = ((CvContour *)pcontour)->rect;
if(r.height * r.width < 800)
{
holeColor=CV_RGB(0,0,0);
externalColor=CV_RGB(0,0,0);
cvDrawContours(pContourImg,pcontour,externalColor,holeColor,1,1,8);
}
else
{
//取得轮廓面积
double contArea = fabs(cvContourArea(pcontour,CV_WHOLE_SEQ));
//取得轮廓长度
double contLenth = cvArcLength(pcontour,CV_WHOLE_SEQ,-1);
// 圆形度
double contcircularity = contLenth * contLenth / contArea;
double pxl =Eccentricity(temp);
cout<<"面积为:"< cout<<"周长为:"< cout<<"圆形度为:"< holeColor=CV_RGB(255,255,255); externalColor=CV_RGB(255,255,255); cvDrawContours(pContourImg,pcontour,externalColor,holeColor,1,1,8); } } //IplConvKernel *element = cvCreateStructuringElementEx( 2, 2, 0, 0, CV_SHAPE_ELLIPSE,0); //cvDilate(pContourImg,pContourImg, element,9); return pContourImg; } double Eccentricity(IplImage *src)//偏心率 { Position pos[4]; int width = src->width; int height = src->height; int i,j; for(i = 0; i < height; i++) { for(j = 0; j < width; j++) { int pixel = (int)cvGet2D(src,i,j).val[0]; if(pixel != 0) { pos[0].x = j; pos[0].y = i;// goto s; } } } s: for(i = height - 1; i >= 0; i--) { for(j = 0; j < width ; j++) { int pixel = (int)cvGet2D(src,i,j).val[0]; if(pixel != 0) { pos[1].x = j; pos[1].y = i;// goto w; } } } w: for(i = 0 ; i < width ; i++) { for(j = 0;j < height; j++) { int pixel = (int)cvGet2D(src,j,i).val[0]; if(pixel != 0) { pos[2].x = j;// pos[2].y = i; goto e; } } } e: for(i = width - 1; i >= 0; i--) { for(j = 0 ; j < height ; j++) { int pixel = (int)cvGet2D(src,j,i).val[0]; if(pixel != 0) { pos[3].x = j;// pos[3].y = i; goto f; } } } f: int l_dis = abs(pos[0].y - pos[1].y); int s_dis = abs(pos[2].x - pos[3].x); int tmp_dis; if(l_dis > s_dis) { printf("偏心率:%f\n",l_dis*1.0/s_dis); } else { tmp_dis = l_dis; l_dis = s_dis; s_dis = tmp_dis; printf("偏心率:%f\n",l_dis*1.0/s_dis); } return 0; } void Getprobability(IplImage *src) { memset(per,0,sizeof(per)); int width = src->width; int height = src->height; for(int i = 0; i < height; i++) { for(int j = 0; j < width; j++) { per[(int)cvGet2D(src,i,j).val[0]]++; } } int PixlNum = width * height; for(i = 0; i < 256; i++) per[i] = per[i] / PixlNum; } int GetThreshold(double *const prob) { int threshold = 0; double maxf = 0; for (int crrctThrshld = 1; crrctThrshld < 256 - 1; ++crrctThrshld) { double W0 = 0, W1 = 0, U0 = 0, U1 = 0; int i = 0; for (i = 0; i <= crrctThrshld; ++i) { U0 += i * prob[i]; W0 += prob[i]; } for (; i < 256; ++i) { U1 += i * prob[i]; W1 += prob[i]; } if (W1 == 0 || W1 == 0) continue; U0 /= W0; U1 /= W1; double D0 = 0, D1= 0; for (i = 0; i <= crrctThrshld; ++i) D0 += pow((i - U0) * prob[i], 2.0); for (; i < 256; ++i) D1 += pow((i - U1) * prob[i], 2.0); D0 /= W0; D1 /= W1; double Dw = pow(D0, 2.0) * W0 + pow(D1, 2.0) * W1; double Db = W0 * W1 * pow((U1 - U0), 2.0); double f = Db / (Db + Dw); if (maxf < f) { maxf = f; threshold = crrctThrshld; } } return threshold; } void proBorder(IplImage *src) // 边界的处理 { int i,j; int height = src->height; int width = src->width; int N = 100; for(i = 0; i < N * width; i += width) // i表示向下走左上角{ for(j = 0; j < N ; j++) { int index = i + j; src->imageData[index] = (char)255; } } int NN = 150; int sw = width * (height - NN);// 左下角三角形 int t = 1; for(i = sw; i < sw + NN * width; i += width,t++) { for(j = 0; j < t; j++) { int index = i + j; src->imageData[index] = (char)255; } } int se = (height - NN - 1) * width; // 右下角 t = 0; for(i = se; i < width * height ; i += width,t++) { for(j = 0; j < t; j++) { int index = i + j - t; src->imageData[index] = (char)255; } } int ne = width - NN; // 右上角三角形剪切t = 0; for(i = ne; i < NN * width; i +=width,t++) { for(j = 0; j < NN - t; j++) { int index = i + j + t; src->imageData[index] = (char)255; } } } void Threshold(IplImage *src) { int width = src->width; int height = src->height; float minpixel = cvGet2D(src,0,0).val[0]; float maxpixel = cvGet2D(src,0,0).val[0]; CvScalar s; for(int i = 0; i < height; i++){ for(int j = 0; j < width; j++){ s = cvGet2D(src,i,j); if(s.val[0] > maxpixel) maxpixel = s.val[0]; if(s.val[0] < minpixel) minpixel = s.val[0]; } } float firstgrey = (maxpixel + minpixel) / 2; printf("%f\n",firstgrey); float lastgrey; float sum1 = 0,sum2 = 0; int num1 = 0,num2 = 0; int result = 0; while(1) { result ++; for(i = 0; i < height; i++){ for(int j = 0; j < width; j++){ s = cvGet2D(src,i,j); if(s.val[0] < firstgrey) { sum1 += s.val[0]; num1++; } if(s.val[0] < firstgrey) { sum2 += s.val[0]; num2++; } } } lastgrey = (sum1/num1 + sum2/num2)/2; if((int)lastgrey == (int)firstgrey) break; else { firstgrey = lastgrey; sum1 = sum2 = 0; num1 = num2 = 0; } } lastgrey = (sum1/num1 + sum2/num2)/2; printf("%f %d\n",firstgrey,result); } 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); *#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++) { // // The full "Square Detector" program. // It loads several images subsequentally and tries to find squares in // each image // #ifdef _CH_ #pragma package 万方数据 万方数据 万方数据 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 万方数据 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的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 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实现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 越大,其对应的图像梯度值也越大,但这 摘要...................................................................................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 #include "cv.h" #include "highgui.h" #include Opencv提取轮廓(去掉面积小于某个值的轮廓) #include cvFindContours cvFindContours可以得到一个图象所有的轮廓, 返回的是轮廓的数量. 函数cvFindContours从二值图像中检索轮廓,并返回检测到的轮廓的个数。first_contour 的值由函数填充返回,它的值将为第一个外轮廓的指针,当没有轮廓被检测到时为NULL。其它轮廓可以使用h_next和连接,从first_contour到达。 h_next 同一个层次上的 v_next 父与子关系 int cvFindContours( CvArr* image, CvMemStorage* storage, CvSeq** first_contour, int header_size = sizeof(CvContour), int mode = CV_RETR_LIST, int method = CV_CHAIN_APPROX_SIMPLE, CvPoint offset=cvPoint(0,0) ); image:8比特单通道的源二值图像。非零像素作为1处理,0像素保存不变。从一个灰度图像得到二值图像的函数有:cvThreshold,cvAdaptiveThreshold和cvCanny。 Storage:返回轮廓的容器。 first_contour:输出参数,用于存储指向第一个外接轮廓。//动态序列 header_size:header序列的尺寸。 如果选择method = CV_CHAIN_CODE, 则header_size >= sizeof(CvChain); 其他,则header_size >= sizeof(CvContour)。 Mode:检索模式,可取值如下: CV_RETR_EXTERNAL:只检索最外面的轮廓; CV_RETR_LIST:检索所有的轮廓,并将其放入list中; CV_RETR_CCOMP:检索所有的轮廓,并将他们组织为两层:顶层是各部分的外部边界,第二层是空洞的边界; CV_RETR_TREE:检索所有的轮廓,并重构嵌套轮廓的整个层次。 Method:边缘近似方法(除了CV_RETR_RUNS使用内置的近似,其他模式均使用此设定的近似算法)。可取值如下: CV_CHAIN_CODE:以Freeman链码的方式输出轮廓,所有其他方法输出多边形(顶点的序列)。 CV_CHAIN_APPROX_NONE:将所有的连码点,转换成点。 CV_CHAIN_APPROX_SIMPLE:压缩水平的、垂直的和斜的部分,也就是,函数只保留他们的终点部分。 CV_CHAIN_APPROX_TC89_L1,CV_CHAIN_APPROX_TC89_KCOS:使用the flavors of Teh-Chin chain近似算法的一种。 CV_LINK_RUNS:通过连接水平段的1,使用完全不同的边缘提取算法。使用CV_RETR_LIST检索模式能使用此方法。 Open Source Computer Vision Library intro.html#SECTION00040000000000000000 https://www.wendangku.net/doc/af15665409.html,/chenyusiyuan/archive/2010/01/26/5259060.aspx 2.2 2、输入处理 2.2.1 (1)处理鼠标事件: 2.2.2 (2)处理键盘事件: 2.2.3 (3)处理滑动条事件: 3 三、OpenCV的基本数据结构 3.1 1、图像数据结构 3.1.1 (1) IPL 图像: 3.2 2、矩阵与向量 3.2.1 (1)矩阵: 3.2.2 (2)一般矩阵: 3.2.3 (3)标量: 3.3 3、其它结构类型 3.3.1 (1)点: 3.3.2 (2)矩形框大小(以像素为精度): 3.3.3 (3)矩形框的偏置和大小: 4 四、图像处理 4.1 1、图像的内存分配与释放 4.1.1 (1)分配内存给一幅新图像: 4.1.2 (2)释放图像: 4.1.3 (3)复制图像: 4.1.4 (4)设置/获取感兴趣区域ROI: 4.1.5 (5)设置/获取感兴趣通道COI: 4.2 2、图像读写 4.2.1 (1)从文件中读入图像: 4.2.2 (2)保存图像: 4.3 3、访问图像像素 4.3.1 (1)假设你要访问第k通道、第i行、第j列的像素。 4.3.2 (2)间接访问: (通用,但效率低,可访问任意格式的图像) 4.3.3 (3)直接访问: (效率高,但容易出错) 4.3.4 (4)基于指针的直接访问: (简单高效) 4.3.5 (5)基于 c++ wrapper 的直接访问: (更简单高效) 4.4 4、图像转换 4.4.1 (1)字节型图像的灰度-彩色转换: 4.4.2 (2)彩色图像->灰度图像: 4.4.3 (3)不同彩色空间之间的转换: 4.5 5、绘图指令 4.5.1 (1)绘制矩形: 4.5.2 (2)绘制圆形: 4.5.3 (3)绘制线段: 4.5.4 (4)绘制一组线段: 4.5.5 (5)绘制一组填充颜色的多边形: 4.5.6 (6)文本标注: 5 五、矩阵处理 5.1 1、矩阵的内存分配与释放 5.1.1 (1)总体上: 5.1.2 (2)为新矩阵分配内存: 5.1.3 (3)释放矩阵内存: 5.1.4 (4)复制矩阵: 5.1.5 (5)初始化矩阵: 5.1.6 (6)初始化矩阵为单位矩阵: 5.2 2、访问矩阵元素 5.2.1 (1)假设需要访问一个2D浮点型矩阵的第(i, j)个单元. 5.2.2 (2)间接访问: 5.2.3 (3)直接访问(假设矩阵数据按4字节行对齐): 5.2.4 (4)直接访问(当数据的行对齐可能存在间隙时 possible alignment gaps): 5.2.5 (5)对于初始化后的矩阵进行直接访问: 5.3 3、矩阵/向量运算 OpenCV特征提取与图像检索实现(附代码) “拍立淘”“一键识花”“街景匹配”……不知道大家在使用 这些神奇的功能的时候,有没有好奇过它们背后的技术原理?其实这些技术都离不开最基本的图像检索技术。本篇文章我们就将对这一技术的原理进行介绍,并通过一个简单的Python脚本来实现一个最基本的图像检索demo。 ▌图像特征 首先我们需要明白图像特征是什么以及它的使用方法。 图像特征是一种简单的图像模式,基于这种模式我们可以描述我们在图像上所看到的内容。例如,在一张跟猫有关的 图片中,猫咪的眼睛就可以作为这幅图像的特征。特征在(包括但不限于)计算机视觉中的主要作用是将视觉信息转换为向量空间表示。这种向量空间表示让我们可以利用数学运算对其进行处理,例如通过计算寻找相似向量(这可以用来寻找相似图像或图像中的相似目标)。 ▌如何从图像中获取特征? 从图像中获取特征的方法有两种,第一种是通过提取图像描述符实现(白盒算法);第二种通过基于神经网络的方法实 现(黑盒算法)。本文主要介绍第一种方法。 特征提取的算法有很多,最常用的有:SURF、ORB、SIFT、BRIEF等。这些算法大多是基于图像梯度的。为了简化安装 需求,本教程使用的是KAZE描述符,因为其他描述符在python的基础OpenCV库中没有提供。 下面是特征提取器的实现代码: import cv2 import numpy as np import scipy from scipy.misc import imread import cPickle as pickle import random import os import matplotlib.pyplot as plt # Feature extractor # 特征提取器 def extract_features(image_path, vector_size=32): image = imread(image_path, mode='RGB') try: # Using KAZE, cause SIFT, ORB and other was moved to additional module # which is adding addtional pain during install #此处为了简化安装步骤,使用KAZE,因为SIFT/ORB以及其他特征算子需要安 #装额外的模块 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:计算两个向量的点积; 1.// readbmp.cpp : Defines the entry point for the console application. 2.// 3. 4.#include "stdafx.h" 5.#include OpenCV成长之路(8)直线、轮廓的提取与描述
opencv 椭圆检测识别并画出轮廓
OPENCV实现的轮廓检测与处理
基于OpenCV的边缘检测算法在车身尺寸检测中的应用
最新Canny边缘检测与轮廓提取汇总
图像处理经典算法及OpenCV程序
OpenCV Haar人脸检测的代码分析
opencv实现canny边缘检测
Canny边缘检测与轮廓提取
Opencv视频运动跟踪代码
OpenCV根据面积提取轮廓
OpenCv中cvFindContours在程序中使用说明
OpenCV 编程简介教程(中文版),Image Processing, C
OpenCV特征提取与图像检索实现(附代码)
常用的OpenCV函数速查
opencv 实现的椭圆检测的源代码