需要下载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");
}
}