IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 人工智能 -> java实现Canny算法 -> 正文阅读

[人工智能]java实现Canny算法

目录

Canny基本思想

算法步骤

高斯滤波

计算梯度值和方向

非极大值抑制

双阈值的选取

滞后边界跟踪


Canny基本思想

? 基本思想:寻找图像梯度的局部最大值。
? Canny 提出了边缘检测算子优劣评判的三条标准:
????????① 高检测率。边缘检测算子应该只对边缘进行响应,检测算子不漏检任何边缘,也不应该将非边缘标记为边缘。
????????② 精确定位。检测到的边缘与实际边缘之间的距离要尽可能的小。
????????③ 明确的响应。对每一条边缘只有一次响应,只得到一个点。
? 优点:在一阶微分算子的基础上,增加了非最大值抑制和双阈值。
? 非极大值抑制:不仅可以有效地抑制多响应边缘,而且还可以提高边缘的定位精度;
? 双阈值:可以有效减少边缘的漏检率。

算法步骤

灰度化:常用公式 -- Gray=0.299R+0.587G+0.114B
高斯滤波
计算梯度值和方向
非极大值抑制
双阈值的选取
滞后边界跟踪

高斯滤波

? 目的:去除噪声
? 方法: 高斯滤波器是将高斯函数离散化,将滤波器中对应的横纵坐标索引代入到高斯函数,从而得到对应的值。
? ?二维的高斯函数如下:其中 (x , y) 为坐标, σ 为标准差

? 不同尺寸的滤波器,得到的值也不同,下面是 (2k+1)x(2k+1) 滤波器的计算公式 :

? ?常见的高斯滤波器大小为 5*5 σ = 1.4 ,其近似值为:

计算梯度值和方向

? 常见方法采用 Sobel 滤波器 水平 x 和垂直 y 方向 在计算梯度和方向
? 采用下列公式计算梯度和方向:

非极大值抑制

????????目的:将模糊(blurred)的边界变得清晰(sharp)。通俗的讲,就是保留了每个像素点上梯度强度的极大值,而删掉其他的值。

?近邻 法:
????????a) 将其梯度方向近似为以下值中的一个( 0,45,90,135,180,225,270,315 )(即上下左右和 45 度方向)
????????b) 比较该像素点,和其梯度方向正负方向的像素点的梯度强度
????????c) 如果该像素点梯度强度最大则保留,否则抑制(删除,即置为 0

?????????插值法:

双阈值的选取

? 使用双阈值来对二值化图像进行筛选,通过选取合适的大阈值与小阈值可以得出最为接近图像真实边缘的边缘图像。
? 实现方法:根据高阈值和低阈值将像素点标记为强边界点、弱边界点和非边界点三类。其中强边界点即为真实边缘点。

滞后边界跟踪

? 目的:进一步处理弱边界点
? 主要思想: 和强边界点相连的弱边界点认为是边界点,其他的弱边界点则被抑制。
? 方法: ?由真实边缘引起的弱边缘像素将连接到强边缘像素,而噪声响应未连接。为了跟踪边缘连接, 通过查看弱边缘像素及其 8 个邻域像素 ,只要其中一个为强边缘像素,则该弱边缘点就可以保留为真实的边缘。

java代码如下:

main程序

package img;

import javax.imageio.ImageIO;

import java.awt.image.BufferedImage;
import java.io.File;

public class main {

    public static void main(String[] args) throws Exception {
        // 读取图片
        BufferedImage bufImage = ImageIO.read(new File("Lena.jpg"));
        // Canny边缘检测
        Canny c=new Canny();
        BufferedImage cannyImg=c.getCannyImg(bufImage,0.08,0.4,2);
        ImageIO.write(cannyImg, "JPEG", new File("cannyImg.jpg"));
        
        System.out.println("Main: Successfully!");
    }
    
}

Canny程序

package img;

import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.IOException;

public class Canny {
	
	static int edge[][];
	static int find[][];
	static double vmax=0;
	static BufferedImage cannyImg;

	public Canny() {
		// TODO Auto-generated constructor stub
	}
	public static BufferedImage getCannyImg(BufferedImage image,double a,double b,double g) throws IOException {
		// TODO Auto-generated method stub
		// 灰度化
        BufferedImage grayImg=getGray(image);
        // 高斯滤波
        grayImg=filtering_Gaussian(grayImg, g);
        // 计算梯度幅度值和梯度方向
        double grad[][][]=getGradient(grayImg);
        // double nms[][]=NMS(grad);
        // 非极大值抑制处理(插值法)
        double nms[][]=NMS_2(grad);
        // 双阈值处理
        double thresh=vmax*a;
        double_threshold(nms, b*thresh, thresh);
        // 边界跟踪处理
        boundary_tracking();
        BufferedImage cannyImg=showCannyImg();
        return cannyImg;
	}
	private static BufferedImage getGray(BufferedImage image) {
		// TODO Auto-generated method stub
		int w = image.getWidth();  
	    int h = image.getHeight();
	    
	    BufferedImage grayImg= new BufferedImage(w,h,image.getType());
	    
	    for(int x=0;x<w;x++)
	    	for(int y=0;y<h;y++) {
	    		int pixel=image.getRGB(x, y);
	    		int r=(pixel & 0xff0000) >> 16;
    			int g=(pixel & 0xff00) >> 8;
    			int b=(pixel & 0xff);
    			int gray = (int) (0.299 * r + 0.587 * g + 0.114 * b);
	    		grayImg.setRGB(x, y, new Color(gray,gray,gray).getRGB());
	    	}

		return grayImg;
	}
	private static int RGBTogray(int pixel) {
		// TODO Auto-generated method stub
		return pixel & 0xff;
	}
	private static BufferedImage filtering_Gaussian(BufferedImage image, double g) {
		// TODO Auto-generated method stub
		int w = image.getWidth();  
	    int h = image.getHeight();
	    
	    int length=5;
	    int k=length/2;
	    double sigma=Math.sqrt(g);
	    
	    double[][] gaussian=new double[length][length];
	    double sum=0;
	    for(int i=0;i<length;i++) {
	    	for(int j=0;j<length;j++) {
	    		gaussian[i][j]=Math.exp(-((i-k)*(i-k)+(j-k)*(j-k))/(2*sigma*sigma));
	    		gaussian[i][j]/=2*Math.PI*sigma*sigma;
	    		sum+=gaussian[i][j];
	    	}
	    }
	    for(int i=0;i<length;i++) {
	    	for(int j=0;j<length;j++) {
	    		gaussian[i][j]/=sum;
	    	}
	    }
	    
		BufferedImage GaussianImg= new BufferedImage(w,h,image.getType());
		
		for(int x=k;x<w-k;x++) {
			for(int y=k;y<h-k;y++) {
				int newpixel=0;
				for(int gx=0;gx<length;gx++) {
					for(int gy=0;gy<length;gy++) {
						int ix=x+gx-k;
						int iy=y+gy-k;
						if(ix<0||iy<0||ix>=w||iy>=h)
							continue;
						else {
							newpixel+=RGBTogray(image.getRGB(ix, iy))*gaussian[gx][gy];
						}
					}
				}
				newpixel=(int) Math.round(1.0*newpixel);
				GaussianImg.setRGB(x, y, new Color(newpixel,newpixel,newpixel).getRGB());
			}
		}
		return GaussianImg;
	}
	private static double[][][] getGradient(BufferedImage image){
		// TODO Auto-generated method stub
		int w = image.getWidth();  
	    int h = image.getHeight();
	    int step=1;
		double[][][] grad = new double[w][h][2];
		for(int x=step;x<w-step;x++) {
			for(int y=step;y<h-step;y++) {
				int gx=-RGBTogray(image.getRGB(x-step, y-step))
						-RGBTogray(image.getRGB(x-step, y))*2
						-RGBTogray(image.getRGB(x-step, y+step))
						+RGBTogray(image.getRGB(x+step, y-step))
						+RGBTogray(image.getRGB(x+step, y))*2
						+RGBTogray(image.getRGB(x+step, y+step));
				int gy=RGBTogray(image.getRGB(x-step, y+step))
						+RGBTogray(image.getRGB(x, y+step))*2
						+RGBTogray(image.getRGB(x+step, y+step))
						-RGBTogray(image.getRGB(x-step, y-step))
						-RGBTogray(image.getRGB(x, y-step))*2
						-RGBTogray(image.getRGB(x+step, y-step));
				grad[x][y][0]=Math.sqrt(gx*gx+gy*gy);
				if(gx==0)
					grad[x][y][1]=90;
				else
					grad[x][y][1]=Math.toDegrees(Math.atan(1.0*gy/gx));
			}
		}
		
		return grad;
	}
	private static double[][] NMS(double[][][] grad){
		// TODO Auto-generated method stub
		int w=grad.length;
		int h=grad[0].length;
		double[][] nms=new double[w][h];
		for(int x=1;x<w-1;x++) {
			for(int y=1;y<h-1;y++) {
				nms[x][y]=grad[x][y][0];
				if(grad[x][y][0]==0)
					continue;
				int a=(int) Math.round(grad[x][y][1]/45);
				if(a==-2||a==2) {
					if(grad[x][y][0]<grad[x][y-1][0]||grad[x][y][0]<grad[x][y+1][0])
						nms[x][y]=0;
				}
				else if(a==-1) {
					if(grad[x][y][0]<grad[x-1][y-1][0]||grad[x][y][0]<grad[x+1][y+1][0])
						nms[x][y]=0;
				}
				else if(a==0) {
					if(grad[x][y][0]<grad[x-1][y][0]||grad[x][y][0]<grad[x+1][y][0])
						nms[x][y]=0;
				}
				else if(a==1) {
					if(grad[x][y][0]<grad[x+1][y-1][0]||grad[x][y][0]<grad[x-1][y+1][0])
						nms[x][y]=0;
				}
				if(nms[x][y]>vmax)vmax=nms[x][y];
			}
		}
		
		return nms;
	}
	private static double[][] NMS_2(double[][][] grad) {
		// TODO Auto-generated method stub
		int w=grad.length;
		int h=grad[0].length;
		double[][] nms=new double[w][h];
		for(int x=1;x<w-1;x++) {
			for(int y=1;y<h-1;y++) {
				nms[x][y]=grad[x][y][0];
				if(grad[x][y][0]==0)
					continue;
				int x1,y1,x2,y2;
				double weight=Math.tan(Math.toRadians(grad[x][y][1]));
				if(grad[x][y][1]>45) {
					x1=0;y1=1;x2=1;y2=1;
					weight=1.0/weight;
				}else if(grad[x][y][1]>0) {
					x1=1;y1=0;x2=1;y2=1;
					weight*=1;
				}else if(grad[x][y][1]>-45) {
					x1=1;y1=0;x2=1;y2=-1;
					weight*=-1;
				}else {
					x1=0;y1=-1;x2=1;y2=-1;
					weight=-1.0/weight;
				}
				double g1=grad[x+x1][y+y1][0];
				double g2=grad[x+x2][y+y2][0];
				double g3=grad[x-x1][y-y1][0];
				double g4=grad[x-x2][y-y2][0];
				double grad_count_1=g1*weight+g2*(1-weight);
				double grad_count_2=g3*weight+g4*(1-weight);
				if(grad[x][y][0]<grad_count_1||grad[x][y][0]<grad_count_2)
					nms[x][y]=0;
				if(nms[x][y]>vmax)vmax=nms[x][y];
			}
		}		
		return nms;
	}
	private static void double_threshold(double[][] nms,double low_th,double high_th){
		// TODO Auto-generated method stub
		int w=nms.length;
		int h=nms[0].length;
		edge=new int[w][h];
		for(int x=0;x<w;x++) {
			for(int y=0;y<h;y++) {
				if(nms[x][y]>=high_th) {
					edge[x][y]=2;
				}else if(nms[x][y]>=low_th) {
					edge[x][y]=1;
				}
			}
		}
	}
	private static void dfs(int x,int y,int w,int h) {
		// TODO Auto-generated method stub
		if(x<0||x>=w||y<0||y>=h||find[x][y]==1)return ;
		find[x][y]=1;
		if(edge[x][y]>=1) {
			edge[x][y]=2;
			for(int i=-1;i<=1;i++) {
				for(int j=-1;j<=1;j++) {
					dfs(x+i,y+j,w,h);
				}
			}
		}
	}
	private static int[][] boundary_tracking(){
		// TODO Auto-generated method stub
		int w=edge.length;
		int h=edge[0].length;
		
		find=new int[w][h];

		for(int x=0;x<w;x++) {
			for(int y=0;y<h;y++) {
				if(find[x][y]==1)continue;
				if(edge[x][y]==2) {
					dfs(x,y,w,h);
				}else if(edge[x][y]==0) {
					find[x][y]=1;
				}
			}
		}
		return edge;
	}
	private static BufferedImage showCannyImg() throws IOException {
		// TODO Auto-generated method stub
		int w=edge.length;
		int h=edge[0].length;
		
		BufferedImage cannyImg= new BufferedImage(w,h,BufferedImage.TYPE_INT_RGB);
		for(int x=0;x<w;x++) {
			for(int y=0;y<h;y++) {
				if(edge[x][y]==2) {
					cannyImg.setRGB(x, y, new Color(255,255,255).getRGB());
				}else {
					cannyImg.setRGB(x, y, new Color(0,0,0).getRGB());
				}
			}
		}
		return cannyImg;
	}
}

处理结果

?

  人工智能 最新文章
2022吴恩达机器学习课程——第二课(神经网
第十五章 规则学习
FixMatch: Simplifying Semi-Supervised Le
数据挖掘Java——Kmeans算法的实现
大脑皮层的分割方法
【翻译】GPT-3是如何工作的
论文笔记:TEACHTEXT: CrossModal Generaliz
python从零学(六)
详解Python 3.x 导入(import)
【答读者问27】backtrader不支持最新版本的
上一篇文章      下一篇文章      查看所有文章
加:2022-04-27 11:19:34  更:2022-04-27 11:20:12 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 10:38:12-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码