OpenCV for Android (Eclipse) 环境配置,请参考:
https://blog.youkuaiyun.com/weixin_39591047/article/details/80456065
opencv 提取骨架 -- 细化,请参考:
https://blog.youkuaiyun.com/jia20003/article/details/52142992
我转化成 Android java 代码如下:
private void Thin2(Mat src,Mat dst){
if(src.type()!=CvType.CV_8UC1)
{
Log.i("Thin","只能处理二值或灰度图像");
return;
}
//非原地操作时候,copy src到dst
if(dst!=src)
{
src.copyTo(dst);
Log.i("Thin","Copy图像");
}
int i, j, n;
int width, height;
width = src.cols() ;
height = src.rows();
byte[] p=new byte[src.cols()*src.rows()];
int [] flagmap=new int [width*height];
dst.get(0, 0, p);
// 距离变化
boolean stop = false;
while(!stop) {
// step one
boolean s1 = step1Scan(p, flagmap, width, height);
deletewithFlag(p, flagmap);
flagmap=new int [width*height];
// step two
boolean s2 = step2Scan(p, flagmap, width, height);
deletewithFlag(p, flagmap);
flagmap=new int [width*height];
if(s1 && s2) {
stop = true;
}
}
dst.put(0, 0, p);
}
private boolean step1Scan(byte[] input, int[] flagmap, int width, int height) {
boolean stop = true;
int fcolor= 255;
int bc = (255 - fcolor);
int p1=0, p2=0, p3=0;
int p4=0, p5=0, p6=0;
int p7=0, p8=0, p9=0;
int offset = 0;
//之所以减1,是方便处理8邻域,防止越界
for(int row=1; row<height-1; row++) {
offset = row*width;
for(int col=1; col<width-1; col++) {
p1 = (input[offset+col])&0xff;
if(p1 == bc) continue;
p2 = (input[offset-width+col])&0xff;
p3 = (input[offset-width+col+1])&0xff;
p4 = (input[offset+col+1])&0xff;
p5 = (input[offset+width+col+1])&0xff;
p6 = (input[offset+width+col])&0xff;
p7 = (input[offset+width+col-1])&0xff;
p8 = (input[offset+col-1])&0xff;
p9 = (input[offset-width+col-1])&0xff;
// match 1 - 前景像素; 0 - 背景像素
p1 = (p1 == fcolor) ? 1 : 0;
p2 = (p2 == fcolor) ? 1 : 0;
p3 = (p3 == fcolor) ? 1 : 0;
p4 = (p4 == fcolor) ? 1 : 0;
p5 = (p5 == fcolor) ? 1 : 0;
p6 = (p6 == fcolor) ? 1 : 0;
p7 = (p7 == fcolor) ? 1 : 0;
p8 = (p8 == fcolor) ? 1 : 0;
p9 = (p9 == fcolor) ? 1 : 0;
int con1 = p2+p3+p4+p5+p6+p7+p8+p9;
/* String sequence = "" + String.valueOf(p2) + String.valueOf(p3) + String.valueOf(p4) + String.valueOf(p5) +
String.valueOf(p6) + String.valueOf(p7) + String.valueOf(p8) + String.valueOf(p9) + String.valueOf(p2);
int index1 = sequence.indexOf("01");
int index2 = sequence.lastIndexOf("01");
*/
int A =0;
A= ((p2 == 0 && p3 == 1)? 1:0);
A+=(p3 == 0 && p4 == 1)?1:0;
A+= (p4 == 0 && p5 == 1)?1:0;
A+= (p5 == 0 && p6 == 1) ?1:0;
A+= (p6 == 0 && p7 == 1) ?1:0;
A+= (p7 == 0 && p8 == 1)?1:0;
A+= (p8 == 0 && p9 == 1) ?1:0;
A+= (p9 == 0 && p2 == 1)?1:0;;
int con3 = p2*p4*p6;
int con4 = p4*p6*p8;
if((con1 >= 2 && con1 <= 6) && (A == 1) && con3 == 0 && con4 == 0) {
flagmap[offset+col] = 1;
stop = false;
}
}
}
return stop;
}
private boolean step2Scan(byte[] input, int[] flagmap, int width, int height) {
boolean stop = true;
int fcolor= 255;
int bc = (255 - fcolor);
int p1=0, p2=0, p3=0;
int p4=0, p5=0, p6=0;
int p7=0, p8=0, p9=0;
int offset = 0;
for(int row=1; row<height-1; row++) {
offset = row*width;
for(int col=1; col<width-1; col++) {
p1 = (input[offset+col])&0xff;
if(p1 == bc) continue;
p2 = (input[offset-width+col])&0xff;
p3 = (input[offset-width+col+1])&0xff;
p4 = (input[offset+col+1])&0xff;
p5 = (input[offset+width+col+1])&0xff;
p6 = (input[offset+width+col])&0xff;
p7 = (input[offset+width+col-1])&0xff;
p8 = (input[offset+col-1])&0xff;
p9 = (input[offset-width+col-1])&0xff;
// match 1 - 前景像素 0 - 背景像素
p1 = (p1 == fcolor) ? 1 : 0;
p2 = (p2 == fcolor) ? 1 : 0;
p3 = (p3 == fcolor) ? 1 : 0;
p4 = (p4 == fcolor) ? 1 : 0;
p5 = (p5 == fcolor) ? 1 : 0;
p6 = (p6 == fcolor) ? 1 : 0;
p7 = (p7 == fcolor) ? 1 : 0;
p8 = (p8 == fcolor) ? 1 : 0;
p9 = (p9 == fcolor) ? 1 : 0;
int con1 = p2+p3+p4+p5+p6+p7+p8+p9;
/* String sequence = "" + String.valueOf(p2) + String.valueOf(p3) + String.valueOf(p4) + String.valueOf(p5) +
String.valueOf(p6) + String.valueOf(p7) + String.valueOf(p8) + String.valueOf(p9) + String.valueOf(p2);
int index1 = sequence.indexOf("01");
int index2 = sequence.lastIndexOf("01");
*/
int A =0;
A= (p2 == 0 && p3 == 1)? 1:0;
A+=(p3 == 0 && p4 == 1)?1:0;
A+= (p4 == 0 && p5 == 1)?1:0;
A+= (p5 == 0 && p6 == 1) ?1:0;
A+= (p6 == 0 && p7 == 1) ?1:0;
A+= (p7 == 0 && p8 == 1)?1:0;
A+= (p8 == 0 && p9 == 1) ?1:0;
A+= (p9 == 0 && p2 == 1)?1:0;;
int con3 = p2*p4*p8;
int con4 = p2*p6*p8;
if((con1 >= 2 && con1 <= 6) && (A==1) && con3 == 0 && con4 == 0) {
flagmap[offset+col] = 1;
stop = false;
}
}
}
return stop;
}
private void deletewithFlag(byte[] pixels, int[] flagmap) {
byte fcolor=(byte) 255;
byte bc = (byte) (255 - fcolor);
for(int i=0; i<pixels.length; i++) {
if(flagmap[i] == 1) {
pixels[i] =bc;
}
}
}