美文网首页
android opencv之旅(四)查找轮廓,获取外包矩形

android opencv之旅(四)查找轮廓,获取外包矩形

作者: 风少侠 | 来源:发表于2018-06-29 15:40 被阅读604次

    棋盘边界是一个黑色的正方形,为了定位这个正方形,我们先查找出图片中的所有轮廓。

    查找轮廓

    List<MatOfPoint> contourList = new ArrayList<>();
    Imgproc.findContours(src, contourList, hierarchy, mode, method);
    

    参数列表:

    • src:源Mat,推荐使用二值化后的Mat
    • contourList:检测到的轮廓列表,每个轮廓用MatOfPoint类表示
    • hiararchy:我们检测轮廓的时候,有时候轮廓会有嵌套关系,这时候我们称外面的轮廓为parent,内部的轮廓为child。此时轮廓之间就有了一定的关系,我们称之为层次结构。


      hierarchy.png

    比如0、1、2为外轮廓,他们处于相同层级,2a、3、3a、4、5为2的内部轮廓,其中2a为2的第一个内部轮廓,称为first_child。我们就可以用相同层级、外轮廓、子轮廓、父轮廓、第一个子轮廓来描述这些关系。
    我们用一个长度为4的数组来存储这些关系[Next, Previous, First_Child, Parent],即hiararchy。前两个代表相同层级的上一个和下一个轮廓的编号,第三个代表第一个子轮廓的编号,第四个代表父轮廓编号,没有的话就是-1。

    • mode:轮廓的检索模式,有四个值
    1. RETR_LIST:检索所有轮廓,但不创建任何父子关系,因此hiararchy数组后两项永远是-1。
    2. RETR_EXTERNAL:只检索外轮廓。hiararchy数组后两项也永远是-1。
    3. RETR_CCOMP:检索所有轮廓,并将他们排列为2级层次结构。即对象的外部轮廓被放在层级1中,内部轮廓被放在层级2中。如果对象的内部还有对象,则内部对象的外轮廓重新被放在层级1中,内轮廓放层级2。如下图,红色数字代表轮廓编号,绿色数字代表层级:


      ccomp_hierarchy.png

      9个轮廓对应的hiararchy:

    [ 3, -1,  1, -1],//轮廓0
    [ 2, -1, -1,  0],//轮廓1
    [-1,  1, -1,  0],//轮廓2
    [ 5,  0,  4, -1],//轮廓3
    [-1, -1, -1,  3],//轮廓4
    [ 7,  3,  6, -1],//轮廓5
    [-1, -1, -1,  5],//轮廓6
    [ 8,  5, -1, -1],//轮廓7
    [-1,  7, -1, -1]//轮廓8
    

    这里简单解释一下轮廓2:父轮廓为0,0下的同一层次中没有下一个轮廓,所以第一项是-1,而不是4,因为4位于轮廓3下面。轮廓4和6同理。

    1. RETR_TREE:检索所有轮廓,并排列成一个完美的层级结构,包括爷爷、父亲、自己、儿子、孙子等等。依旧看图理解:红色数字代表轮廓编号,绿色数字代表层级:


      tree_hierarchy.png

      9个轮廓对应的hiararchy:

    [ 7, -1,  1, -1],//轮廓0
    [-1, -1,  2,  0],//轮廓1
    [-1, -1,  3,  1],//轮廓2
    [-1, -1,  4,  2],//轮廓3
    [-1, -1,  5,  3],//轮廓4
    [ 6, -1, -1,  4],//轮廓5
    [-1,  5, -1,  4],//轮廓6
    [ 8,  0, -1, -1],//轮廓7
    [-1,  7, -1, -1]//轮廓8
    
    • method:轮廓是具有相同色值强度的边界,它存储这边界坐标,method代表了存储的方式。比如CHAIN_APPROX_NONE代表存储所有边界点坐标,CHAIN_APPROX_SIMPLE只存储关键坐标,比如说存储一条直线只需要两个端点,存储一个矩形只需要四个端点。

    更多关于轮廓的知识请参考https://docs.opencv.org/master/d3/d05/tutorial_py_table_of_contents_contours.html

    获取轮廓的外包矩形

    Rect rect = Imgproc.boundingRect(mp);//mp为一个轮廓MatOfPoint
    

    到此基本就可以定位出我需要的棋盘区域了。

    相关文章

      网友评论

          本文标题:android opencv之旅(四)查找轮廓,获取外包矩形

          本文链接:https://www.haomeiwen.com/subject/jpkxyftx.html