opencv 实现孔洞填充的两个解决方案 MATLAB--imfill功能(收集)

opencv 孔洞填充,方案1: 

http://bbs.csdn.net/topics/391542633?page=1


opencv 孔洞填充,方案1: 

其实主要是imfill(matrix, 'holes'); 的openCV/C++ 实现。
Overview:
imfill是matlab的一个函数,在http://www.mathworks.cn/cn/help/images/ref/imfill.html 中有详细的讲解。这个函数有好几种不同的签名。在这里我的侧重点是imfill(m, 'holes'),以及如何用openCV来实现imfill一样的功能。本文有三部分组成。

1. 使用Matlab 的imfill 进行填充图像
在Matlab中简单的几行代码就能实现:
1
2
3
4
5
6
7
8
 
clc;
clear;
BW  im2bw(  imread( 'imfilltest.tif'));
imshow(BW);
holes  imfill(BW,  'holes');

BW(~holes)  1
figure,imshow(holes);
左图为填充前的图像,右图是填充后的图像:
[原]imfill <wbr>的openCV实现

2. 用opencv来实现imfill(bw, 'holes')
opencv 在这里不像matlab那么好用了,matlab调用下。
  C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
 
#include 
#include 
#include 

using  namespace  std;
using  namespace  cv;

void  my_imfillholes(Mat  &src)
{
      // detect external contours
      //
      vector  contours;
      vector  hierarchy;
      findContours(src,  contours,  hierarchy,  CV_RETR_EXTERNAL,  CV_CHAIN_APPROX_SIMPLE);
      //
      // fill external contours
      //
      if!contours.empty()  &&  !hierarchy.empty()  )
      {
            for  ( int  idx= 0;idx  contours.size();idx++)
            {
                  drawContours(src,contours,idx,Scalar::all( 255),CV_FILLED, 8);
            }
      }
}

void  test_my_imfillholes()
{
      Mat  imread(filltestName,IMREAD_GRAYSCALE);
      //threshold, (i,j)>100 -->255
      Mat  th_m;
      threshold(m,  th_m,  100 255THRESH_BINARY);
      my_imfillholes(th_m);
      namedWindow(WinName,  CV_WINDOW_AUTOSIZE);
      imshow(WinName,  th_m);
      waitKey( 0); 
}

void  main()
{
      test_my_imfillholes();
      system( "pause");
}
[原]imfill <wbr>的openCV实现

3. imfill 和opencv实现的imfill 对矩阵进行操作的对比
我仍有点不放心,觉得尽管2幅图看起来差不多,但是是不是完全一样呢,然后我觉得用个矩阵试一下。
m = [1, 1, 1, 0, 0, 0, 0, 0;
         1, 0, 1, 0, 1, 1, 0, 0;
         1, 0, 1, 0, 1, 1, 0, 0;
         1, 1, 1, 0, 1, 0, 1, 0;
         1, 0, 1, 0, 1, 0, 1, 0;
         1, 1, 1, 0, 1, 0, 1, 0;
         1, 0, 1, 0, 0, 1, 1, 0;
         1, 1, 1, 0, 0, 0, 0, 0];
without_holes = imfill(m, 'holes')

得到结果:
without_holes =
     1     1     1     0     0     0     0     0
     1     1     1     0     1     1     0     0
     1     1     1     0     1     1     0     0
     1     1     1     0     1     1     1     0
     1     1     1     0     1     1     1     0
     1     1     1     0     1     1     1     0
     1     1     1     0     0     1     1     0
     1     1     1     0     0     0     0     0
然后用第2部分所说的opencv的方法也试一下,结果发现是这样的:
without_holes =
     0     0     0     0     0     0     0     0
     0     1     1     0     1     1     0     0
     0     1     1     0     1     1     0     0
     0     1     1     0     1     1     1     0
     0     1     1     0     1     1     1     0
     0     1     1     0     1     1     1     0
     0     1     1     0     0     1     1     0
     0     0     0     0     0     0     0     0
是不一样的。这个问题折腾了我一个晚上,终于,我在
中的 findContours找到了这样的一个note:
Note:
Source image is modified by this function. Also, the function does not take into account 1-pixel border of the image (it’s filled with 0’s and used for neighbor analysis in the algorithm), therefore the contours touching the image border will be clipped.
它的意思是,findCountours 是不会包含1-pixel的边界的。所以这就是为啥opencv计算的结果中边界的1都消失的原因。 我想,既然边界不被包含,那么我给它上下左右加一个1-pixel的框,这样边界点就变成了内部点,就能成功的用findCountours了。于是乎:我写了下面的code:
C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
 
#include 
#include 
#include 

using  namespace  std;
using  namespace  cv;

void  my_imfillholes_v2()
{
      //step 1: make border
      Mat  m( 8 8CV_8UC1,  data);
      Mat  m_with_border;
      copyMakeBorder(m,  m_with_border,  1 1 1 1BORDER_CONSTANT,  Scalar());
      cout<<m_with_border<<endl;

      //setp 2: find the contour fill holes
      vector  contours;
      vector  hierarchy;
      findContours(m_with_border,  contours,  hierarchy,  CV_RETR_CCOMP,  CV_CHAIN_APPROX_NONE);
      //
      // fill external contours
      // 
      if!contours.empty()  &&  !hierarchy.empty()  )
      {
            for  ( int  idx= 0;idx  contours.size();idx++)
            {
                  drawContours(m_with_border,contours,idx,Scalar::all( 1),CV_FILLED, 8);
            }
      }
      //cout<<m_with_border<<endl;
      //step 3: remove the border
      m_with_border  m_with_border.rowRange(Range( 1m_with_border.rows- 1));
      //cout<<m_with_border<<endl;
      m_with_border  m_with_border.colRange(Range( 1m_with_border.cols- 1));
      cout<<m_with_border<<endl;
}

void  main()
{
      my_imfillholes_v2();
      system( "pause");
}

先加一个全0的1-pixel的框,然后在findCountours填充,最后把框给去了。这样结果就完全和matlab中的imfill一致了。
result =
     1     1     1     0     0     0     0     0
     1     1     1     0     1     1     0     0
     1     1     1     0     1     1     0     0
     1     1     1     0     1     1     1     0
     1     1     1     0     1     1     1     0
     1     1     1     0     1     1     1     0
     1     1     1     0     0     1     1     0
     1     1     1     0     0     0     0     0

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值