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