图像边缘检测 Sobel边缘检测

底下有详细代码

一、介绍

1、图像检测的原理。

        图像检测的原理是检测相邻的几个点像素值之间的变化率,相对于对函数求导。求点P(x,y)的变换率,可以在点P周围选取一些点,求x方向的距离Gx,再求y方向上的距离Gy。最后变换率G等于Gx平方加上Gy平方的和的平方差,即G=Math.sqrt(Gx^2+Gy^2)。

2、Sobel算子。

        索贝尔算子对噪声不敏感。是计算机视觉领域的一种重要处理方法。主要用于获得数字图像的一阶梯度,常见的应用和物理意义是边缘检测。索贝尔算子是把图像中每个像素的上下左右四领域的灰度值加权差,在边缘处达到极值从而检测边缘。
        索贝尔算子主要用作边缘检测。在技术上,它是一离散性差分算子,用来运算图像亮度函数的梯度之近似值。在图像的任何一点使用此算子,将会产生对应的梯度矢量或是其法矢量。
        索贝尔算子不但产生较好的检测效果,而且对噪声具有平滑抑制作用,但是得到的边缘较粗,且可能出现伪边缘。

3、Sobel算子模版。

        Gx=f(x+1,y-1)+2f(x+1,y)+f(x+1,y+1)-(f(x-1,y-1)+2f(x-1,y)+f(x-1,y+1))
        Gy=f(x-1,y+1)+2f(x,y+1)+f(x+1,y+1)-(f(x-1,y-1)+2f(x,y-1)+f(x+1,y-1))
        Gx=[-1 0  1] , Gy=[-1 -2 -1]
               [-2 0  2]         [ 0  0  0]
               [-1 0  1]         [ 1  2  1]

二、主要代码

1、EdgeDetectionTest 类。

package com.zxj.reptile.test.image.edge;

import com.zxj.reptile.utils.image.EdgeDetectionUtils;
import com.zxj.reptile.utils.image.ImageService;
import com.zxj.reptile.utils.image.ImageUtils;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;

/**
 * 图像边缘检测
 */
public class EdgeDetectionTest {
    public static void main(String[] args) {
        sobelTest();
    }

    private static void sobelTest() {
        String sourcePath = "G:\\xiaojie-java-test\\img\\边缘检测\\Lena灰度图.jpg";
        String targetPath = "G:\\xiaojie-java-test\\img\\边缘检测\\Lena-sobel.jpg";
        sobel(sourcePath, targetPath);
        sobelBinaryTest(128);
        sobelBinaryTest(64);
        sobelBinaryTest(32);
    }

    private static void sobel(String sourcePath, String targetPath) {
        try {
            //获取原图像对象,并获取原图像的二维数组
            BufferedImage image = ImageIO.read(new File(sourcePath));
            int[][] imgArrays = ImageUtils.getBytes(image);
            //生成新图像的二维数组
            int[][] newImgArrays = EdgeDetectionUtils.sobel(imgArrays);
            //生成新图片对象,填充像素
            BufferedImage newImage = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_INT_RGB);
            ImageUtils.setIntsForGray(newImage, newImgArrays);
            //生成图片文件
            ImageIO.write(newImage, "JPEG", new File(targetPath));
            Thread.sleep(1);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static void sobelBinaryTest(int threshold) {
        String sourcePath = "G:\\xiaojie-java-test\\img\\边缘检测\\Lena-sobel.jpg";
        String targetPath = "G:\\xiaojie-java-test\\img\\边缘检测\\Lena-sobel-binary-" + threshold + ".jpg";
        ImageService.toBinaryImg(sourcePath, targetPath, threshold);
    }
}

2、EdgeDetectionUtils 类。

package com.zxj.reptile.utils.image;

/**
 * 图像边缘检测
 */
public class EdgeDetectionUtils {
    /*
     * 一阶微分算子:Roberts 、Sobel 、Prewitt
     * G = Math.sqrt(Gx^2 + Gy^2)
     * angle = arctan(Gy / Gx)
     */


    /**
     * 边缘检测--Sobel
     * Gx=f(x+1,y-1)+2f(x+1,y)+f(x+1,y+1)-(f(x-1,y-1)+2f(x-1,y)+f(x-1,y+1))
     * Gy=f(x-1,y+1)+2f(x,y+1)+f(x+1,y+1)-(f(x-1,y-1)+2f(x,y-1)+f(x+1,y-1))
     * Gx=[-1 0  1] , Gy=[-1 -2 -1]
     * ---[-2 0  2]      [ 0  0  0]
     * ---[-1 0  1]      [ 1  2  1]
     */
    public static int[][] sobel(int[][] array) {
        int row = array.length;
        int column = array[0].length;
        int[][] newArray = new int[row][column];
        //注意:x = j = column , y = i = row
        for (int i = 0; i < row; i++) {//图片第几行
            for (int j = 0; j < column; j++) {//图片第几列
                int sum, sumX, sumY;
                if (i > 0 && j > 0 && i < row - 1 && j < column - 1) {
                    //Gx=f(x+1,y-1)+f(x+1,y)+f(x+1,y+1)-(f(x-1,y-1)+f(x-1,y)+f(x-1,y+1))
                    //Gy=f(x-1,y+1)+f(x,y+1)+f(x+1,y+1)-(f(x-1,y-1)+f(x,y-1)+f(x+1,y-1))
                    sumX = array[i - 1][j + 1] + 2 * array[i][j + 1] + array[i + 1][j + 1] -
                            (array[i - 1][j - 1] + 2 * array[i][j - 1] + array[i + 1][j - 1]);
                    sumY = array[i + 1][j - 1] + 2 * array[i + 1][j] + array[i + 1][j + 1] -
                            (array[i - 1][j - 1] + 2 * array[i - 1][j] + array[i - 1][j + 1]);
                    sum = (int) Math.sqrt(sumX * sumX + sumY * sumY);
                    newArray[i][j] = sum > 0xff ? 0xff : sum;
                } else if (i < row - 1 && j < column - 1) {
                    //Gx=f(x+1,y+1)-f(x,y),
                    //Gy=f(x,y+1)-f(x+1,y)
                    sumX = array[i + 1][j + 1] - array[i][j];
                    sumY = array[i + 1][j] - array[i][j + 1];
                    sum = (int) Math.sqrt(sumX * sumX + sumY * sumY);
                    newArray[i][j] = sum > 0xff ? 0xff : sum;
                } else if (j == column - 1) {
                    //最后一列
                    newArray[i][j] = newArray[i][j - 1];
                } else if (i == row - 1) {
                    //最后一行
                    newArray[i][j] = newArray[i - 1][j];
                }
            }
        }
        return ImageUtils.rangeByte(newArray);
    }
}

三、结果

1、原图。

2、生成的结果截图。

3、图片边缘检测的图片。

4、将图片边缘检测的图片二值化,其中阈值分别为:32、64、128。                                                           

四、详细代码

详细代码可以查看文章图像边缘检测 Reberts边缘检测的详细代码,因为一样的,就不重复写出了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值