使⽤java+OpenCV进⾏图⽚对⽐并标记差异部分(⽀持中⽂图⽚路径)1、设计⽅法为:
1. ⾸先将两个图⽚转化为灰度图;
2. 进⾏灰度图⽐对,1为完全相同,此处可以插⼊阀值;
3. 计算两个灰度图的绝对差值并放⼊⼀个新的Mat对象;
4. 将新的mat对象进⾏绝对差值化;
5. 寻轮廓图并⽤红⾊进⾏标记;
6. 输出到新图⽚中(带有标记的图⽚);
2、难点说明:
1. 读取图⽚时,OpenCV默认不⽀持中⽂图⽚路径,故需要⽤其他⽅法来进⾏,参考⾥描述的⽅法来解决该问题,具体代码见代码块中
的⽅法readMat;
2. 由于为中⽂路径,故使⽤OpenCV⾃带的写出图⽚⽅法会导致代码运⾏⽆异常,但是⽆法输出图⽚,故更换使⽤ImageIO中的⽅法来
写出图⽚,代码见⽅法writeImage;
3、代码块如下所⽰
package st;
import java.awt.HeadlessException;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import javax.imageio.ImageIO;
import Core;
import CvType;
import Mat;
import MatOfByte;
import MatOfPoint;
import Rect;
import Scalar;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
import org.opencv.utils.Converters;
public class ImageCompare {
private boolean compareResult = false;
private String mark = "_compareResult";
/**
* ⽐较两张图⽚,如不同则将不同处标记并输出到新的图⽚中
* @param imagePath1 图⽚1的路径
* @param imagePath2 图⽚2的路径
*/
public void CompareAndMarkDiff(String imagePath1, String imagePath2)
{
Mat mat1 = readMat(imagePath1);
Mat mat2 = readMat(imagePath2);
Mat mat2 = readMat(imagePath2);
mat1 = Imgcodecs.imdecode(mat1, Imgcodecs.IMREAD_UNCHANGED);
mat2 = Imgcodecs.imdecode(mat2, Imgcodecs.IMREAD_UNCHANGED);
/*Mat mat1 = Imgcodecs.imread(imagePath1, Imgcodecs.IMREAD_UNCHANGED);
Mat mat2 = Imgcodecs.imread(imagePath2, Imgcodecs.IMREAD_UNCHANGED);*/
ls() == 0 || ls() == 0 || ws() == 0 || ws() == 0)
{
System.out.println("图⽚⽂件路径异常,获取的图⽚⼤⼩为0,⽆法读取");
return;
}
ls() != ls() || ws() != ws())
{
System.out.println("两张图⽚⼤⼩不同,⽆法⽐较");
return;
}
Mat mat1_gray = new Mat();
Imgproc.cvtColor(mat1, mat1_gray, Imgproc.COLOR_BGR2GRAY);
Mat mat2_gray = new Mat();
Imgproc.cvtColor(mat2, mat2_gray, Imgproc.COLOR_BGR2GRAY);
vertTo(mat1_gray, CvType.CV_32F);
vertTo(mat2_gray, CvType.CV_32F);
double result = ImgprocpareHist(mat1_gray, mat2_gray, Imgproc.CV_COMP_CORREL);
if(result == 1)
{
compareResult = true;//此处结果为1则为完全相同
return;
}
System.out.println("相似度数值为:"+result);
Mat mat_result = new Mat();
//计算两个灰度图的绝对差值,并输出到⼀个Mat对象中
Core.absdiff(mat1_gray, mat2_gray, mat_result);
//将灰度图按照阈值进⾏绝对值化
vertTo(mat_result, CvType.CV_8UC1);
List<MatOfPoint> mat2_list = new ArrayList<MatOfPoint>();
Mat mat2_hi = new Mat();
//寻轮廓图
Imgproc.findContours(mat_result, mat2_list, mat2_hi, Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE);        Mat mat_result1 = mat1;
Mat mat_result2 = mat2;
//使⽤红⾊标记不同点
System.out.println(mat2_list.size());
for (MatOfPoint matOfPoint : mat2_list)
{
Rect rect = Imgproc.boundingRect(matOfPoint);
}
String fileName1 = getFileName(imagePath1);
String targetPath1 = getParentDir(imagePath2)+File.place(".", mark+".");
String fileName2 = getFileName(imagePath2);
String targetPath2 = getParentDir(imagePath2)+File.place(".", mark+".");
System.out.println(targetPath1);
System.out.println(targetPath2);
//图⽚⼀的带标记的输出⽂件;
//        Imgcodecs.imwrite(targetPath1, mat_result1);
//图⽚⼆的带标记的输出⽂件;
//        Imgcodecs.imwrite(targetPath2, mat_result2);
writeImage(mat_result1, targetPath1);
writeImage(mat_result2, targetPath2);
}
private void writeImage(Mat mat, String outPutFile)
{
MatOfByte matOfByte = new MatOfByte();
MatOfByte matOfByte = new MatOfByte();
Imgcodecs.imencode(".png", mat, matOfByte);
byte[] byteArray = Array();
BufferedImage bufImage = null;
try {
InputStream in = new ByteArrayInputStream(byteArray);
bufImage = ad(in);
ImageIO.write(bufImage, "png", new File(outPutFile));
rectangle函数opencv
} catch (IOException | HeadlessException e)
{
e.printStackTrace();
}
}
private String getFileName(String filePath)
{
File f = new File(filePath);
Name();
}
private String getParentDir(String filePath)
{
File f = new File(filePath);
Parent();
}
private Mat readMat(String filePath)
{
try {
File file = new File(filePath);
FileInputStream inputStream = new FileInputStream(filePath);
byte[] byt = new byte[(int) file.length()];
int read = ad(byt);
List<Byte> bs = convert(byt);
Mat mat1 = Converters.vector_char_to_Mat(bs);
return mat1;
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return new Mat();
}
private List<Byte> convert(byte[] byt)
{
List<Byte> bs = new ArrayList<Byte>();
for (int i = 0; i < byt.length; i++)
{
bs.add(i, byt[i]);
}
return bs;
}
}
主函数:
package st.entry;
import Core;
import st.ImageCompare;
public class TestMain {
public static void main(String[] args)
{
//ISO-8859-1
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
String imagePath1 = "D:\\test\\中⽂路径\\2018-07-07_172702.PNG";
String imagePath2 = "D:\\test\\中⽂路径\\2018-07-07_172702 - 副本.PNG";
ImageCompare imageCompare = new ImageCompare();
imageCompare.CompareAndMarkDiff(imagePath1, imagePath2);
}
}
运⾏结果:
相似度数值为:0.9031714333320275
1
D:\test\中⽂路径\2018-07-07_172702_compare.PNG
D:\test\中⽂路径\2018-07-07_172702 - 副本_compare.PNG
⽐较结果图⽚正常输出

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。