answerOpenCV轮廓类问题解析

本文涉及的产品
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: contour在opencv中是一个基础的数据结构,灵活运用的话,作用很大。以contour为关键字,在answerOpenCV中能够发现很多有趣的东西。1、无法解决的问题http://answers.
contour在opencv中是一个基础的数据结构,灵活运用的话,作用很大。以contour为关键字,在answerOpenCV中能够发现很多有趣的东西。
img_491df057f17545c53011cac5ca86ee2c.png

1、无法解决的问题
img_16e1f3a19fa806bf16adfbfa4882c204.jpe
The problem is that. I just want to take the external contours of the main leaf in the image. Or If it is possible, The image can be cleaned. The second important point is that the process should be standard for all images.
解析:这个提问者希望从上面的叶子图片,得到叶子的轮廓。但实际上这是不可能完成的任务,这个图片质量达不到要求,关于这一点,是图像处理的常识。
也就是根本无法轮廓分析,因为没有稳定的轮廓。

2、如何从图像中获得完整轮廓

How to find dimensions of an object in the image


这道题厉害了,一看这个需求就是专业的:
I want to find the length of an object in the image (image length not the real physical length). My first idea is was to use boundingRect to find the dimensions, but some of the masks I have split in between them so the boundingRect method fails. Can someone suggest me a robust method to find the length of the object in the given mask

Mask with split
他需要从这个图中活动轮廓的长度(这个应该是一个脚印),但是因为图上轮廓可能有多个,所以不知道怎么办。
解析: 这道题的关键, 就在于实际上,每张图的轮廓只有一个。 这是重要的先验条件。那怎么办?把识别出来的轮廓连起来呀。
连的方法有多种,我给出两种比较保险:
1、形态学变化
img_9a95d87d96bc2b17e8530a4856de6101.png
    dilate(bw,bw,Mat(11,11,CV_8UC1));
    erode(bw,bw,Mat(11,11,CV_8UC1));
img_8822cd804ab7aa466390a86a542b6c6f.png
2、实在距离太远,靠不上了,直接把中线连起来吧
img_858d68e0bef972f8ca7a364e36614abc.jpe

由于这道题目前还没有比较好的解决方法,所以我实现了一个,应该是可以用的,这是结果:
img_b065e6c891cdbb3989679dd140893c8c.jpe
网站代码也已经提交到网站上了
//程序主要部分
int mainint argcchar** argv )
{
    //读入图像,转换为灰度
    Mat img = imread("e:/sandbox/1234.png");
    Mat bw;
    bool dRet;
    cvtColor(imgbwCOLOR_BGR2GRAY);
    //阈值处理
    threshold(bwbw, 150, 255, CV_THRESH_BINARY);
    bitwise_not(bw,bw);
    //形态学变化
    dilate(bw,bw,Mat(11,11,CV_8UC1));
    erode(bw,bw,Mat(11,11,CV_8UC1));
    //寻找轮廓
    vector<vector<Point> > contours;
    vector<Vec4ihierarchy;
    findContours(bwcontourshierarchyCV_RETR_LISTCV_CHAIN_APPROX_NONE);
    /// 计算矩
    vector<Momentsmu(contours.size() );
    forint i = 0; i < contours.size(); i++ )
        mu[i] = momentscontours[i], false ); 
    ///  计算中心矩:
    vector<Point2fmccontours.size() );
    forint i = 0; i < contours.size(); i++ )
        mc[i] = Point2fmu[i].m10/mu[i].m00 , mu[i].m01/mu[i].m00 ); 
    //connect all contours into ONE
    for (int i = 0; i < contours.size(); ++i)
    {
        Scalar color = Scalarrng12345.uniform(0, 255), rng12345.uniform(0,255), rng12345.uniform(0,255) );
        drawContoursimgcontoursicolor, 2, 8, hierarchy, 0, Point() );
        circleimgmc[i], 4, color, -1, 8, 0 );
        //connect
        if (i+1 <contours.size())
            line(bw,mc[i],mc[i+1],Scalar(255,255,255));
    }
    contours.clear();
    hierarchy.clear();
    //寻找结果
    findContours(bwcontourshierarchyCV_RETR_LISTCV_CHAIN_APPROX_NONE);
    for (int i = 0;i<contours.size();i++)
    {
        RotatedRect minRect = minAreaRectMat(contours[i]) );
        Point2f rect_points[4];
        minRect.pointsrect_points ); 
        forint j = 0; j < 4; j++ )
            lineimgrect_points[j], rect_points[(j+1)%4],Scalar(255,255,0),2);
        float fshort = std::min(minRect.size.width,minRect.size.height); //short
        float flong = std::max(minRect.size.width,minRect.size.height);  //long
    }
    imshow("img",img);
    waitKey();
    return 0;
}

3、新函数

Orientation of two contours


image description

这个topic希望能够获得两个轮廓之间的角度。并且后期通过旋转将两者重合。
I try to calculate the orientation of 2 contours. At the end i want to rotate one contour, so it is in cover with the other one. With my code I get a result, but it isn't that accurate. Also I get the same orientations although the contours is rotated around 90 degrees.

解析: 如果是我,一定会直接使用pca分别求出两个轮廓的角度,然后算差。但是原文中使用了,并且提出了独特的解决方法。

Shape Distance and Common Interfaces

https://docs.opencv.org/3.0-beta/modules/shape/doc/shape_distances.html#shapecontextdistanceextractor

Shape Distance algorithms in OpenCV are derivated from a common interface that allows you toswitch between them in a practical way for solving the same problem with different methods.Thus, all objects that implement shape distance measures inherit the ShapeDistanceExtractor interface.
当然,有了这个函数,做轮廓匹配也是非常方便:
image description
http://answers.opencv.org/question/28489/how-to-compare-two-contours-translated-from-one-another/
 
4、发现opencv的不足

I need a maxEnclosingCircle function


opencv目前是没有最大内接圆函数的(当然它还没有很多函数),但是这个只有研究要一定程度的人才会发现。这里他提问了,我帮助解决下:

img_b95eac4eaaf638b00adf7cf2710ef34f.jpe


# include   "stdafx.h"
# include   < iostream >
 
using   namespace  std;
using   namespace  cv;
 
VP FindBigestContour(Mat src){    
     int  imax  =   0 //代表最大轮廓的序号
     int  imaxcontour  =   - 1 //代表最大轮廓的大小
    std : : vector < std : : vector < cv : : Point >> contours;    
    findContours(src,contours,CV_RETR_LIST,CV_CHAIN_APPROX_SIMPLE);
     for  ( int  i = 0 ;i < contours.size();i ++ ){
         int  itmp  =   contourArea(contours[i]); //这里采用的是轮廓大小
         if  (imaxcontour  <  itmp ){
            imax  =  i;
            imaxcontour  =  itmp;
        }
    }
     return  contours[imax];
}
int  main( int  argc,  char *  argv[])
{
    Mat src  =  imread( "e:/template/cloud.png" );
    Mat temp;
    cvtColor(src,temp,COLOR_BGR2GRAY);
    threshold(temp,temp, 100 , 255 ,THRESH_OTSU);
    imshow( "src" ,temp);
     //寻找最大轮廓
    VP VPResult  =  FindBigestContour(temp);
     //寻找最大内切圆
     int  dist  =   0 ;
     int  maxdist  =   0 ;
    Point center;
     for ( int  i = 0 ;i < src.cols;i ++ )
    {
         for ( int  j = 0 ;j < src.rows;j ++ )
        {
            dist  =  pointPolygonTest(VPResult,cv : : Point(i,j), true );
             if (dist > maxdist)
            {
                maxdist = dist;
                center = cv : : Point(i,j);
            }
        }
    }
     //绘制结果
    circle(src,center,maxdist,Scalar( 0 , 0 , 255 ));
    imshow( "dst" ,src);
    waitKey();
}
    



另过程中,发现了pyimagesearch上的一些不错文章,感谢这个blog的作者的长期、高质量的付出,向他学习。
1、 Removing contours from an image using Python and OpenCV


3、 Finding extreme points in contours with OpenCV
https://www.pyimagesearch.com/2016/04/11/finding-extreme-points-in-contours-with-opencv/

结语:
实际上,最近我正在做关于轮廓的事情,这也是今天我做这个研究的直接原因。

我的问题是:如何识别出轮廓准确的长和宽
比如这张,其中2的这个外轮廓明显是识别错误的,这样它的长宽也是错误的(注意里面我标红的1和2)
image description

代码:
int mainint argcchar** argv )
{
    //read the image
    Mat img = imread("e:/sandbox/leaf.jpg");
    Mat bw;
    bool dRet;
    //resize
    pyrDown(img,img);
    pyrDown(img,img);
    cvtColor(imgbwCOLOR_BGR2GRAY);
    //morphology operation    
    threshold(bwbw, 150, 255, CV_THRESH_BINARY);
    //bitwise_not(bw,bw);
    //find and draw contours
    vector<vector<Point> > contours;
    vector<Vec4ihierarchy;
    findContours(bwcontourshierarchyCV_RETR_LISTCV_CHAIN_APPROX_NONE);
    for (int i = 0;i<contours.size();i++)
    {
        RotatedRect minRect = minAreaRectMat(contours[i]) );
        Point2f rect_points[4];
        minRect.pointsrect_points ); 
        forint j = 0; j < 4; j++ )
            lineimgrect_points[j], rect_points[(j+1)%4],Scalar(255,255,0),2);
    }
    imshow("img",img);
    waitKey();
    return 0;
}

我们要得到这样的结果
image description

当然,这个代码我已经差不多写出来了,如何获得轮廓的真实的长宽?这个问题很实际,opencv没有实现,目前看来answeropencv也人问?
就是这张图片?想看看大家的想法。也可以直接在answeropencv上进行讨论。
img_ca730f3c368cd889257eb5abf7a32d24.jpe

answerOpencv的讨论地址为:



感谢阅读至此,希望有所帮助。








目前方向:图像拼接融合、图像识别 联系方式:jsxyhelu@foxmail.com
目录
相关文章
|
1月前
|
存储 Java API
详细解析HashMap、TreeMap、LinkedHashMap等实现类,帮助您更好地理解和应用Java Map。
【10月更文挑战第19天】深入剖析Java Map:不仅是高效存储键值对的数据结构,更是展现设计艺术的典范。本文从基本概念、设计艺术和使用技巧三个方面,详细解析HashMap、TreeMap、LinkedHashMap等实现类,帮助您更好地理解和应用Java Map。
51 3
|
5月前
|
缓存 开发者 索引
深入解析 `org.elasticsearch.action.search.SearchRequest` 类
深入解析 `org.elasticsearch.action.search.SearchRequest` 类
|
1月前
|
存储 编译器 数据安全/隐私保护
【C++篇】C++类与对象深度解析(四):初始化列表、类型转换与static成员详解2
【C++篇】C++类与对象深度解析(四):初始化列表、类型转换与static成员详解
31 3
|
1月前
|
编译器 C++
【C++篇】C++类与对象深度解析(四):初始化列表、类型转换与static成员详解1
【C++篇】C++类与对象深度解析(四):初始化列表、类型转换与static成员详解
47 3
|
1月前
|
安全 编译器 C++
【C++篇】C++类与对象深度解析(三):类的默认成员函数详解
【C++篇】C++类与对象深度解析(三):类的默认成员函数详解
20 3
|
1月前
|
程序员 开发者 Python
深度解析Python中的元编程:从装饰器到自定义类创建工具
【10月更文挑战第5天】在现代软件开发中,元编程是一种高级技术,它允许程序员编写能够生成或修改其他程序的代码。这使得开发者可以更灵活地控制和扩展他们的应用逻辑。Python作为一种动态类型语言,提供了丰富的元编程特性,如装饰器、元类以及动态函数和类的创建等。本文将深入探讨这些特性,并通过具体的代码示例来展示如何有效地利用它们。
39 0
|
3月前
|
缓存 Java 开发者
Spring高手之路22——AOP切面类的封装与解析
本篇文章深入解析了Spring AOP的工作机制,包括Advisor和TargetSource的构建与作用。通过详尽的源码分析和实际案例,帮助开发者全面理解AOP的核心技术,提升在实际项目中的应用能力。
48 0
Spring高手之路22——AOP切面类的封装与解析
|
3月前
|
JSON 图形学 数据格式
Json☀️ 一、认识Json是如何解析成类的
Json☀️ 一、认识Json是如何解析成类的
|
3月前
|
开发者 编解码
界面适应奥秘:从自适应布局到图片管理,Xamarin响应式设计全解析
【8月更文挑战第31天】在 Xamarin 的世界里,构建灵活且适应性强的界面是每位开发者的必修课。本文将带您探索 Xamarin 的响应式设计技巧,包括自适应布局、设备服务协商和高效图片管理,帮助您的应用在各种设备上表现出色。通过 Grid 和 StackLayout 实现弹性空间分配,利用 Device 类检测设备类型以加载最优布局,以及使用 Image 控件自动选择合适图片资源,让您轻松应对不同屏幕尺寸的挑战。掌握这些技巧,让您的应用在多变的市场中持续领先。
39 0
|
3月前
|
存储 开发者 Ruby
【揭秘Ruby高手秘籍】OOP编程精髓全解析:玩转类、继承与多态,成就编程大师之路!
【8月更文挑战第31天】面向对象编程(OOP)是通过“对象”来设计软件的编程范式。Ruby作为一种纯面向对象的语言,几乎所有事物都是对象。本文通过具体代码示例介绍了Ruby中OOP的核心概念,包括类与对象、继承、封装、多态及模块混合,展示了如何利用这些技术更好地组织和扩展代码。例如,通过定义类、继承关系及私有方法,可以创建具有特定行为的对象,并实现灵活的方法重写和功能扩展。掌握这些概念有助于提升代码质量和可维护性。
38 0
下一篇
无影云桌面