Android实现Canny算法

package com.example.yanhuang.canny;


import android.content.Context;
import android.graphics.Bitmap;
import android.widget.ImageView;
import android.graphics.Bitmap.Config;  
import android.graphics.drawable.BitmapDrawable;
 
public class EdgeDetector {

final float ORIENT_SCALE = 40F;
    private int height;
    private int width;
    private int picsize;
    private int data[];
    private int derivative_mag[];
    private int magnitude[];
    private int orientation[];
    //private ImageView sourceImage;
    //private ImageView edgeImage;
    private int threshold1;
    private int threshold2;
    private int threshold;
    private int widGaussianKernel;
    private Context context;
    private Bitmap sourceBitmap;
    private Bitmap edgeBitmap;
    /**

*/
private static final long serialVersionUID = 1L;
public EdgeDetector(Context context) {
this.context = context;
threshold1 = 50;
        threshold2 = 230;
        setThreshold(128);
        setWidGaussianKernel(15);   
    }


    public void process() throws EdgeDetectorException {
           if (threshold < 0 || threshold > 255)
                   throw new EdgeDetectorException("The value of the threshold is out of its valid range.");
           if (widGaussianKernel < 3 || widGaussianKernel > 40)
                   throw new EdgeDetectorException("The value of the widGaussianKernel is out of its valid range.");
           width = sourceBitmap.getWidth();
           height = sourceBitmap.getHeight();
           //width = 328;
           //height = 140;
           System.out.println("2++++"+sourceBitmap.getWidth()+";"+sourceBitmap.getHeight());
           picsize = width * height;
           System.out.println("-------"+picsize);
           data = new int[picsize];
           magnitude = new int[picsize];
           orientation = new int[picsize];
           float f = 1.0F;
           canny_core(f, widGaussianKernel);
           thresholding_tracker(threshold1, threshold2);
           for (int i = 0; i < picsize; i++)
                   if (data[i] > threshold)
                           data[i] = 0xff000000;
                   else
                           data[i] = -1;


           edgeBitmap = pixels2image(data);
           data = null;
           magnitude = null;
           orientation = null;
    }


    private void canny_core(float f, int i) {
           boolean flag = false;
           boolean flag1 = false;
           derivative_mag = new int[picsize];
           float af4[] = new float[i];
           float af5[] = new float[i];
           float af6[] = new float[i];
           data = image2pixels(sourceBitmap);
           int k4 = 0;
           do {
                   if (k4 >= i)
                           break;
                   float f1 = gaussian(k4, f);
                   if (f1 <= 0.005F && k4 >= 2)
                           break;
                   float f2 = gaussian((float) k4 - 0.5F, f);
                   float f3 = gaussian((float) k4 + 0.5F, f);
                   float f4 = gaussian(k4, f * 0.5F);
                   af4[k4] = (f1 + f2 + f3) / 3F / (6.283185F * f * f);
                   af5[k4] = f3 - f2;
                   af6[k4] = 1.6F * f4 - f1;
                   k4++;
           } while (true);
           int j = k4;
           float af[] = new float[picsize];
           float af1[] = new float[picsize];
           int j1 = width - (j - 1);
           int l = width * (j - 1);
           int i1 = width * (height - (j - 1));
           for (int l4 = j - 1; l4 < j1; l4++) {
                   for (int l5 = l; l5 < i1; l5 += width) {
                           int k1 = l4 + l5;
                           float f8 = (float) data[k1] * af4[0];
                           float f10 = f8;
                           int l6 = 1;
                           int k7 = k1 - width;
                           for (int i8 = k1 + width; l6 < j; i8 += width) {
                                  f8 += af4[l6] * (float) (data[k7] + data[i8]);
                                  f10 += af4[l6] * (float) (data[k1 - l6] + data[k1 + l6]);
                                  l6++;
                                  k7 -= width;
                           }


                           af[k1] = f8;
                           af1[k1] = f10;
                   }


           }


           float af2[] = new float[picsize];
           for (int i5 = j - 1; i5 < j1; i5++) {
                   for (int i6 = l; i6 < i1; i6 += width) {
                           float f9 = 0.0F;
                           int l1 = i5 + i6;
                           for (int i7 = 1; i7 < j; i7++)
                                  f9 += af5[i7] * (af[l1 - i7] - af[l1 + i7]);


                           af2[l1] = f9;
                   }


           }


           af = null;
           float af3[] = new float[picsize];
           for (int j5 = k4; j5 < width - k4; j5++) {
                   for (int j6 = l; j6 < i1; j6 += width) {
                           float f11 = 0.0F;
                           int i2 = j5 + j6;
                           int j7 = 1;
                           for (int l7 = width; j7 < j; l7 += width) {
                                  f11 += af5[j7] * (af1[i2 - l7] - af1[i2 + l7]);
                                  j7++;
                           }


                           af3[i2] = f11;
                   }


           }


           af1 = null;
           j1 = width - j;
           l = width * j;
           i1 = width * (height - j);
           for (int k5 = j; k5 < j1; k5++) {
                   for (int k6 = l; k6 < i1; k6 += width) {
                           int j2 = k5 + k6;
                           int k2 = j2 - width;
                           int l2 = j2 + width;
                           int i3 = j2 - 1;
                           int j3 = j2 + 1;
                           int k3 = k2 - 1;
                           int l3 = k2 + 1;
                           int i4 = l2 - 1;
                           int j4 = l2 + 1;
                           float f6 = af2[j2];
                           float f7 = af3[j2];
                           float f12 = hypotenuse(f6, f7);
                           int k = (int) ((double) f12 * 20D);
                           derivative_mag[j2] = k >= 256 ? 255 : k;
                           float f13 = hypotenuse(af2[k2], af3[k2]);
                           float f14 = hypotenuse(af2[l2], af3[l2]);
                           float f15 = hypotenuse(af2[i3], af3[i3]);
                           float f16 = hypotenuse(af2[j3], af3[j3]);
                           float f18 = hypotenuse(af2[l3], af3[l3]);
                           float f20 = hypotenuse(af2[j4], af3[j4]);
                           float f19 = hypotenuse(af2[i4], af3[i4]);
                           float f17 = hypotenuse(af2[k3], af3[k3]);
                           float f5;
                           if (f6 * f7 <= (float) 0
                                  ? Math.abs(f6) >= Math.abs(f7)
                                  ? (f5 = Math.abs(f6 * f12))
                                          >= Math.abs(f7 * f18 - (f6 + f7) * f16)
                                  && f5
                                          > Math.abs(f7 * f19 - (f6 + f7) * f15) : (
                                                 f5 = Math.abs(f7 * f12))
                                          >= Math.abs(f6 * f18 - (f7 + f6) * f13)
                                  && f5
                                          > Math.abs(f6 * f19 - (f7 + f6) * f14) : Math.abs(f6)
                                          >= Math.abs(f7)
                                          ? (f5 = Math.abs(f6 * f12))
                                                 >= Math.abs(f7 * f20 + (f6 - f7) * f16)
                                  && f5
                                          > Math.abs(f7 * f17 + (f6 - f7) * f15) : (
                                                 f5 = Math.abs(f7 * f12))
                                          >= Math.abs(f6 * f20 + (f7 - f6) * f14)
                                  && f5 > Math.abs(f6 * f17 + (f7 - f6) * f13)) {
                                  magnitude[j2] = derivative_mag[j2];
                                  orientation[j2] = (int) (Math.atan2(f7, f6) * (double) 40F);
                           }
                   }


           }


           derivative_mag = null;
           af2 = null;
           af3 = null;
    }


    private float hypotenuse(float f, float f1) {
           if (f == 0.0F && f1 == 0.0F)
                   return 0.0F;
           else
                   return (float) Math.sqrt(f * f + f1 * f1);
    }


    private float gaussian(float f, float f1) {
           return (float) Math.exp((-f * f) / ((float) 2 * f1 * f1));
    }


    private void thresholding_tracker(int i, int j) {
           for (int k = 0; k < picsize; k++)
                   data[k] = 0;


           for (int l = 0; l < width; l++) {
                   for (int i1 = 0; i1 < height; i1++)
                           if (magnitude[l + width * i1] >= i)
                                  follow(l, i1, j);


           }


    }


    private boolean follow(int i, int j, int k) {
           int j1 = i + 1;
           int k1 = i - 1;
           int l1 = j + 1;
           int i2 = j - 1;
           int j2 = i + j * width;
           if (l1 >= height)
                   l1 = height - 1;
           if (i2 < 0)
                   i2 = 0;
           if (j1 >= width)
                   j1 = width - 1;
           if (k1 < 0)
                   k1 = 0;
           if (data[j2] == 0) {
                   data[j2] = magnitude[j2];
                   boolean flag = false;
                   int l = k1;
                   do {
                           if (l > j1)
                                  break;
                           int i1 = i2;
                           do {
                                  if (i1 > l1)
                                          break;
                                  int k2 = l + i1 * width;
                                  if ((i1 != j || l != i)
                                          && magnitude[k2] >= k
                                          && follow(l, i1, k)) {
                                          flag = true;
                                          break;
                                  }
                                  i1++;
                           } while (true);
                           if (!flag)
                                  break;
                           l++;
                   }
                   while (true);
                   return true;
           } else {
                   return false;
           }
    }


    private Bitmap pixels2image(int ai[]) {
    Bitmap bitmap = Bitmap.createBitmap(ai, width, height, Config.ARGB_4444);
    return bitmap;
    }


    private int[] image2pixels(Bitmap image) {
        int ai[] = new int[picsize];
        image.getPixels(ai, 0, width, 0, 0, width, height);
        /*PixelGrabber pixelgrabber =
                new PixelGrabber(image, 0, 0, width, height, ai, 0, width);
        try {
                pixelgrabber.grabPixels();
        } catch (InterruptedException interruptedexception) {
                interruptedexception.printStackTrace();
        }*/
        boolean flag = false;
        int k1 = 0;
        do {
                if (k1 >= 16)
                        break;
                int i = (ai[k1] & 0xff0000) >> 16;
                int k = (ai[k1] & 0xff00) >> 8;
                int i1 = ai[k1] & 0xff;
                if (i != k || k != i1) {
                        flag = true;
                        break;
                }
                k1++;
        } while (true);
        if (flag) {
                for (int l1 = 0; l1 < picsize; l1++) {
                        int j = (ai[l1] & 0xff0000) >> 16;
                        int l = (ai[l1] & 0xff00) >> 8;
                        int j1 = ai[l1] & 0xff;
                        ai[l1] =
                               (int) (0.29799999999999999D * (double) j
                                       + 0.58599999999999997D * (double) l
                                       + 0.113D * (double) j1);
                }


        } else {
                for (int i2 = 0; i2 < picsize; i2++)
                        ai[i2] = ai[i2] & 0xff;


        }
        
        
        return ai;
 }


    public void setThreshold(int i) {
           threshold = i;
    }


    public void setWidGaussianKernel(int i) {
           widGaussianKernel = i;
    }


public Bitmap getSourceBitmap() {
return sourceBitmap;
}


public void setSourceBitmap(Bitmap sourceBitmap) {
this.sourceBitmap = sourceBitmap;
}


public Bitmap getEdgeBitmap() {
return edgeBitmap;
}


public void setEdgeBitmap(Bitmap edgeBitmap) {
this.edgeBitmap = edgeBitmap;
}

}


package com.example.yanhuang.canny;


public class EdgeDetectorException extends Exception
{
  /**

*/
private static final long serialVersionUID = 1L;
public EdgeDetectorException()
{
//do something?
}
public EdgeDetectorException(String s)
{
super(s);
}
}


调用

EdgeDetector edgeDetector=new EdgeDetector(this);
       edgeDetector.setSourceBitmap(bmp);
       edgeDetector.setThreshold(128);
       edgeDetector.setWidGaussianKernel(5);
       try {
           edgeDetector.process();
       }
       catch(EdgeDetectorException e) {
           System.out.println(e.getMessage());
       }
       
       grayBmp = edgeDetector.getEdgeBitmap();
       imageView.setImageBitmap(grayBmp);

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值