基于Mat变换的骨架提取Java

针对一副二值图像,区域内的点只有背景点(白点,0值)和前景点(黑点,1值)。对于给定区域的像素点逐次应用两个基本步骤,以提取骨架:

step1,如果一个像素点满足下列4个条件,那么将它标记为要删除的点:

(1)2<=N(p1)<=6,其中N(p1)=p2+p3+p4+...+p8+p9;

(2)T(p1)=1,其中T(p1)是以p2,p3,...,p8,p9,p2的次序旋转,从0到1的变换次数;

(3)p2*p4*p6=0;

(4)p4*p6*p8=0.

step2,条件(1)(2)不变,但是条件(3)(4)变为:

(3)p2*p4*p8=0;

(4)p2*p6*p8=0.

这里,每个像素点的八邻域结构为

p9 p2 p3
p8 p1 p4
p7 p6 p5

 

 

 

基于Mat变换的骨架提取的完整步骤:

(1)执行step1,对需要删除的边界点进行标记;

(2)删除标记点;

(3)执行step2,对需要删除的边界点进行标记;

(4)删除标记点;

(1)到(4)属于一个循环过程,不断反复进行这一循环过程,检测是否存在符合条件的删除点,直到再也找不到可删除的点的时候,说明此时骨架已经生成,结束循环。

  1 package com.example.lenovo.linehough;
  2 
  3 import android.graphics.Color;
  4 
  5 public class Mat {
  6 
  7     public static int[] matswitch(int w, int h, int[] inputs) {
  8         int[] imgBuf = new int[w * h];
  9         int[] neighbor = new int[10];
 10         int[] mark = new int[w * h];
 11         int markNum1;
 12         int markNum2;
 13         boolean s = true;
 14         for(int index=0;index<w*h;index++)
 15             imgBuf[index] = inputs[index];
 16         while (s) {
 17             //第一步,统一黑点值为1,白点值为0
 18             markNum1 = 0;//步骤1中标记被删除的边界点的个数
 19             for (int x = 1; x < w - 1; x++) {
 20                 for (int y = 1; y < h - 1; y++) {
 21                     //条件1:p必须是边界点,值为1, 8邻域内至少有1个像素点值为0
 22                     if (imgBuf[y * w + x] == Color.WHITE) continue;
 23                     int[] detectBlack = new int[10];
 24                     neighbor[2] = ((imgBuf[(y - 1) * w + x] & 0x00ff0000) >> 16) / 255;//黑点neighbor为0,白点neighbor为1
 25                     neighbor[3] = ((imgBuf[(y - 1) * w + x + 1] & 0x00ff0000) >> 16) / 255;
 26                     neighbor[4] = ((imgBuf[y * w + x + 1] & 0x00ff0000) >> 16) / 255;
 27                     neighbor[5] = ((imgBuf[(y + 1) * w + x + 1] & 0x00ff0000) >> 16) / 255;
 28                     neighbor[6] = ((imgBuf[(y + 1) * w + x] & 0x00ff0000) >> 16) / 255;
 29                     neighbor[7] = ((imgBuf[(y + 1) * w + x - 1] & 0x00ff0000) >> 16) / 255;
 30                     neighbor[8] = ((imgBuf[(y) * w + x - 1] & 0x00ff0000) >> 16) / 255;
 31                     neighbor[9] = ((imgBuf[(y - 1) * w + x - 1] & 0x00ff0000) >> 16) / 255;
 32                     for (int i = 2; i <= 9; i++) {
 33                         if (neighbor[i] == 0)
 34                             detectBlack[i]++;//(黑点)neighbor为0,detectBlack就为1;(白点)neighbor为1,detectBlack就为0
 35                     }
 36                     //8领域的点都是黑点,证明该点不是边界点,退出该轮循环,检测下一个点
 37                     if (detectBlack[2] * detectBlack[3] * detectBlack[4] * detectBlack[5]
 38                             * detectBlack[6] * detectBlack[7] * detectBlack[8] * detectBlack[9] != 0)
 39                         continue;
 40 
 41                     //条件2:2<=N(p)<=6
 42                     int np = (detectBlack[2] + detectBlack[3] + detectBlack[4] + detectBlack[5]
 43                             + detectBlack[6] + detectBlack[7] + detectBlack[8] + detectBlack[9]);
 44                     if (np < 2 || np > 6) continue;
 45 
 46                     //条件3:T(p)=1
 47                     int tp = 0;
 48                     for (int i = 3; i <= 9; i++) {
 49                        /* if(neighbor[i]-neighbor[i-1]==Color.WHITE-Color.BLACK )*/
 50                         if (detectBlack[i] - detectBlack[i - 1] == 1)
 51                             tp++;
 52                     }
 53                     if (detectBlack[2] - detectBlack[9] == 1)
 54                         tp++;
 55                     if (tp != 1) continue;
 56 
 57                     //条件4:p2*p4*p6=0
 58                     if (detectBlack[2] * detectBlack[4] * detectBlack[6] != 0)
 59                         continue;
 60                     //条件5:p4*p6*p8=0
 61                     if (detectBlack[4] * detectBlack[6] * detectBlack[8] != 0)
 62                         continue;
 63 
 64                     //标记要被删除的点
 65                     mark[y * w + x] = 1;
 66                     markNum1++;
 67                 }
 68             }
 69 
 70             //将标记删除的点置为背景色
 71             if (markNum1 > 0) {
 72                 for (int x = 1; x < w - 1; x++) {
 73                     for (int y = 1; y < h - 1; y++) {
 74                         //删除被标记的点,即置为背景色黑色
 75                         if (mark[y * w + x] == 1) {
 76                             imgBuf[y * w + x] = Color.WHITE;
 77                         }
 78                     }
 79                 }
 80             }
 81 
 82 
 83             //第二步
 84             markNum2 = 0;//步骤2中标记被删除的点的个数
 85             for (int x = 1; x < w - 1; x++) {
 86                 for (int y = 1; y < h - 1; y++) {
 87                     //条件1:p必须是前景点BLACK
 88                     if (imgBuf[y * w + x] == Color.WHITE) continue;
 89                     int[] detectBlack = new int[10];
 90                     neighbor[2] = ((imgBuf[(y - 1) * w + x] & 0x00ff0000) >> 16) / 255;
 91                     neighbor[3] = ((imgBuf[(y - 1) * w + x + 1] & 0x00ff0000) >> 16) / 255;
 92                     neighbor[4] = ((imgBuf[y * w + x + 1] & 0x00ff0000) >> 16) / 255;
 93                     neighbor[5] = ((imgBuf[(y + 1) * w + x + 1] & 0x00ff0000) >> 16) / 255;
 94                     neighbor[6] = ((imgBuf[(y + 1) * w + x] & 0x00ff0000) >> 16) / 255;
 95                     neighbor[7] = ((imgBuf[(y + 1) * w + x - 1] & 0x00ff0000) >> 16) / 255;
 96                     neighbor[8] = ((imgBuf[(y) * w + x - 1] & 0x00ff0000) >> 16) / 255;
 97                     neighbor[9] = ((imgBuf[(y - 1) * w + x - 1] & 0x00ff0000) >> 16) / 255;
 98                     for (int i = 2; i < 10; i++) {
 99                         if (neighbor[i] == 0) detectBlack[i]++;
100                     }
101 
102                     if (detectBlack[2] * detectBlack[3] * detectBlack[4] * detectBlack[5]
103                             * detectBlack[6] * detectBlack[7] * detectBlack[8] * detectBlack[9] != 0)
104                         continue;
105 
106                     //条件2:2<=N(p)<=6
107                     int np = (detectBlack[2] + detectBlack[3] + detectBlack[4] + detectBlack[5]
108                             + detectBlack[6] + detectBlack[7] + detectBlack[8] + detectBlack[9]);
109                     if (np < 2 || np > 6) continue;
110 
111                     //条件3:T(p)=1
112                     int tp = 0;
113                     for (int i = 3; i <= 9; i++) {
114                        /* if(neighbor[i]-neighbor[i-1]==Color.WHITE-Color.BLACK )*/
115                         if (detectBlack[i] - detectBlack[i - 1] == 1)
116                             tp++;
117                     }
118                     if (detectBlack[2] - detectBlack[9] == 1)
119                         tp++;
120                     if (tp != 1) continue;
121 
122                     //条件4:p2*p4*p8==0
123                     if (detectBlack[2] * detectBlack[4] * detectBlack[8] != 0)
124                         continue;
125                     //条件5:p2*p6*p8==0
126                     if (detectBlack[2] * detectBlack[6] * detectBlack[8] != 0)
127                         continue;
128 
129                     //标记删除
130                     mark[y * w + x] = 1;
131                     markNum2++;
132                 }
133             }
134 
135             //将标记删除的点置为背景色WHITE
136             if (markNum2 > 0) {
137                 for (int x = 1; x < w - 1; x++) {
138                     for (int y = 1; y < h - 1; y++) {
139                         if (mark[y * w + x] == 1) {
140                             imgBuf[y * w + x] = Color.WHITE;
141                         }
142                     }
143                 }
144             }
145             //先步骤1再步骤2,一次周期循环后,不再出现标记删除的点时,说明已生成骨架了
146             if (markNum1 == 0 && markNum2 == 0) s = false;
147             else s = true;
148         }
149         return imgBuf;
150     }
151 
152 
153 }

 

posted on 2017-09-10 09:53  萌虾  阅读(558)  评论(0编辑  收藏  举报

导航