边缘检测值canny算子

canny算子进行边缘检测的步骤是:

(1)使用高斯滤波器平滑图形

(2)使用一阶偏导的有限差分方程来计算梯度的赋值和方向

(3)对梯度幅值进行非极大值抑制

(4)用双阀值算法检测和连接边缘


案例:

public class ImageJAndroid3Activity extends Activity {
     ImageView sourceImage;
     ImageView destinationImage;
     int[] data;
     int[] magnitude;
     int[] orientation;
     int width;
     int height;
     int derivative_mag[];
     int threshold1;
     int threshold2;
     int threshold=128;
    
     private Handler handler=new Handler(){

        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            if(msg.what==1){
                destinationImage.setImageBitmap((Bitmap)msg.obj);
            }
        }
        
     };
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        sourceImage=(ImageView) findViewById(R.id.source);
        destinationImage=(ImageView) findViewById(R.id.destination);
    }
    
    public void remove(View v){
        new Thread(){
            public void run(){
                
                Bitmap bitmap=BitmapFactory.decodeResource(getResources(),R.drawable.gg);
                width=bitmap.getWidth();
                height=bitmap.getHeight();
                int widGaussianKernel=5;
                data=new int[width*height];
                bitmap.getPixels(data, 0, width, 0, 0, width, height);
                magnitude=new int[width*height];
                orientation=new int[width*height];
                float f = 1.0F;
                canny_core(f, widGaussianKernel); //生成高斯算子5
                threshold1=50;
                threshold2=230;
                thresholding_tracker(threshold1, threshold2);//50,230
                for (int i = 0; i < width*height; i++)
                    if (data[i] > threshold)//大于128
                            data[i] = 0xff000000; //为黑
                    else
                            data[i] = -1; //为白
                
                Bitmap newBitmap=Bitmap.createBitmap(width,height,Config.RGB_565);
                newBitmap.setPixels(data, 0, width, 0, 0, width, height);
                Message message=Message.obtain();
                message.what=1;
                message.obj=newBitmap;
                handler.sendMessage(message);
            }
        }.start();
    }
    
    private void canny_core(float f, int i) { //1.0,5.0
        boolean flag = false;
        boolean flag1 = false;
        derivative_mag = new int[width*height];
        float af4[] = new float[i]; //大小为5
        float af5[] = new float[i];
        float af6[] = new float[i];
        image2pixels(); //将data中数据变成灰度数据
        int k4 = 0;//k4最大为4
        do {
                if (k4 >= i)  //进行5次
                        break;
                float f1 = gaussian(k4, f); //e(0/2),e(-1/2),e(-4/2),e(-9/2),e(-16/2),
                if (f1 <= 0.005F && k4 >= 2)//?
                        break;
                float f2 = gaussian((float) k4 - 0.5F, f); //生成5个
                float f3 = gaussian((float) k4 + 0.5F, f);
                float f4 = gaussian(k4, f * 0.5F);//k4,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; //k4为4
        float af[] = new float[width*height]; //计算af[]
        float af1[] = new float[width*height];  //计算af1[]
        int j1 = width - (j - 1);  //width-3
        int l = width * (j - 1);  //width*3
        int i1 = width * (height - (j - 1)); //width*(height-3)
        for (int l4 = j - 1; l4 < j1; l4++) {//3,width-3
                for (int l5 = l; l5 < i1; l5 += width) { //width*3,width*(height-3)
                        int k1 = l4 + l5;
                        float f8 = (float) data[k1] * af4[0];
                        float f10 = f8;
                        int l6 = 1;
                        int k7 = k1 - width;//l4+l5-width
                        for (int i8 = k1 + width; l6 < j; i8 += width) {  //l6小于4,并且每次i8相加width
                               f8 += af4[l6] * (float) (data[k7] + data[i8]);
                               f10 += af4[l6] * (float) (data[k1 - l6] + data[k1 + l6]);
                               l6++; //只能循环3
                               k7 -= width;
                        }
                        af[k1] = f8;
                        af1[k1] = f10;
                }
        }
        float af2[] = new float[width*height];  //计算af2[]
        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[width*height];  //计算af3[]
        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; //初始化dervative[]数组,大小为面积
                        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];  //初始化magnitude[],大小我面积
                               orientation[j2] = (int) (Math.atan2(f7, f6) * (double) 40F); //初始化orientation[]大小为面积
                        }
                }
        }
        derivative_mag = null;
        af2 = null;
        af3 = null;
    }
    //将data中数据变成灰度数据
    public void image2pixels(){
        for(int y=0;y<height;y++){
            for(int x=0;x<width;x++){
                int a=data[y*width+x]>>24&0xff;
                int red=data[y*width+x]>>16&0xff;
                int green=data[y*width+x]>>8&0xff;
                int blue=data[y*width+x]&0xff;
                int grey=(int)(0.299 * red + 0.587 * green+ 0.114 * blue);
                data[y*width+x]=a<<24|grey<<16|grey<<8|grey;
            }
        }
    }
    
    //返回高斯数据  
    private float gaussian(float f, float f1) {
        return (float) Math.exp((-f * f) / ((float) 2 * f1 * f1));
   }
    //hypotenuse方法
    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 void thresholding_tracker(int i, int j) {
        for (int k = 0; k < width*height; k++)
                data[k] = 0;  //初始化
        for (int l = 0; l < width; l++) {
                for (int i1 = 0; i1 < height; i1++)
                        if (magnitude[l + width * i1] >= i) //像素值大于等于50
                               follow(l, i1, j); //x,y,230
        }
   }
    
    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;//l1(y)的最大值
        if (i2 < 0)
                i2 = 0;  //i2(y)的最小值
        if (j1 >= width)
                j1 = width - 1; //j1(x)的最大值
        if (k1 < 0)
                k1 = 0;  //k1(x)的最小值
        if (data[j2] == 0) {  //像素值为黑
                data[j2] = magnitude[j2]; //等级
                boolean flag = false;
                int l = k1;//l为x-1
                do {
                        if (l > j1)//l大于x+1
                               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;
        }
   }

    
}



实验效果:


参考博客来自:

http://blog.csdn.net/haohappy2004/article/details/476820

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值