精华内容
参与话题
问答
  • 利用OpenCV提取目标轮廓

    千次阅读 2012-03-26 09:22:59
    一个简单的提取飞机目标图像(二值图)轮廓的程序  #include  #include  #include  #include  IplImage* g_image = NULL;  IplImage* g_gray =NULL;  int g_thresh = 100;  CvMemStorage* g_...
    一个简单的提取飞机目标图像(二值图)轮廓的程序

        #include <cv.h>
        #include <highgui.h>
        #include <iostream.h>
        #include <stdio.h>
        IplImage* g_image = NULL;
        IplImage* g_gray =NULL;
        int g_thresh = 100;
        CvMemStorage* g_storage = NULL;
        char name[1][80];
        int Presskey;
        int main( int argc, char** argv )
        {
        if( argc==2 && ( g_image = cvLoadImage( argv[1], 1 ) ) != 0 )
        {
        cvNamedWindow( "Contours", 1 );
        if( g_storage == NULL )
        {
        g_gray = cvCreateImage( cvGetSize(g_image), 8, 1 );
        g_storage = cvCreateMemStorage(0);
        }
        else
        {
        cvClearMemStorage( g_storage );
        }
        CvSeq* contours = 0;
        cvCvtColor( g_image, g_gray, CV_BGR2GRAY );
        //cvThreshold( g_gray, g_gray, g_thresh, 255, CV_THRESH_BINARY );
        cvFindContours( g_gray, g_storage, &contours );
        cvZero( g_gray );
        if( contours )
        {
        cvDrawContours(
        g_gray,
        contours,
        cvScalarAll(255),
        cvScalarAll(255),
        1);
        }
        cvShowImage( "Contours", g_gray );
        Presskey=cvWaitKey();
        printf("%c is pressed\n",Presskey);
        switch( Presskey )
        {
        case 's':
        cout<<"The image is going to be saved, please input the name:"<<endl;
        cin>>name[0];
        cvSaveImage( name[0], g_gray );
        break;
        default:
        break;
        }
        cvDestroyWindow( "Contours" );
        cvReleaseImage( &g_image );
        cvReleaseImage( &g_gray );
        }
        else
        return -1;
        return 0;
        }


    使用F15战机的二值图像进行了实验,下面是原图和结果图:

    =====================================



    展开全文
  • opencv中常用的跟轮廓相关的操作有:findContours()查找轮廓;drawContours()画轮廓轮廓填充;计算轮廓的面积和周长;提取轮廓凸包,矩形,最小外接矩形,外接圆等。它们都有相应的函数可以直接调用,那么任意形状...

            opencv中常用的跟轮廓相关的操作有:findContours()查找轮廓;drawContours()画轮廓;轮廓填充;计算轮廓的面积和周长;提取轮廓凸包,矩形,最小外接矩形,外接圆等。它们都有相应的函数可以直接调用,那么任意形状怎么取呢?

            方法1:点乘,将其形状与图像进行点乘,求其形状对应的图像形状;

            方法2:用findContours函数得对应的形状区域,其边缘显示类型可以通过设置参数可以控制;

    点乘——适用于不规则图形的提取

    //===============================对应灰度图的区域segImage==============================================================
        // 遍历图像 对每个非零像素值赋值为对应灰度图的像素值
    
        Mat zeroImage(Size(rioImage.cols, rioImage.rows), CV_8U, Scalar(0));//建立全0矩阵
        for (int i = 0; i < closeImg.rows; i++)//行遍历
        {
    
            unsigned char* ptr = (unsigned char*)closeImg.data + closeImg.step*i;
    
            for (int j = 0; j < closeImg.cols; j++)//列遍历
            {
                int intensity = ptr[j];
                if (intensity != 0)
    
                {
                    zeroImage.at<uchar>(i, j) = rioImage.at<uchar>(i, j);//对应位置赋值为灰度图像素
                }
            }
        }
    
        zeroImage.copyTo(segImage);
        //imshow("segImage.jpg", segImage);
        //waitKey(0);
    }

    规则图形的提取: 

    一、findContours()查找轮廓

    void findContours (

    InputOutputArray image,//输入图像,必须是8位单通道二值图像

    OutputArrayOfArrays contours,//检测到的轮廓,每个轮廓被表示成一个point向量

    OutputArray hierarchy,//可选的输出向量,包含图像的拓扑信息。其中元素的个数和检测到的轮廓的数量相等

    int mode,//说明需要的轮廓类型和希望的返回值方式

    int method,//轮廓近似方法

    Point offset = Point()

    )

    参数说明:

    mode:

    ①mode的值决定把找到的轮廓如何挂到轮廓树节点变量(h_prev, h_next, v_prev, v_next)上,拓扑结构图如下;

    ②每种情况下,结构都可以看成是被横向连接(h_prev, h_next)联系和被纵向连接(v_prev, v_next)不同层次。

    ③CV_RETR_EXTERNAL:只检测出最外轮廓即c0;

      CV_RETR_LIST:检测出所有的轮廓并将他们保存到表(list)中;

      CV_RETR_COMP:检测出所有的轮廓并将他们组织成双层的结构,第一层是外部轮廓边界,第二层边界是孔的边界;

      CV_RETR_TREE:检测出所有轮廓并且重新建立网状的轮廓结构;

    ④参数method:

      CV_CHAIN_CODE:用freeman链码输出轮廓,其他方法输出多边形(顶点的序列);

      CV_CHAIN_APPROX_NONE:将链码编码中的所有点转换为点;

      CV_CHAIN_APPROX_SIMPLE:压缩水平,垂直或斜的部分,只保存最后一个点;

      CV_CHAIN_APPROX_TC89_L1,CV_CHAIN_QPPROX_TC89_KCOS:使用Teh-Chin链逼近算法中的一个。

      CV_LINK_RUNS:与上述的算法完全不同,连接所有的水平层次的轮廓。

    【注】:findContours()查找时,这个图像会被直接涂改,因此如果是以后有用的图像,应该复制之后再进行查找;

                                                    

                                            

    二、drawContours()绘制轮廓:具有绘制轮廓和填充功能 

    void drawContours(

                    InputOutputArray image,//要绘制轮廓的图像

                    InputArrayOfArrays contours,//所有输入的轮廓,每个轮廓被保存成一个point向量

                    int contourIdx,//指定要绘制轮廓的编号,如果是负数,则绘制所有的轮廓

                    const Scalar& color,//绘制轮廓所用的颜色

                    int thickness = 1, //绘制轮廓的线的粗细,如果是负数,则轮廓内部被填充

                    int lineType = 8, /绘制轮廓线的连通性

                    InputArray hierarchy = noArray(),//关于层级的可选参数,只有绘制部分轮廓时才会用到

                    int maxLevel = INT_MAX,//绘制轮廓的最高级别,这个参数只有hierarchy有效的时候才有效

     Point offset = Point()

    )

    【注】:

    ①maxLevel=0,绘制与输入轮廓属于同一等级的所有轮廓即输入轮廓和与其相邻的轮廓

    maxLevel=1, 绘制与输入轮廓同一等级的所有轮廓与其子节点。

    maxLevel=2,绘制与输入轮廓同一等级的所有轮廓与其子节点以及子节点的子节点

                                                   

    三、轮廓填充

    步骤:

    a) 依次遍历轮廓点,将点绘制到img上;

    b) 使用floodFill以及一个种子点进行填充;

    两种方法:

    法一:自己编写程序;使用drawContours()函数;

    void drawMaxAreaLine(Mat& dst, vector<Point> maxAreaPoints)
    
        {
            int step = dst.step;
            auto data = dst.data;
            for (int i = 0; i < maxAreaPoints.size(); ++i)
            {
                *(data + maxAreaPoints[i].x + maxAreaPoints[i].y * step) = 255;
            }
        }
    
    

    法二:孔洞填充算法

    void fillHole(Mat src_Bw, Mat &dst_Bw) 
    
    { 
        Size m_Size = src_Bw.size(); 
        Mat Temp=Mat::zeros(m_Size.height+10,m_Size.width+10,src_Bw.type());
        src_Bw.copyTo(Temp(Range(5, m_Size.height + 5), Range(5, m_Size.width + 5)));
        floodFill(Temp, Point(0, 0), Scalar(255)); 
        Mat cutImg;
        Temp(Range(5, m_Size.height + 5), Range(5, m_Size.width + 5)).copyTo(cutImg); 
        dst_Bw = src_Bw | (~cutImg); 
    
    }

    【注】:这里常会碰到种子点不好选取的问题,因为有时候所选择的种子点不能保证对所有轮廓都适用。也就是查找一个在轮廓内的点是存在一定难度的。

    使用drawContours()就会很方便:

    vector<vector<Point> > contours;
    contours.push_back(currentFrameEdge);
    Mat savedGrayMat = Mat::zeros(RectData[0].rows, RectData[0].cols, CV_8UC1);
    //drawMaxAreaLine(savedGrayMat, currentFrameEdge);
    //floodFill(savedGrayMat, Point(currentFrameEdge[0].x + 2, currentFrameEdge[0].y + 2), 255);
    drawContours(savedGrayMat, contours, 0, Scalar(255), CV_FILLED);
    imshow("savedGrayMat", savedGrayMat);
    waitKey();

                                            

    四、计算轮廓的面积和周长

    ①计算轮廓面积:

    double contourArea(InputArray contour, bool oriented=false )

    InputArray contour:输入的点,一般是图像的轮廓点;

    bool oriented=false: 表示某一个方向上轮廓的的面积值,顺时针或者逆时针,一般选择默认false;

    ②计算轮廓边长:

    double arcLength(InputArray curve, bool closed)

    InputArray curve:表示图像的轮廓;

    bool closed:表示轮廓是否封闭的;

    【注】:

    ①contourArea计算整个或部分轮廓的面积;

    在计算部分轮廓的情况时,由轮廓弧线和连接两端点的弦围成的区域总面积被计算,如图;

    ②轮廓的位置将影响区域面积的符号,因此函数范围的有可能是负值。可以在运行时使用fabs()来得到面积的绝对值;

                                                                          

    五、提取轮廓凸包,矩形,最小外接矩形,外接圆

    ①convexhull():函数提取轮廓的凸包:

    格式:

    void convexhul(InputArray points,//要求凸包的点集

    OutputArray hull,//输出的凸包点,可以为vector,此时返回的是凸包点在原轮廓点集中的索引,也可以为vector,此时存放的是凸包点的位置

    bool clockwise=false,//一个bool变量,表示求得的凸包是顺时针方向还是逆时针方向,true是顺时针方向;

    bool returnPoints=true)//表示第二个参数的返回类型是vector还是vector,可以忽略;

    ②boundingRect():计算轮廓外包矩形,矩形是与图像上下边界平行的;

    格式:

    Rect boundingRect(InputArray points);

    输入:二维点集,点的序列或向量 (Mat)

    返回:Rect

    //寻找外包矩阵

    Rect maxRect = boundingRect(contours[m_count]);

     //绘制外包矩阵

      rectangle(contours_img_1, maxRect, Scalar(0, 255, 0));

    ③minAreaRect():提取轮廓的最小外包矩形;

    主要求包含点集最小面积的矩形,这个矩形是可以有偏转角度的,可以与图像的边界不平行;

    格式:

    RotatedRect minAreaRect(InputArray points);

    输入:二维点集,点的序列或向量 (Mat)

    返回:RotatedRect

    ④minEnclosingcircle():提取轮廓的最小外包圆;

    格式:

    void minEnclosingcircle(InputArray points,Point2f& center,float& radius);

    输入:

    二维点集:点的序列vector< point >或向量 (Mat) ,

    圆心坐标;

    半径;

    OpenCV函数:提取轮廓相关函数使用方法

    OpenCV函数:提取轮廓相关函数使用方法

           

    参考:https://jingyan.baidu.com/article/4d58d54179ecfb9dd4e9c092.html

    展开全文
  • Opencv 轮廓提取

    万次阅读 2019-01-27 23:38:06
    边缘检测的一般步骤 滤波——消除噪声 增强——使边界轮廓更加明显 ...opencv2\opencv.hpp&gt; #include&lt;opencv2\highgui\highgui.hpp&gt; using namespace std; using namespace cv; //边...

    边缘检测的一般步骤

    • 滤波——消除噪声
    • 增强——使边界轮廓更加明显
    • 检测——选出边缘点

    方法一

    Canny算法
    特点:轮廓细腻

    #include<opencv2\opencv.hpp>   
    #include<opencv2\highgui\highgui.hpp>
    
    using namespace std;
    using namespace cv;
    
    //边缘检测
    int main()
    {
    	Mat img = imread("1.jpg");
    	imshow("原始图", img);
    
    	Mat DstPic, edge, grayImage;
    
    	//创建与src同类型和同大小的矩阵
    	DstPic.create(img.size(), img.type());
    
    	//将原始图转化为灰度图
    	cvtColor(img, grayImage, COLOR_BGR2GRAY);
    
    	//先使用3*3内核来降噪
    	blur(grayImage, edge, Size(3, 3));
    
    	//运行canny算子
    	Canny(edge, edge, 3, 9, 3);
    
    	imshow("Canny算法轮廓提取效果", edge);
    
    	waitKey(0);
    }
    

    在这里插入图片描述

    方法二

    Sobel算法

    #include<opencv2\opencv.hpp>   
    #include<opencv2\highgui\highgui.hpp>
    
    using namespace std;
    using namespace cv;
    
    //边缘检测
    int main()
    {
    	Mat img = imread("1.jpg");
    
    	imshow("原始图", img);
    
    	Mat grad_x, grad_y;
    	Mat abs_grad_x, abs_grad_y, dst;
    
    	//求x方向梯度
    	Sobel(img, grad_x, CV_16S, 1, 0, 3, 1, 1, BORDER_DEFAULT);
    	convertScaleAbs(grad_x, abs_grad_x);
    	imshow("x方向soble", abs_grad_x);
    
    	//求y方向梯度
    	Sobel(img, grad_y, CV_16S, 0, 1, 3, 1, 1, BORDER_DEFAULT);
    	convertScaleAbs(grad_y, abs_grad_y);
    	imshow("y向soble", abs_grad_y);
    
    	//合并梯度
    	addWeighted(abs_grad_x, 0.5, abs_grad_y, 0.5, 0, dst);
    	imshow("Sobel算法轮廓提取效果", dst);
    
    	waitKey(0);
    }
    

    在这里插入图片描述

    方法三

    Laplacian算法

    #include<opencv2\opencv.hpp>   
    #include<opencv2\highgui\highgui.hpp>
    
    using namespace std;
    using namespace cv;
    
    //边缘检测
    int main()
    {
    	Mat img = imread("1.jpg");
    	imshow("原始图", img);
    	Mat gray, dst, abs_dst;
    	//高斯滤波消除噪声
    	GaussianBlur(img, img, Size(3, 3), 0, 0, BORDER_DEFAULT);
    	//转换为灰度图
    	cvtColor(img, gray, COLOR_RGB2GRAY);
    	//使用Laplace函数
    	//第三个参数:目标图像深度;第四个参数:滤波器孔径尺寸;第五个参数:比例因子;第六个参数:表示结果存入目标图
    	Laplacian(gray, dst, CV_16S, 3, 1, 0, BORDER_DEFAULT);
    	//计算绝对值,并将结果转为8位
    	convertScaleAbs(dst, abs_dst);
    	imshow("Laplace算法轮廓提取效果", abs_dst);
    	
    	waitKey(0);
    }
    

    在这里插入图片描述

    展开全文
  • opencv提取轮廓与抠图

    万次阅读 多人点赞 2014-03-19 21:41:08
    自然图像抠图/视频抠像技术梳理(image matting, video matting)-计算机视视觉专题1 图像抠图算法学习 - Shared Sampling for Real-Time Alpha Matting ... 学习opencv ,图像分割中分水岭算法的感性认识
    展开全文
  • OpenCV轮廓提取

    千次阅读 2018-05-21 00:14:32
    相应的轮廓提取分为以下两部分:1、cvThreshold(pImg, pImg, 150, 255, CV_THRESH_BINARY); cvShowImage("threshold", pImg); 对图像进行二值化,显示相应的图像2、cvFindContours(pImg, storage, &...
  • OpenCV学习指南(五)轮廓提取

    千次阅读 2019-08-24 17:26:03
    #图像中的轮廓提取 #时间:2019/1/3 #作者:cclplus #仅供学习交流使用 #如若照片本人认为侵犯了肖像权,请联系我的邮箱707101557@qq.com #如有疑问或者需求,可以联系作者的邮箱 #如果你有什么好的建议或者...
  • 最近用OPENCV轮廓提取函数,总结一下。void findContours//提取轮廓,用于提取图像的轮廓(InputOutputArray image,//输入图像,必须是8位单通道图像,并且应该转化成二值的OutputArrayOfArrays contours,//检测到...
  • opencv3/C++轮廓提取与筛选

    千次阅读 2018-09-10 16:32:31
    版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/akadiao/article/details/78843773 ...
  • opencv 轮廓提取

    千次阅读 2017-08-30 09:51:24
    轮廓指的是将连续的点连接在一起的曲线,具有相同的灰度值或颜色,提取轮廓就是提取这些具有相同颜色或灰度值的曲线 寻找轮廓应该用二值图,这样更明显 findcontours会改变原图,应该用copyto保存原图 查找轮廓应该...
  • opencv学习笔记二十一:轮廓提取

    千次阅读 2018-09-08 11:24:22
    轮廓:一个轮廓代表一系列的点(像素),这一系列的点构成一个有序的点集,所以可以把一个轮廓理解为一个有序的点集。 在opencv中,提供了一个函数返回一个有序的点集或者有序的点集的集合(指多个有序的点集),...
  • 本范例主要介绍了如何提取轮廓和用一些形状描述符对轮廓进行表述,轮廓提取函数涉及到的参数很多,没有经常用到它的话,对参数的了解就不会太深刻,这里也按照本人搜索出来的一些资料进行总结,希望对大家有用。...
  • opencv轮廓提取示例

    2018-05-25 15:21:35
    图片地址需要自己改动,用的是opencv提取轮廓函数,可以通过参数设定选择提取轮廓的外边缘和内边缘
  • OpenCV轮廓提取

    千次阅读 2013-02-24 17:31:57
    OpenCV中,一个轮廓一般对应一系列的点,也就是图像中的一条曲线,表示方法可能根据不同的情况有所不同,在OpenCV中,一般用序列来存储轮廓信息,序列中的每一个元素是曲线中一个点的位置。虽然Canny之类的边缘...
  • Android Opencv 轮廓提取

    千次阅读 2019-06-25 16:48:30
    1.把图片转成灰度图 2.再转成黑白 ...4.查找轮廓 这里查找的是图片中最大的矩形 Mat src=new Mat(); Mat grayMat=new Mat(); Mat edge=new Mat(); Utils.bitmapToMat(bitmap_src, src); I...
  • OPENCV轮廓提取findContours和drawContours

    万次阅读 多人点赞 2015-11-12 10:16:29
    关于opencv中的轮廓提取函数findcontours()和轮廓绘制函数drawContours()中参数的说明和实验结果。
  • findContours函数,这个函数的原型为: void findContours(InputOutputArray image, OutputArrayOfArrays contours, OutputArray hierar- chy, int mode, int method, Point offset=Point()) 参数说明 ...
  • opencv轮廓提取与轮廓拟合

    千次阅读 2015-09-03 19:59:48
    #include #include #include #include #include using namespace std; using namespace cv; int main() { // Read input binary image Mat image= imread("./binaryGroup.bmp",0);... r
  • opencv轮廓提取与轮廓拟合

    千次阅读 2019-04-29 09:21:47
    opencv轮廓提取与轮廓拟合 Opencv(Python) 教程-轮廓(2)轮廓特征求取 OpenCV之findContours获取轮廓(Python版) python+opencv学习(二)--直线拟合、轮廓检测 Python+OpenCV教程14:轮廓特征 opencv...
  • 最近用OPENCV轮廓提取函数,总结一下。 void findContours//提取轮廓,用于提取图像的轮廓 ( InputOutputArray image,//输入图像,必须是8位单通道图像,并且应该转化成二值的 OutputArrayOfArrays contours,/...
  • opencv轮廓提取与轮廓拟合

    千次阅读 2015-01-05 09:55:45
    #include &lt;iostream&...opencv2/core/core.hpp&gt; #include &lt;opencv2/imgproc/imgproc.hpp&gt; #include &lt;opencv2/highgui/highgui.hpp&gt; using namesp...

空空如也

1 2 3 4 5 ... 20
收藏数 8,830
精华内容 3,532
关键字:

opencv轮廓提取