java利用opencv检测图片中圆形物件

需要下载opencv环境,并在项目中加载opencv-320.jar(根据环境确定用32或64位);
目前检测只能作为demo参考,检测完整率不高,生产使用还需完善。

package com.ruida.util;

import java.awt.Color;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferByte;
import java.awt.image.RenderedImage;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;

import javax.imageio.ImageIO;
import javax.imageio.plugins.jpeg.JPEGImageWriteParam;

import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.core.Point;
import org.opencv.core.Scalar;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;

/**
 * 
 * @see https://www.studyweb.cn/detail/java_165668.html
 * hough圆检测和hough线检测的原理近似,对于圆来说,在参数坐标系中表示为C:(x,y,r)。
 * image:源图像
 * circles:检测到的圆的输出矢量(x,y,r)
 * method:使用的检测方法,目前只有一种Imgproc.HOUGH_GRADIENT
 * dp:检测圆心的累加器图像与源图像之间的比值倒数
 * minDist:检测到的圆的圆心之间的最小距离
 * param1:method设置的检测方法对应参数,针对HOUGH_GRADIENT,表示边缘检测算子的高阈值(低阈值是高阈值的一半),默认值100
 * param2:method设置的检测方法对应参数,针对HOUGH_GRADIENT,表示累加器的阈值。值越小,检测到的无关的圆(越少?)
 * minRadius:圆半径的最小半径,默认为0
 * maxRadius:圆半径的最大半径,默认为0(若minRadius和maxRadius都默认为0,则HoughCircles函数会自动计算半径)
 * @author Administrator
 *
 */
public class CheckCicle {
	
	private static BufferedImage  bufferedIamge,bufferedImageT;
	
	/**
	 * 
	 * @param imgfile
	 */
	public static int checkCicle(String imgfile,String outfile){//报错
		    int count=0;
		   try {
			   System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
			    Mat src = Imgcodecs.imread(imgfile);
			 
			    Mat dst = src.clone();
			    Imgproc.cvtColor(src, dst, Imgproc.COLOR_BGR2GRAY);
			 
			    Mat circles = new Mat();
			 // Imgproc.HoughCircles(dst, circles, Imgproc.HOUGH_GRADIENT, 1, 100, 440, 50, 0,345);//old
			  //Imgproc.HoughCircles(dst, circles, Imgproc.HOUGH_GRADIENT, 1, 100, 440, 50,100,0);
			    //Imgproc.HoughCircles(dst, circles, Imgproc.HOUGH_GRADIENT, 1.5,10,440,100,0, 0);
			    Imgproc.HoughCircles(dst, circles, Imgproc.HOUGH_GRADIENT, 1, 100, 440, 50, 0, 345);
			  //Imgproc.HoughCircles(dst, circles, Imgproc.HOUGH_GRADIENT, 1, 300, 400, 100, 0, 0);//test2
			    // Imgproc.HoughCircles(dst, circles, Imgproc.HOUGH_GRADIENT, 1, 100, 440, 50, 0, 0);
			    count=circles.cols();
			    
			    for (int i = 0; i < circles.cols(); i++)
			    {
			      double[] vCircle = circles.get(0, i);
			 
			      Point center = new Point(vCircle[0], vCircle[1]);
			      int radius = (int) Math.round(vCircle[2]);
			 
			      // circle center
			      Imgproc.circle(src, center, 3, new Scalar(0, 255, 0), -1, 8, 0);
			      // circle outline
			      Imgproc.circle(src, center, radius, new Scalar(0, 0, 255), 3, 8, 0);
			      if(i>10){
			    	  break;
			      }
			    }
			 
			    Imgcodecs.imwrite(outfile, src);
		} catch (Exception e) {
			e.printStackTrace();
		}
		   return count;
		  }
	
	
	
  
	/**
	 * 图片二值化 的理解就是讲图片上超过某阈值的像素设为A,不超过的设为B 
	 * @param image
	 * @return
	 */
	public static BufferedImage binaryization(BufferedImage image){
	  int width=image.getWidth();
	  int height=image.getHeight();
	  int r=0;
      bufferedImageT= new BufferedImage(width,height, BufferedImage.TYPE_3BYTE_BGR );
	 
	  for(int y=0;y<height;y++){
	  for(int x=0;x<width;x++){
 
		Color color = new Color(image.getRGB(x,y));
        int gray = (color.getRed()  + color.getGreen() + color.getBlue())/3;
          //设置阈值
        if (gray <100){
            r = 255;
        }else{
        	r=0;
        }
        Color color_end = new Color(r,r,r);
        bufferedImageT.setRGB(x,y,color_end.getRGB());
	   }
	  }
	  
	 return bufferedImageT;
  }

	
	public static void grayImage(String img,String grayImg) throws IOException{
		 
		try {
			File file=new File(img);
			BufferedImage image = ImageIO.read(file);  
			int width = image.getWidth();
			int height = image.getHeight();
	
			for (int y = 0; y < height; y++) {//
			    for (int x = 0; x < width; x++) {
			        int rgb = image.getRGB(x, y);
			        int r = (rgb >> 16) & 0xFF;
			        int g = (rgb >> 8) & 0xFF;
			        int b = rgb & 0xFF;
			        int gray = (r + g + b) / 3;
			        int grayRgb = (gray << 16) + (gray << 8) + gray;
			        image.setRGB(x, y, grayRgb);
			    }
			}
			
			 File newfile = new File(grayImg);
	         ImageIO.write(image, "png", newfile);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
    /**
     * 中值过滤1
     * @param sourceImage
     * @param kernelSize
     * @return
     */
	public BufferedImage medianFilter(BufferedImage sourceImage, int kernelSize) {
		// Get image dimension
		int width = sourceImage.getWidth();
		int height = sourceImage.getHeight();
		// Create new image object
		BufferedImage destImage = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY);
		int halfKernelSize = kernelSize / 2;
		int[] filterArray = new int[kernelSize * kernelSize];
		// Loop through image pixels
		for (int x = 0; x< width; x++) {
		for (int y = 0; y< height; y++) {
		int arrayIndex = 0;
		// Loop through filter
		for (int xx = x - halfKernelSize; xx<= x + halfKernelSize; xx++) {
		for (int yy = y - halfKernelSize; yy<= y + halfKernelSize; yy++) {
		if (xx >= 0 && xx< width && yy >= 0 && yy< height) {
		filterArray[arrayIndex++] = sourceImage.getRGB(xx, yy) & 0xff;
		}
		}
		}
		// Sort filterArray
		Arrays.sort(filterArray);
		// Set median pixel value
		int medianValue = filterArray[arrayIndex / 2];
		destImage.setRGB(x, y, (medianValue<< 16) | (medianValue<< 8) | medianValue);
		}
		}
		return destImage;
		}
	
	/**
	 * 中值过滤2
	 * @param image
	 * @return
	 */
	 public static BufferedImage apply(BufferedImage image) {
		 
	        int width = image.getWidth();
	        int height = image.getHeight();
	        BufferedImage filteredImage = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY);
	 
	        // 获取图像数据
	        byte[] pixels = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();
	        byte[] filteredPixels = ((DataBufferByte) filteredImage.getRaster().getDataBuffer()).getData();
	 
	        // 应用中值滤波器
	        for (int y = 1; y < height - 1; y++) {
	            for (int x = 1; x < width - 1; x++) {
	                int[] window = new int[9];
	                int index = 0;
	                for (int j = -1; j <= 1; j++) {
	                    for (int i = -1; i <= 1; i++) {
	                        window[index++] = pixels[(y + j) * width + x + i]&0xFF;
	                    }
	                }
	                Arrays.sort(window);
	                filteredPixels[y * width + x] = (byte) window[4];
	            }
	        }
	 
	        return filteredImage;
	    }
	
	
	public static void main(String[] args)throws Exception
	  {
		
		//直接检测
		String i="d:/tmp/1.jpg";
		String o="e:/test2.jpg";
		//checkCicle(i,o);
		
		//图片灰度化
		String grayfile="d:/tmp/5gray.png";
		//grayImage(i,grayfile);
		
		//中值过滤
		File file=new File(grayfile);
		BufferedImage image = ImageIO.read(file);  
		BufferedImage newimage=apply(image);
		File newfile = new File("d:/tmp/5grayfilter.png");
        ImageIO.write(newimage, "png", newfile);
		
		
		
		/**
		//二值化 
	    bufferedIamge = ImageIO.read(new File("d:/tmp/3.png"));
	    RenderedImage rendImage =binaryization(bufferedIamge);
	    File file = new File("d:/tmp/5clone.png");
	    ImageIO.write(rendImage, "png", file);
	    **/
		
		System.out.println("over");
	  }
	   
	
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值