java使用opencv库二值化图片

应用场景:
截取监控视频图片保存到本地后用作后期监控视频角度调整参考。
使用二值化后的图片并进行透明度降低进行监控矫正。

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,0,0).getRGB());
				}else {
					cannyImg.setRGB(x, y, new Color(0,0,0).getRGB());
				}
			}
		}
		return cannyImg;
	}
}

你可能感兴趣的:(java,opencv,python,图片二值化)