基于Mat变换的骨架提取Java

Posted 萌虾

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基于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 /**
  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 }

 

以上是关于基于Mat变换的骨架提取Java的主要内容,如果未能解决你的问题,请参考以下文章

图像的骨架提取

如何从 glm::quat 和 glm::mat4 中提取偏航俯仰滚动

数字图像处理课程设计(基于matlab的Hough变换检测图像边缘提取,包含完整代码)

Java Open CV 3.4.2如何从Mat对象中提取不同的通道?

基于NSCT变换的人脸图像特征提取matlab仿真

通过 Java 正则表达式提取 semver 版本字符串的片段