《图像处理实例》 之 寻找山脊线

 


 

寻找山脊线算法

以下的改进是http://www.imagepy.org/的作者原创,我只是对其理解之后改进和说明,欢迎大家使用这个小软件!

C++版本已经编写完毕,有需要的朋友请留邮箱

 


 

算法含义:

    提取一个山脉的山峰,图像中就是在距离变换之后提取局部最亮的线

《图像处理实例》 之 寻找山脊线

 


 

算法应用:

    用作图像的断裂修补

 

 

《图像处理实例》 之 寻找山脊线

 

方法:

    1.直接用分水岭算法进行区域分割。

    2.类似分水岭的算法,找山脊线。


 

分水岭算法:

    这里有个哲学的思想,还是开头大佬点拨我的,修补前景就等价于分割背景,一定要理解这句话的含义,我们把白色的直线当做前景修复对象,那么就等价于用白线去分割黑色的背景。

    opencv的分水岭算法不是很好,必须找到合适的mask才能达到要求。

    skimage的分水岭相对较好,效果差强人意吧.

《图像处理实例》 之 寻找山脊线

 

 

      分水岭结果如上图,在这基础上阈值一下就可以得到我们的图像(这个图像有多余的线条),然后再和原始图像做差值得到修补的线条,把修补的很长线条去除之后再加上原图就可以了。

     大家也发现了一个问题,手动的元素比较多,预处理做的不好(局部极大值找的不好,我用的自适应阈值,效果不好就不上图了),上图的效果算比较好的,至少可以解决我们的问题。

 代码:

       

  1 #include<opencv2/opencv.hpp>
  2 #include<iostream>
  3 using namespace std;
  4 using namespace cv;
  5 
  6 #define WINDOW_NAME "【程序窗口1】"
  7 Mat g_maskImage, g_srcImage;
  8 Point prevPt(-1, -1);
  9 static void on_Mouse(int event, int x, int y, int flags, void*);
 10 
 11 int main()
 12 {
 13     //载入原图,初始化掩膜和灰度图
 14     g_srcImage = imread("123.png");
 15     imshow(WINDOW_NAME, g_srcImage);
 16     Mat srcImage, grayImage;
 17     g_srcImage.copyTo(srcImage);
 18     cvtColor(g_srcImage, g_maskImage, COLOR_BGR2GRAY);
 19     cvtColor(g_maskImage, grayImage, COLOR_GRAY2BGR);
 20     g_maskImage = Scalar::all(0);
 21     //设置鼠标回调函数
 22     setMouseCallback(WINDOW_NAME, on_Mouse);
 23     //轮询按键
 24     while (1)
 25     {
 26         int c = waitKey(0);
 27         if ((char)c == 27) break;
 28         if ((char)c == '2') {   //按键‘2’, 恢复源图
 29             g_maskImage = Scalar::all(0);
 30             srcImage.copyTo(g_srcImage);
 31             imshow("image", g_srcImage);
 32         }
 33         if ((char)c == '1' || (char)c == ' ') {
 34             //定义一些参数            
 35             vector<vector<Point> > contours;
 36             vector<Vec4i> hierarchy;
 37             //寻找轮廓
 38             findContours(g_maskImage, contours, hierarchy, CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE);
 39             //轮廓为空时的处理
 40             if (contours.empty()) continue;
 41             //复制掩膜
 42             Mat maskImage(g_maskImage.size(), CV_32S);
 43             maskImage = Scalar::all(0);
 44             //循环绘制出轮廓
 45             int compCount = 0;
 46             for (int index = 0; index >= 0; index = hierarchy[index][0], compCount++)
 47                 drawContours(maskImage, contours, index, Scalar::all(compCount + 1), -1, LINE_8, hierarchy);
 48             //compCount为零时的处理
 49             if (compCount == 0)
 50                 continue;
 51             //生成随机颜色
 52             vector<Vec3b> colorTab;
 53             for (unsigned int i = 0; i < compCount; i++) {
 54                 int b = theRNG().uniform(0, 255);
 55                 int g = theRNG().uniform(0, 255);
 56                 int r = theRNG().uniform(0, 255);
 57                 colorTab.push_back(Vec3b((uchar)b, (uchar)g, (uchar)r));
 58             }
 59             //计算处理时间并输出到窗口中
 60             double dTime = (double)getTickCount();
 61             watershed(srcImage, maskImage);
 62             dTime = (double)getTickCount() - dTime;
 63             printf("处理时间=%gms\n", dTime*1000. / getTickFrequency());
 64             //双层循环,将分水岭图像遍历存入watershedImage中
 65             Mat watershedImage(maskImage.size(), CV_8UC3);
 66             for (unsigned int i = 0; i < maskImage.rows; i++)
 67                 for (unsigned int j = 0; j < maskImage.cols; j++)
 68                 {
 69                     int index = maskImage.at<int>(i, j);
 70                     if (index == -1)
 71                         watershedImage.at<Vec3b>(i, j) = Vec3b(255, 255, 255);
 72                     else if (index <= 0 || index > compCount)
 73                         watershedImage.at<Vec3b>(i, j) = Vec3b(0, 0, 0);
 74                     else
 75                         watershedImage.at<Vec3b>(i, j) = colorTab[index - 1];
 76                 }
 77             //混合灰度图和分水岭效果图并显示最终的窗口
 78             //watershedImage = watershedImage*0.5 + grayImage*0.5;
 79             imshow("watershed transform", watershedImage);
 80         }
 81     }
 82     return 0;
 83 }
 84 
 85 static void on_Mouse(int event, int x, int y, int flags, void*)
 86 {
 87     //处理鼠标不在窗口中的情况
 88     if (x < 0 || x >= g_srcImage.cols || y < 0 || y >= g_srcImage.rows) return;
 89     //处理鼠标左键相关消息
 90     if (event == EVENT_LBUTTONUP || !(flags & EVENT_FLAG_LBUTTON))   //左键抬起动作或处于没有按下状态
 91         prevPt = Point(-1, -1);
 92     else if (event == EVENT_LBUTTONDOWN)  //左键按下动作
 93         prevPt = Point(x, y);
 94     //鼠标左键按下并移动,绘制出白色线条
 95     else if (event == EVENT_MOUSEMOVE && (flags & EVENT_FLAG_LBUTTON))
 96     {
 97         Point pt(x, y);
 98         if (prevPt.x < 0) prevPt = pt;
 99         line(g_maskImage, prevPt, pt, Scalar::all(255), 5);
100         line(g_srcImage, prevPt, pt, Scalar::all(255), 5);
101         prevPt = pt;
102         imshow(WINDOW_NAME, g_srcImage);
103     }
104 
105 }

 


 

 

找山脊线算法:

     类似于骨架提取、图像细化、中轴线提取等思想

      把白色的线当做前景图,然后进行距离变换,之后进行全局阈值把前景全部包括在mask里面,接着利用原始图对mask进行操作,具体的细节看代码分析。

    以下是效果图,很完美的解决了问题。《图像处理实例》 之 寻找山脊线

《图像处理实例》 之 寻找山脊线

《图像处理实例》 之 寻找山脊线

《图像处理实例》 之 寻找山脊线

《图像处理实例》 之 寻找山脊线

算法的原理: 

 

    第一步:对图像进行距离变换---->>>之后阈值化(全局阈值就好)

《图像处理实例》 之 寻找山脊线

例如:效果图

    注释:这里不进行距离变换,直接进行阈值化也可以,但是对于特殊的图像效果很差。因为掩膜的应用可以结合分水岭[0:255]进行操作,没有距离变换的掩膜就只有255,这就和图像细化或者中轴线算法差不多了。

《图像处理实例》 之 寻找山脊线

 

原图

《图像处理实例》 之 寻找山脊线

 距离变换图

 《图像处理实例》 之 寻找山脊线

掩膜图

《图像处理实例》 之 寻找山脊线

结果图

《图像处理实例》 之 寻找山脊线

掩膜图

《图像处理实例》 之 寻找山脊线

 结果图

  

    第二步:对二值化图像进行标记(做mask)

        边界标记成4,这里为了防止越界,按照opencv c++的说法就是img.rows-1....

        背景标记成2

        前景标记成0,这里是除去图形边界的前景

        图形边界标记成1

《图像处理实例》 之 寻找山脊线

    第三步:分水岭算法

        进行操作的是距离图+掩膜图(dis+mask)

        这里使用涨水的方式对像素进行操作,从刚开始标记的边界1开始向内部涨水,由于距离变换之后映射到【0-255】,所以水从0开始涨,知道255为止:

《图像处理实例》 之 寻找山脊线

 

 

        这一步关键一点是内部的凹池,采用类似水漫算法进行:

 《图像处理实例》 之 寻找山脊线

 

 

 《图像处理实例》 之 寻找山脊线

 

 《图像处理实例》 之 寻找山脊线

            就这样把低于水平线的像素都填充为背景2了,当然按照其他的行列循环也是可以的,怎么写都行!

    注释:

      这里有几个小技巧:

            1.因为是从边界开始判断的,比如边界高度为100,那么水就从100开始涨,不然0-99是没意义的,具体代码见程序说217行。

            2.每一次的循环最少是图形一圈,因为这里以涨水为标准,比如上面的以原图二值化为掩膜,那么图像都为255,这时候就是一次性得出山脊线。

             简单的说就是每次处理的单位都是一个水平线,比如水平线是200,那么边界高度为201就是下一次涨水再进行处理。

            3.掩膜取得合适得出的图像效果最好,也不是越大越好,具体例子就不举了。

            4.因为这里查表遵循的是不断裂原则(貌似图像细化和骨架提取都是这样),回头想想你把掩膜图进行细化然后再和原图叠加也能进行图像修复哈!

    下面是我自己的一个误区:(这里大家看完上面说明就知道以下的问题是不存在的)    

        当然这里的算法不稳定,一些特殊的图像还是不行,比如下面的图像,水还没涨到200,图就已经分割完了,程序是水涨一次就分割一次,但是这个图明显都大于200.

《图像处理实例》 之 寻找山脊线

 

《图像处理实例》 之 寻找山脊线

 

 

 

 

  1 from scipy.misc import imread
  2 import matplotlib.pyplot as plt
  3 import numpy as np
  4 from numba import jit
  5 from skimage.data import camera
  6 import scipy.ndimage as ndimg
  7 from time import time
  8 import cv2
  9 from scipy.ndimage import label, generate_binary_structure
 10 
 11 strc = np.ones((3, 3), dtype=np.bool)
 12 
 13 
 14 def count(n):
 15     a = [(n>>i) & 1 for i in range(8)]
 16     if sum(a)<=1:return False
 17     if a[1] & a[3] & a[5] & a[7]:return False
 18     a = np.array([[a[0],a[1],a[2]],
 19                   [a[7],  0 ,a[3]],
 20                   [a[6],a[5],a[4]]])
 21     n = label(a, strc)[1]
 22     return n<2
 23 
 24 
 25 lut = np.array([count(n) for n in range(256)])
 26 lut = np.dot(lut.reshape((-1, 8)), [1, 2, 4, 8, 16, 32, 64, 128]).astype(np.uint8)
 27 
 28 
 29 #@jit
 30 def core(n):
 31     a = np.zeros(8, dtype=np.uint8)
 32     for i in range(8):
 33         a[i] = (n >> i * 2) & 3
 34     if a[1] == 1 and a[0] == 0: a[0] = 1
 35     if a[1] == 1 and a[2] == 0: a[0] = 1
 36     if a[3] == 1 and a[2] == 0: a[2] = 1
 37     if a[3] == 1 and a[4] == 0: a[4] = 1
 38     if a[5] == 1 and a[4] == 0: a[4] = 1
 39     if a[5] == 1 and a[6] == 0: a[6] = 1
 40     if a[7] == 1 and a[6] == 0: a[6] = 1
 41     if a[7] == 1 and a[0] == 0: a[0] = 1
 42     for i in range(8):
 43         if a[i] == 0 or a[i] == 2: a[i] = 0
 44         if a[i] == 1 or a[i] == 3: a[i] = 1
 45     return np.dot(a, [1, 2, 4, 8, 16, 32, 64, 128])
 46 
 47 
 48 index = np.array([core(i) for i in range(65536)], dtype=np.uint8)
 49 
 50 #
 51 '''
 52 lut = np.array([223, 221, 1, 221, 1, 221, 1, 221, 1, 0, 0, 0, 1, 221, 1, 221, 207, 204,
 53                 0, 204, 207,  51, 207, 1, 207, 204, 0, 204, 207, 51, 207, 51], dtype=np.uint8)
 54 '''
 55 
 56 #
 57 def nbs8(h, w):
 58     return np.array([-w - 1, -w, -w + 1, +1, +w + 1, +w, +w - 1, -1], dtype=np.int32)
 59 
 60 #类似创建2X2内核(上下左右4个数)
 61 def nbs4(h, w):
 62     return np.array([-1, -w, 1, w], dtype=np.int32)
 63 
 64 
 65 #@jit
 66 
 67 def fill(img, msk, p, level, pts, s, nbs, buf):
 68     n = 0
 69     cur = 0
 70     buf[0] = p      
 71     msk[p] = 2      
 72     bs = 1
 73     while cur < bs:
 74         p = buf[cur]
 75         for dp in nbs:
 76             if msk[p + dp] != 0: continue  
 77             if img[p + dp] < level: 
 78                 buf[bs] = p + dp            
 79                 msk[p + dp] = 2             
 80                 bs += 1                     
 81                 if bs == len(buf):
 82                     buf[:bs - cur] = buf[cur:bs]
 83                     bs -= cur
 84                     cur = 0
 85             else:                           
 86                 pts[s + n] = p + dp
 87                 msk[ p + dp] = 1
 88                 n += 1
 89         cur += 1
 90     return n
 91 
 92 
 93 #@jit
 94 def check(msk, p, nbs, lut):
 95     c = 0
 96     s = 0
 97     for i in range(8):
 98         v = msk[p + nbs[i]]
 99         # if v==0: c|=(0<<i*2)
100         if v == 1: c |= (1 << i * 2)
101         if v == 2: c |= (2 << i * 2)
102         if v == 3: c |= (3 << i * 2)
103     v = index[c]
104     if lut[v // 8] >> v % 8 & 1:
105         msk[p] = 2
106     else:
107         msk[p] = 3
108 
109 
110 #@jit
111 def step(img, msk, pts, s, level, nbs, nbs8):
112     ddd = 0
113     cur = 0
114     buf = np.zeros(10240, dtype=np.int64)
115     while cur < s:  
116         p = pts[cur]    
117         if img[p] > level:
118             cur += 1
119             continue
120 
121         filled = False
122         for dp in nbs:
123             if msk[p + dp] == 4: msk[p] = 2 
124             if msk[p + dp] == 0:            
125                 if img[p + dp] >= level:    
126                     msk[p + dp] = 1         
127                     pts[s] = p + dp         
128                     s += 1                  
129                 else:                       
130                     n = fill(img, msk, p, level, pts, s, nbs, buf)
131                     s += n      
132                     filled = True
133 
134         if filled:      
135             cur += 1
136             continue
137         elif msk[p] == 1:  
138             check(msk, p, nbs8, lut)   
139 
140         cur += 1   
141     return cur
142 
143 
144 @jit
145 def clear(msk, pts, s):
146     cur = 0
147     for c in range(s):
148         if msk[pts[c]] == 1:
149             pts[cur] = pts[c]
150             cur += 1
151     return cur
152 
153 
154 @jit
155 def collect(img, mark, nbs, pts):
156     bins = np.zeros(img.max() + 1, dtype=np.uint32) 
157     cur = 0     
158     '''
159     for p in range(len(mark)):      
160         if mark[p] != 0: continue
161         for dp in nbs:          
162             if mark[p + dp] == 1:
163                 mark[p] = 2
164     '''
165     for p in range(len(mark)):         
166         if mark[p] == 1: mark[p] = 2
167     for p in range(len(mark)):
168         if mark[p] != 0: continue
169         s = 0   
170         for dp in nbs:
171             if mark[p + dp] == 2:       
172                 s += 1                  
173                 mark[p] = 1             
174                 pts[cur] = p           
175                 cur += 1               
176                 break
177         if s == 0: bins[img[p]] += 1    
178     return cur, bins
179 
180 
181 #@jit
182 def watershed(img, mark):
183     oimg, omark = img, mark
184     ndim = img.ndim
185     mark[[0, -1], :] = 4   
186     mark[:, [0, -1]] = 4    
187 
188     nb4 = nbs4(*img.shape) 
189     nb8 = nbs8(*img.shape)
190     acc = np.cumprod((1,) + img.shape[::-1][:-1])[::-1] 
191     img = img.ravel()       
192     mark = mark.ravel()     
193 
194     pts = np.zeros(131072, dtype=np.int64) 
195     s, bins = collect(img, mark, nb4, pts)  
196     for level in range(len(bins)):  
197         if bins[level] == 0: continue
198         s = clear(mark, pts, s)     
199         s = step(img, mark, pts, s, level, nb4, nb8)
200 '''
201 dem = cv2.imread('gis1.jpg',0)
202 plt.imshow(dem, cmap='gray')
203 mark = (dem > 150).astype(np.uint8)
204 plt.imshow(mark, cmap='gray')
205 plt.show()
206 
207 watershed(dem, mark.copy())
208 start = time()
209 watershed(dem, mark)
210 print(time() - start)
211 dem[:] = dem * 0.8
212 dem[mark == 3] = 255
213 plt.imshow(dem, cmap='gray')
214 plt.show()
215 '''
216 #dem = imread('line2.png')
217 dem = cv2.imread('0.jpg')
218 dem = cv2.cvtColor(dem,cv2.COLOR_BGR2GRAY)
219 ret2, dem = cv2.threshold(dem, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)
220 dis = ndimg.distance_transform_edt(~dem).astype(np.uint8)
221 dis = ~dis
222 mark = (dis<230).astype(np.uint8)
223 plt.imshow(dis, cmap='gray')
224 plt.imshow(mark, cmap='gray')
225 watershed(dis, mark)
226 dem //= 2
227 dem[mark==3] = 255
228 plt.imshow(dem, cmap='gray')
229 plt.show()

 C++版本:

 

  1 //---table
  2 uchar lut[] = { 200, 206, 220, 204, 0, 207, 0, 204, 0, 207, 221, 51, 1, 207, 221, 51,
  3 0, 0, 221, 204, 0, 0, 0, 204, 1, 207, 221, 51, 1, 207, 221, 51 };
  4 
  5 //---FindRidge
  6 void FindRidge(InputArray& _src, Mat& mask, vector<Point> Edge_Point, uchar thred)
  7 {
  8     Mat src = _src.getMat();// , mask = _mask.getMat();
  9 
 10     mask = src.clone();
 11     bitwise_not(mask, mask);
 12     distanceTransform(mask, mask, DIST_L2, DIST_MASK_3, 5);
 13     normalize(mask, mask, 0, 255, NORM_MINMAX);
 14     mask.convertTo(mask, CV_8UC1);
 15     threshold(mask, mask, thred, 255, THRESH_BINARY_INV);
 16     Mat temp = mask.clone();
 17 
 18     bitwise_not(mask, mask);
 19     mask = mask - 253;
 20     Mat rows = Mat::ones(Size(src.cols, 1), CV_8UC1), cols = Mat::zeros(Size(1, src.rows), CV_8UC1);
 21     rows.setTo(4); cols.setTo(4);
 22     Mat src_rows_beg = mask.row(0),                src_cols_beg = mask.col(0);
 23     Mat src_rows_end = mask.row(src.rows - 1),    src_cols_end = mask.col(src.cols - 1);
 24     rows.copyTo(src_rows_beg); rows.copyTo(src_rows_end);
 25     cols.copyTo(src_cols_beg); cols.copyTo(src_cols_end);
 26 
 27     Edge_Point = FindEdge(temp, mask);
 28     bool TF = true;
 29     while (TF)
 30     {
 31         TF = false;
 32         for (size_t i = 0; i < mask.rows - 1; i++)
 33         {
 34             uchar* msk_up = mask.ptr(i - 1);
 35             uchar* msk = mask.ptr(i);
 36             uchar* msk_dw = mask.ptr(i + 1);
 37             for (size_t j = 0; j < mask.cols - 1; j++)
 38             {
 39                 uchar _temp_data = msk[j];
 40                 msk[j] = msk[j] == 2 && (msk_up[j] == 255 || msk_up[j] == 0)
 41                     && (msk_dw[j] == 255 || msk_dw[j] == 0)
 42                     && (msk[j - 1] == 255 || msk[j - 1] == 0)
 43                     && (msk[j + 1] == 255 || msk[j + 1] == 0) ? 0 : msk[j];
 44                 msk[j] = msk[j] == 0 && (msk_up[j] == 2 || msk_dw[j] == 2 || msk[j - 1] == 2 || msk[j + 1] == 2) ? 2 : msk[j];
 45                 TF = _temp_data != msk[j] ? true : TF;
 46             }
 47         }
 48     }
 49 
 50     distanceTransform(src, src, DIST_L2, DIST_MASK_3, 5);
 51     normalize(src, src, 0, 255, NORM_MINMAX);
 52     src.convertTo(src, CV_8UC1);
 53 
 54     const int histSize = 255;
 55     float range[] = { 0, 255 };
 56     const float* histRange = { range };
 57     Mat hist;
 58     calcHist(&src, 1, 0, Mat(), hist, 1, &histSize, &histRange, true, false);
 59 
 60     hist = hist.reshape(1,1);
 61     normalize(hist, hist, 0, 1000, NORM_MINMAX);
 62     hist.convertTo(hist, CV_32FC1);
 63     //float* ptr = hist.ptr(0);
 64     for (size_t level = 0; level <= 255; level++)
 65     {
 66         if (!hist.at<float>(0,level)) continue;
 67         FloorEdge(src, Edge_Point, mask, level);
 68     }
 69 }
 70 
 71 /*
 72 
 73 vector<Point> FindEdge(InputArray& _src, Mat& mask)
 74 {
 75     Mat src1 = _src.getMat(),src = src1.clone();
 76     Mat kernel = getStructuringElement(MORPH_RECT, Size(3, 3));
 77     morphologyEx(src, src, MORPH_ERODE, kernel);
 78     vector<Point> wjy_Point;
 79     vector<vector<Point>> contours;
 80     vector<Vec4i> hierarchy;
 81     findContours(src, contours, hierarchy, RETR_TREE, CHAIN_APPROX_NONE, Point(-1, -1));
 82     for (size_t i = 0; i < contours.size(); i++)
 83     {
 84         for (size_t j = 0; j < contours[i].size(); j++)
 85         {
 86             wjy_Point.push_back(contours[i][j]);
 87             mask.at<uchar>(contours[i][j]) = 255;
 88         }
 89     }
 90     return wjy_Point;
 91 }
 92 */
 93 
 94 
 95 vector<Point> FindEdge(Mat& src,Mat& mask)
 96 {
 97     //Mat src = mask.clone();
 98     Mat kernel = getStructuringElement(MORPH_RECT, Size(3, 3));
 99     //morphologyEx(src, src, MORPH_ERODE, kernel);
100     vector<Point> wjy_Point;
101     vector<vector<Point>> contours;
102     vector<Vec4i> hierarchy;
103     findContours(src, contours, hierarchy, RETR_TREE, CHAIN_APPROX_NONE, Point(-1, -1));
104     for (size_t i = 0; i < contours.size(); i++)
105     {
106         for (size_t j = 0; j < contours[i].size(); j++)
107         {
108             wjy_Point.push_back(contours[i][j]);
109             mask.at<uchar>(contours[i][j]) = 255;
110         }
111     }
112     return wjy_Point;
113 }
114 
115 
116 void FloorEdge(InputArray& _src, vector<Point>& Edge_Point, Mat& mask,int level)
117 {
118     Mat src = _src.getMat();
119     for (int i = 0; i < Edge_Point.size(); i++)
120     {
121         vector<Point> temp_vector;
122         temp_vector.push_back(Point(Edge_Point[i].x, Edge_Point[i].y - 1));
123         temp_vector.push_back(Point(Edge_Point[i].x, Edge_Point[i].y + 1));
124         temp_vector.push_back(Point(Edge_Point[i].x - 1, Edge_Point[i].y));
125         temp_vector.push_back(Point(Edge_Point[i].x + 1, Edge_Point[i].y));
126         uchar* msk = mask.ptr(Edge_Point[i].y);
127         uchar* img = src.ptr(Edge_Point[i].y);
128         if (img[Edge_Point[i].x] > level)    continue;
129         bool Flag = true;
130         uchar count_num = 0;
131         for (size_t j = 0; j < temp_vector.size(); j++)
132         {
133             uchar* pre_data = mask.ptr(temp_vector[j].y);
134             if (pre_data[temp_vector[j].x] == 2 || pre_data[temp_vector[j].x] == 4)
135             {
136                 pre_data[temp_vector[j].x] = 2;
137                 continue;
138             }
139             else if (pre_data[temp_vector[j].x] == 128 || pre_data[temp_vector[j].x] == 255)
140             {
141                 continue;                
142                 count_num++;
143             }
144             else
145             {
146                 if (src.at<uchar>(temp_vector[j]) >= level)
147                 {            
148                     count_num++;
149                     pre_data[temp_vector[j].x] = 255;
150                     Edge_Point.push_back(temp_vector[j]);    
151                     //Edge_Point.insert(Edge_Point.begin()+i+1,temp_vector[j]);
152                 }
153                 else
154                 {
155                     int temp = FillBlock(src, Edge_Point, mask, level, Edge_Point[i]);
156                     Flag = false;
157                 }
158             }
159         }
160         if (false)
161         {
162             msk[Edge_Point[i].x] = 128;
163             Edge_Point.erase(Edge_Point.begin() + i);
164             i--;
165             continue;
166         }
167         else if (count_num == 4)
168         {
169             Edge_Point.push_back(Edge_Point[i]);
170             Edge_Point.erase(Edge_Point.begin() + i);
171             i--;
172             continue;
173         }
174         else if (msk[Edge_Point[i].x] == 255)
175         {
176             msk[Edge_Point[i].x] = CheckData(mask, Edge_Point[i]) == true ? 128 : 2;
177             Edge_Point.erase(Edge_Point.begin() + i);
178             i--;
179         }
180     }
181 }
182 
183 int FillBlock(InputArray& _src, vector<Point>& Edge_Point, Mat& mask, int level, Point center)
184 {
185     Mat src = _src.getMat();
186     mask.at<uchar>(center) = 2;
187     vector<Point> fill_point;
188     int count = 0, count_mount = 1;
189     fill_point.push_back(center);
190     while (count < count_mount)
191     {
192         vector<uchar*> img;
193         vector<uchar*> msk;
194         for (int i = -1; i < 2; i++)
195         {
196             img.push_back(src.ptr<uchar>(fill_point[count].y + i));
197             msk.push_back(mask.ptr<uchar>(fill_point[count].y + i));
198         }
199         for (size_t i = 0; i < 3; i++)
200         {
201             for (int j = -1; j < 2; j++)
202             {
203                 if (img[i][fill_point[count].x + j] < level && !(j == 0 && i == 1) && msk[i][fill_point[count].x + j] == 0)
204                 {
205                     fill_point.push_back(Point(fill_point[count].x + j, fill_point[count].y + i - 1));
206                     msk[i][fill_point[count].x + j] = 2;
207                 }
208                 else if (img[i][fill_point[count].x + j] >= level && msk[i][fill_point[count].x + j] == 0)
209                 {
210                     Edge_Point.push_back(Point(fill_point[count].x + j, fill_point[count].y + i - 1));
211                     msk[i][fill_point[count].x + j] = 255;
212                 }
213             }
214         }
215         //msk[1][fill_point[count].x] = 2;
216         count_mount = fill_point.size() - 1;
217         fill_point.erase(fill_point.begin());
218     }
219     return 0;
220 }
221 
222 
223 bool CheckData(Mat& mask, Point center)
224 {
225     uchar* msk_up = mask.ptr(center.y - 1);
226     uchar* msk = mask.ptr(center.y);
227     uchar* msk_dw = mask.ptr(center.y + 1);
228     int num[8];
229     int sum = (num[0] = msk_up[center.x - 1] == 255 || msk_up[center.x - 1] == 128 || msk_up[center.x - 1] == 0 ? 1 : 0)
230             + (num[1] = msk_up[center.x] == 255 || msk_up[center.x] == 128 || msk_up[center.x] == 0 ? 1 : 0) * 2
231             + (num[2] = msk_up[center.x + 1] == 255 || msk_up[center.x + 1] == 128 || msk_up[center.x + 1] == 0 ? 1 : 0) * 4
232             + (num[3] = msk[center.x - 1] == 255 || msk[center.x - 1] == 128 || msk[center.x - 1] == 0 ? 1 : 0) * 8
233             + (num[4] = msk[center.x + 1] == 255 || msk[center.x + 1] == 128 || msk[center.x + 1] == 0 ? 1 : 0) * 16
234             + (num[5] = msk_dw[center.x - 1] == 255 || msk_dw[center.x - 1] == 128 || msk_dw[center.x - 1] == 0 ? 1 : 0) * 32
235             + (num[6] = msk_dw[center.x] == 255 || msk_dw[center.x] == 128 || msk_dw[center.x] == 0 ? 1 : 0) * 64
236             + (num[7] = msk_dw[center.x + 1] == 255 || msk_dw[center.x + 1] == 128 || msk_dw[center.x + 1] == 0 ? 1 : 0) * 128;
237     return ((lut[uchar(sum / 8)] >> sum % 8) & 1) != 1 ? true : false;
238 }