Commit 4ba97838 by 陈皓

.

parent defdfe32
......@@ -53,11 +53,6 @@ public class ImgProcService {
@Value("${imgconfig.deskewpy}")
String deskewpyUrl;
/**
* 黑边像素阈值
*/
private static final Integer THRESHOLD = 30;
public List<ImgVO> detection(List<ImgVO> pathList) throws Exception {
List<ImgVO> res = new ArrayList<>(pathList.size());
for (ImgVO one : pathList) {
......@@ -71,7 +66,7 @@ public class ImgProcService {
// 检测图片的DPI
vo.setDpi(getDpi(FileUtil.file(path)));
// 检测图片清晰度
vo.setClarity(clarityDetection(image));
vo.setClarity(ImageUtil.tenengrad(image));
// 检测图片的亮度
double[] arr = brightnessDetection(image);
if (arr != null) {
......@@ -81,7 +76,7 @@ public class ImgProcService {
// 检测图片倾斜角度
vo.setAngle(getAngle(image));
// 检测图片的黑边
vo.setBlack(blackDetection(image));
vo.setBlack(ImageUtil.blackDetection(image));
one.setDetectionRes(vo);
res.add(one);
}
......@@ -103,7 +98,7 @@ public class ImgProcService {
// 检测图片倾斜角度
res.setAngle(getAngle(image));
// 检测图片的黑边
res.setBlack(blackDetection(image));
res.setBlack(ImageUtil.blackDetection(image));
return res;
}
......@@ -134,7 +129,7 @@ public class ImgProcService {
// 检测图片倾斜角度
res.setAngle(Deskew.getDeskewAngle(image));
// 检测图片的黑边
res.setBlack(blackDetection(image));
res.setBlack(ImageUtil.blackDetection(image));
image.release();
FileUtil.del(filePath);
return res;
......@@ -245,56 +240,6 @@ public class ImgProcService {
}
/**
* 黑边检测
*
* @param src 图片矩阵
* @return true表示可能存在黑边
*/
private boolean blackDetection(Mat src) {
int width = src.width();
int height = src.height();
// 定义初始边界
int top = 0;
int left = 0;
int right = width - 1;
int bottom = height - 1;
// 上方黑边判断
for (int row = 0; row < height; row++) {
if (ImageUtil.sum(src.row(row)) / width < THRESHOLD) {
top = row;
} else {
break;
}
}
// 左边黑边判断
for (int col = 0; col < width; col++) {
if (ImageUtil.sum(src.col(col)) / height < THRESHOLD) {
left = col;
} else {
break;
}
}
// 右边黑边判断
for (int col = width - 1; col > 0; col--) {
if (ImageUtil.sum(src.col(col)) / height < THRESHOLD) {
right = col;
} else {
break;
}
}
// 下方黑边判断
for (int row = height - 1; row > 0; row--) {
if (ImageUtil.sum(src.row(row)) / width < THRESHOLD) {
bottom = row;
} else {
break;
}
}
// 若是边界没有被更新,认为不存在黑边
return top != 0 || left != 0 || right != width - 1 || bottom != height - 1;
}
/**
* 图像清晰度,求出灰度图的平均灰度和标准差
* 平均值和方差越大,代表图片越清晰
*
......@@ -502,7 +447,7 @@ public class ImgProcService {
int index = 1;
for (ImgVO one : pathList) {
String ext = FileUtil.extName(one.getFileName());
if (ext.equals("heic")) {
if ("heic".equals(ext)) {
Mat mat = Imgcodecs.imread(one.getUrl());
double angle = getAngle(mat);
ImageUtil.rotateImage(one.getUrl(), savePath + index + "." + ext, angle);
......@@ -586,7 +531,7 @@ public class ImgProcService {
long start = System.currentTimeMillis();
String blackUrl = savePath + "(1)." + ext;
Mat aMat = Imgcodecs.imread(newPath);
if (blackDetection(aMat)) {
if (ImageUtil.blackDetection(aMat)) {
res.setRemoveBlack(true);
RemoveBlackUtil2.remove(newPath, blackUrl);
newPath = blackUrl;
......
......@@ -40,6 +40,11 @@ import java.util.Objects;
public class ImageUtil {
/**
* 去黑边"全黑"阈值
*/
private static final Integer BLACK_VALUE = 200;
/**
* 使用Graphics2D进行旋转图片
*
* @param image 需要旋转的图片
......@@ -272,6 +277,84 @@ public class ImageUtil {
}
/**
* Tenengrad梯度方法计算清晰度
* Tenengrad梯度方法利用Sobel算子分别计算水平和垂直方向的梯度,同一场景下梯度值越高,图像越清晰。
*
* @param image 图片矩阵
* @return 图片清晰度
*/
public static double tenengrad(Mat image) {
// 图片灰度化
Mat grayImage = image.clone();
Imgproc.cvtColor(image, grayImage, Imgproc.COLOR_BGR2GRAY);
// Sobel算子
Mat sobelImage = new Mat();
Imgproc.Sobel(grayImage, sobelImage, CvType.CV_16U, 1, 1);
Scalar mean = Core.mean(sobelImage);
double meanValue = mean.val[0];
// 释放内存
sobelImage.release();
grayImage.release();
return meanValue;
}
/**
* Laplacian方法计算清晰度
*
* @param image 图片矩阵
* @return 图片清晰度
*/
public static double laplacian(Mat image) {
// 图片灰度化
Mat grayImage = image.clone();
Imgproc.cvtColor(image, grayImage, Imgproc.COLOR_BGR2GRAY);
// Laplacian算子
Mat laplacian = new Mat();
Imgproc.Laplacian(grayImage, laplacian, CvType.CV_16U);
Scalar mean = Core.mean(laplacian);
double meanValue = mean.val[0];
// 释放内存
laplacian.release();
grayImage.release();
return meanValue;
}
/**
* 通过灰度方差获取图片清晰度
* 对焦清晰的图像相比对焦模糊的图像,它的数据之间的灰度差异应该更大,即它的方差应该较大,可以通过图像灰度数据的方差来衡量图像的清晰度,方差越大,表示清晰度越好。
*
* @param image 图片矩阵
* @return 图片清晰度
*/
public static double variance(Mat image) {
// 图片灰度化
Mat grayImage = image.clone();
Imgproc.cvtColor(image, grayImage, Imgproc.COLOR_BGR2GRAY);
// 计算灰度图像的标准差
MatOfDouble mean = new MatOfDouble();
MatOfDouble stdDev = new MatOfDouble();
Core.meanStdDev(grayImage, mean, stdDev);
double meanValue = stdDev.get(0, 0)[0];
// 释放内存
mean.release();
stdDev.release();
grayImage.release();
return meanValue;
}
/**
* 计算图片清晰度
*
* @param image 图片矩阵
......@@ -369,4 +452,56 @@ public class ImageUtil {
return unsharpMasked;
}
/**
* 黑边检测
*
* @param src 图片矩阵
* @return true表示可能存在黑边
*/
public static boolean blackDetection(Mat src) {
int width = src.width();
int height = src.height();
// 定义初始边界
int top = 0;
int left = 0;
int right = width - 1;
int bottom = height - 1;
// 上方黑边判断
for (int row = 0; row < height; row++) {
if (ImageUtil.sum(src.row(row)) / width < BLACK_VALUE) {
top = row;
} else {
break;
}
}
// 左边黑边判断
for (int col = 0; col < width; col++) {
if (ImageUtil.sum(src.col(col)) / height < BLACK_VALUE) {
left = col;
} else {
break;
}
}
// 右边黑边判断
for (int col = width - 1; col > 0; col--) {
if (ImageUtil.sum(src.col(col)) / height < BLACK_VALUE) {
right = col;
} else {
break;
}
}
// 下方黑边判断
for (int row = height - 1; row > 0; row--) {
if (ImageUtil.sum(src.row(row)) / width < BLACK_VALUE) {
bottom = row;
} else {
break;
}
}
// 若是边界没有被更新,认为不存在黑边
return top != 0 || left != 0 || right != width - 1 || bottom != height - 1;
}
}
......@@ -22,14 +22,13 @@ public class RemoveBlackUtil {
public static void main(String[] args) {
long start = System.currentTimeMillis();
String testImg = "C:/Users/11419/Desktop/Deskew/TestImages/4res.png";
String resImg = "C:/Users/11419/Desktop/Deskew/TestImages/res.png";
System.load("C:/Users/11419/Desktop/lib/opencv_java460.dll");
String testImg = "C:\\Users\\11419\\Desktop\\project\\company\\test\\9.jpg";
String resImg = "C:\\Users\\11419\\Desktop\\project\\company\\test\\res9.jpg";
System.load("C:\\Users\\11419\\Desktop\\project\\company\\imgproc\\lib\\opencv_java460.dll");
remove(testImg, resImg);
}
public static void remove(String src,String dst) {
//这个必须配置,否则会报错
Mat img = Imgcodecs.imread(src);
if(img.empty()){
return;
......@@ -37,15 +36,21 @@ public class RemoveBlackUtil {
Mat greyImg = img.clone();
//1.彩色转灰色
Imgproc.cvtColor(img, greyImg, Imgproc.COLOR_BGR2GRAY);
// ImageUtil.saveImage(greyImg, "C:\\Users\\11419\\Desktop\\project\\company\\test\\guoc\\1.jpg");
Mat gaussianBlurImg = greyImg.clone();
// 2.高斯滤波,降噪
Imgproc.GaussianBlur(greyImg, gaussianBlurImg, new Size(3,3),2,2);
// ImageUtil.saveImage(gaussianBlurImg, "C:\\Users\\11419\\Desktop\\project\\company\\test\\guoc\\2.jpg");
Mat cannyImg = gaussianBlurImg.clone();
// 3.Canny边缘检测
Imgproc.Canny(gaussianBlurImg, cannyImg, 20, 60, 3, false);
// ImageUtil.saveImage(cannyImg, "C:\\Users\\11419\\Desktop\\project\\company\\test\\guoc\\3.jpg");
// 4.膨胀,连接边缘
Mat dilateImg = cannyImg.clone();
Imgproc.dilate(cannyImg, dilateImg, new Mat(), new Point(-1, -1), 2, 1, new Scalar(1));
// ImageUtil.saveImage(dilateImg, "C:\\Users\\11419\\Desktop\\project\\company\\test\\guoc\\4.jpg");
//5.对边缘检测的结果图再进行轮廓提取
List<MatOfPoint> contours = new ArrayList<>();
List<MatOfPoint> drawContours = new ArrayList<>();
......@@ -98,6 +103,10 @@ public class RemoveBlackUtil {
}
//这里是把提取出来的轮廓通过不同颜色的线描述出来,具体效果可以自己去看
Random r = new Random();
// for (int i = 0; i < drawContours.size(); i++) {
// Imgproc.drawContours(linePic, drawContours, i, new Scalar(r.nextInt(255),r.nextInt(255), r.nextInt(255)));
// }
// ImageUtil.saveImage(linePic, "C:\\Users\\11419\\Desktop\\project\\company\\test\\guoc\\5.jpg");
//7.找出最大的矩形
int index = findLargestSquare(squares);
MatOfPoint largest_square = null;
......@@ -108,6 +117,8 @@ public class RemoveBlackUtil {
return;
}
Mat polyPic = Mat.zeros(img.size(), CvType.CV_8UC3);
// Imgproc.drawContours(polyPic, squares, index, new Scalar(0, 0,255), 2);
// ImageUtil.saveImage(polyPic, "C:\\Users\\11419\\Desktop\\project\\company\\test\\guoc\\6.jpg");
//存储矩形的四个凸点
hull = new MatOfInt();
Imgproc.convexHull(largest_square, hull, false);
......@@ -120,6 +131,7 @@ public class RemoveBlackUtil {
hullPointList.add(polyContoursList.get(hullList.get(i)));
}
Core.addWeighted(polyPic, 1, img, 1, 0, img);
// ImageUtil.saveImage(img, "C:\\Users\\11419\\Desktop\\project\\company\\test\\guoc\\7.jpg");
for(int i = 0; i < hullPointList.size(); i++){
lastHullPointList.add(hullPointList.get(i));
}
......
......@@ -18,7 +18,7 @@ public class RemoveBlackUtil2 {
/**
* 去黑边"全黑"阈值
*/
private static final Integer BLACK_VALUE = 40;
private static final Integer BLACK_VALUE = 200;
public static void remove(String src, String dst) {
Mat mat = Imgcodecs.imread(src);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment