基于Opencv和Java识别图片中的黑色矩形
思路:
- 二值化,将纯黑的保留,其他颜色转为白色
- 去噪,将散乱的黑点去掉,
- 求边缘轮廓,求出最大的边缘
- 从最大边缘中求出最小的 x,最小的y,最大的x,最大的y.(不规则图形就去它的外接矩形)
1.官网下载Opencv
2.在eclipse中添加jar包
3.在jvm中添加参数,-Djava.library.path=C:\Java\opencv\build\java\x64(path后的路径是opecv中一个dll路径的目录,可以参照我的目录去寻找)
全文代码:
package com.ebupt.ringtone_video_hub.create_video.taskv2.render;
import org.bytedeco.javacv.Java2DFrameConverter;
import org.bytedeco.javacv.OpenCVFrameConverter;
import org.javatuples.Quartet;
import org.junit.Test;
import org.opencv.core.*;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferByte;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class FindBlackArea {
Quartet<Integer, Integer, Integer, Integer> quartet;
public Quartet<Integer, Integer, Integer, Integer> find(BufferedImage image){
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);//加载本地dll文件
// Mat originalMat= Imgcodecs.imread(inputPath,Imgcodecs.IMREAD_GRAYSCALE);//加载图片时灰度处理
Mat originalMat=BufImg2Mat(image,image.getType(), CvType.CV_8UC3);
Imgproc.threshold(originalMat, originalMat, 0, 255,Imgproc.THRESH_BINARY);//二值化
Mat dst = originalMat.clone();
Imgproc.medianBlur(originalMat, dst, 7);//去除噪点
List contours=find_contours(dst);
return calculate(contours);
}
public List find_contours(Mat img) {
Imgproc.threshold(img, img, 0, 255, Imgproc.THRESH_BINARY);
List<MatOfPoint> contours = new ArrayList<MatOfPoint>();
Mat firstMat = new Mat();
Imgproc.findContours(img, contours, firstMat, Imgproc.RETR_LIST, Imgproc.CHAIN_APPROX_SIMPLE);
return contours;
}
public Quartet<Integer, Integer, Integer, Integer>calculate(List<MatOfPoint> contours){
int maxSizeIndex=-1;
int maxSize=Integer.MIN_VALUE;
//找出轮廓面积最大的轮廓
for(int i=0;i<contours.size();i++){
Mat mat=(MatOfPoint)contours.get(i);
int size=mat.width()*mat.height();
if(size>maxSize){
maxSize=size;
maxSizeIndex=i;
}
}
if(maxSizeIndex!=-1){
String dump=contours.get(maxSizeIndex).dump();
return stringToArray(dump);
}
return null;
}
public Quartet<Integer, Integer, Integer, Integer> stringToArray(String dump){
int minX=Integer.MAX_VALUE;
int minY=Integer.MAX_VALUE;
int maxX=Integer.MIN_VALUE;
int maxY=Integer.MIN_VALUE;
dump=dump.substring(1, dump.length()-1);
String[] stringArray=dump.split(";");
for(String s:stringArray) {
String[] l=s.split(",");
int x=Integer.valueOf(l[0].trim());
int y=Integer.valueOf(l[1].trim());
minX=Math.min(x, minX);
maxX=Math.max(x,maxX);
minY=Math.min(y,minY);
maxY=Math.max(y, maxY);
}
System.out.println(" x1 "+minX+" y1:"+minY);
System.out.println(" x2 "+maxX+" y2:"+maxY);
int width=maxX-minX;
int height=maxY-minY;
System.out.println(" width"+width+" height:"+height);
quartet=new Quartet<>(minX,minY,width,height);
return quartet;
}
public Mat BufImg2Mat (BufferedImage original, int imgType, int matType) {
if (original == null) {
throw new IllegalArgumentException("original == null");
}
// Don't convert if it already has correct type
if (original.getType() != imgType) {
// Create a buffered image
BufferedImage image = new BufferedImage(original.getWidth(), original.getHeight(), imgType);
// Draw the image onto the new buffer
Graphics2D g = image.createGraphics();
try {
g.setComposite(AlphaComposite.Src);
g.drawImage(original, 0, 0, null);
} finally {
g.dispose();
}
}
byte[] pixels = ((DataBufferByte) original.getRaster().getDataBuffer()).getData();
Mat mat = Mat.eye(original.getHeight(), original.getWidth(), matType);
mat.put(0, 0, pixels);
Mat sc=new Mat();
Imgproc.cvtColor(mat, sc, Imgproc.COLOR_BGR2GRAY);
return sc;
}
@Test
public void test(){
String inputpathString="C:\\Users\\86130\\Desktop\\pictures\\2019-12-30-17-41.jpg";
try {
BufferedImage image= ImageIO.read(new File(inputpathString));
find(image);
} catch (IOException e) {
e.printStackTrace();
}
}
}