Commit 9b3f9b97 by 陈皓

init

parent 5ecec3eb
#Redis配置
redis.url: 127.0.0.1
redis.port: 6379
redis.password:
#数据库源配置
db:
cloud:
username: root
password: Dk2019!23456
driver-class-name: com.mysql.cj.jdbc.Driver
url:
cloud: jdbc:mysql://119.45.183.210:13308/image?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai
#jwt
jwt:
header: Authorization
# 令牌前缀
token-start-with: Bearer
# 必须使用最少88位的Base64对该令牌进行编码
base64-secret: ZmQ0ZGI5NjQ0MDQwY2I4MjMxY2Y3ZmI3MjdhN2ZmMjNhODViOTg1ZGE0NTBjMGM4NDA5NzYxMjdjOWMwYWRmZTBlZjlhNGY3ZTg4Y2U3YTE1ODVkZDU5Y2Y3OGYwZWE1NzUzNWQ2YjFjZDc0NGMxZWU2MmQ3MjY1NzJmNTE0MzI=
# 令牌过期时间 此处单位/毫秒 ,默认2小时,可在此网站生成 https://www.convertworld.com/zh-hans/time/milliseconds.html
token-validity-in-seconds: 7200000
# 在线用户key
online-key: online-token-
# 验证码
code-key: code-key-
# token 续期检查时间范围(默认30分钟,单位默认毫秒),在token即将过期的一段时间内用户操作了,则给用户的token续期
detect: 1800000
# 续期时间范围,默认 1小时,这里单位毫秒
renew: 3600000
#线程池配置
task:
pool:
# 是否启用线程池
enable: true
# 核心线程池大小
core-pool-size: 5
# 最大线程数
max-pool-size: 15
# 队列容量
queue-capacity: 20
# 活跃时间
keep-alive-seconds: 30
......@@ -86,7 +86,7 @@
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
<!-- OpenCv -->
<!-- mvn install:install-file -Dfile=./src/main/resources/lib/opencv-460.jar -DgroupId=org.opencv -DartifactId=opencv -Dversion=4.6.0 -Dpackaging=jar -->
<!-- mvn install:install-file -Dfile=D:/project/image-backend/config/lib/opencv-460.jar -DgroupId=org.opencv -DartifactId=opencv -Dversion=4.6.0 -Dpackaging=jar -->
<dependency>
<groupId>org.opencv</groupId>
<artifactId>opencv</artifactId>
......
......@@ -6,14 +6,17 @@ import com.zq.common.utils.AssertUtils;
import com.zq.common.vo.ResultVo;
import com.zq.imgproc.service.ApiService;
import com.zq.imgproc.vo.OptimizationReq;
import com.zq.imgproc.vo.OptimizationVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.io.IOException;
/**
* <p>
* 图片处理API
......@@ -27,11 +30,6 @@ import org.springframework.web.bind.annotation.RestController;
@RestController
public class ApiController {
@Value("${imgconfig.opencv}")
String opencvUrl;
@Value("${imgconfig.deskew}")
String deskewUrl;
private final ApiService service;
@Autowired
public ApiController(ApiService service) {
......@@ -52,4 +50,44 @@ public class ApiController {
return service.detection(req);
}
@ApiOperation("图片优化")
@PostMapping("/imageOptimization")
public ResultVo<OptimizationVO> imageOptimization(@RequestBody OptimizationReq req) throws IOException {
AssertUtils.hasText(req.getFileContent(), "缺少文件内容");
AssertUtils.hasText(req.getFileName(), "缺少文件名");
return ResultVo.success(service.optimization(req));
}
@ApiOperation("图片纠偏")
@AnonymousPostMapping("/deskew")
public ResultVo<String> deskew(@RequestBody OptimizationReq req) throws Exception {
AssertUtils.hasText(req.getFileContent(), "缺少文件内容");
AssertUtils.hasText(req.getFileName(), "缺少文件名");
return service.deskew(req);
}
@ApiOperation("图片去黑边")
@AnonymousPostMapping("/removeBlack")
public ResultVo<String> removeBlack(@RequestBody OptimizationReq req) throws Exception {
AssertUtils.hasText(req.getFileContent(), "缺少文件内容");
AssertUtils.hasText(req.getFileName(), "缺少文件名");
return service.removeBlack(req);
}
@ApiOperation("图片灰度化")
@AnonymousPostMapping("/gray")
public ResultVo<String> gray(@RequestBody OptimizationReq req) throws Exception {
AssertUtils.hasText(req.getFileContent(), "缺少文件内容");
AssertUtils.hasText(req.getFileName(), "缺少文件名");
return service.gray(req);
}
@ApiOperation("图片边缘检测")
@AnonymousPostMapping("/canny")
public ResultVo<String> canny(@RequestBody OptimizationReq req) throws Exception {
AssertUtils.hasText(req.getFileContent(), "缺少文件内容");
AssertUtils.hasText(req.getFileName(), "缺少文件名");
return service.canny(req);
}
}
package com.zq.imgproc.service;
import cn.hutool.core.codec.Base64;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.codec.Base64Decoder;
import cn.hutool.core.codec.Base64Encoder;
import cn.hutool.core.io.FileUtil;
import com.zq.common.utils.UuidUtils;
import com.zq.common.vo.ResultVo;
import com.zq.imgproc.utils.Deskew;
import com.zq.imgproc.utils.ImageUtil;
import com.zq.imgproc.utils.RemoveBlackUtil2;
import com.zq.imgproc.vo.ApiDetectionVO;
import com.zq.imgproc.vo.OptimizationReq;
import com.zq.imgproc.vo.OptimizationVO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.opencv.core.Mat;
import org.opencv.imgcodecs.Imgcodecs;
import org.springframework.stereotype.Service;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* <p>
......@@ -54,9 +62,10 @@ public class ApiService {
BigDecimal clarity = BigDecimal.valueOf(ImageUtil.tenengrad(src));
vo.setClarity(clarity.setScale(2, RoundingMode.HALF_UP).doubleValue());
// 检测图片的亮度
vo.setBrightness(Convert.toInt(ImageUtil.brightness(src)));
BigDecimal brightness = BigDecimal.valueOf(ImageUtil.brightness(src));
vo.setBrightness(brightness.setScale(1, RoundingMode.HALF_UP).doubleValue());
// 检测图片倾斜角度
vo.setDeskewAngel(Math.abs(Deskew.getDeskewAngle(src)));
vo.setAngel(Math.abs(Deskew.getDeskewAngle(src)));
// 检测图片的黑边
vo.setBlack(ImageUtil.blackDetection2(src));
// 图片弯曲检测
......@@ -72,6 +81,59 @@ public class ApiService {
return ResultVo.success(vo);
}
// public ResultVo<?> detection(OptimizationReq req) {
// ApiDetectionVO vo = new ApiDetectionVO();
// StopWatch sw = new StopWatch();
// try {
// String ext = FileUtil.extName(req.getFileName());
// String filePath = "/data/temp/" + UuidUtils.uuidNoDash() + "." + ext;
// File image = FileUtil.file(filePath);
// FileUtil.writeBytes(Base64.decode(req.getFileContent()), image);
// Mat src = Imgcodecs.imread(filePath);
//
// vo.setFileName(req.getFileName());
// vo.setSize(transformMb(image.length()));
//
// // 检测图片的分辨率
// vo.setWidthResolution(src.width());
// vo.setHeightResolution(src.height());
// // 检测图片的DPI
// vo.setDpi(ImageUtil.getDpi(image));
// // 检测图片清晰度
// sw.start();
// BigDecimal clarity = BigDecimal.valueOf(ImageUtil.tenengrad(src));
// vo.setClarity(clarity.setScale(2, RoundingMode.HALF_UP).doubleValue());
// sw.stop();
// log.info("检测图片清晰度耗时为: {}", sw.getTotalTimeMillis());
// // 检测图片的亮度
// sw.start();
// vo.setBrightness(Convert.toInt(ImageUtil.brightness(src)));
// sw.stop();
// log.info("检测图片亮度耗时为: {}", sw.getTotalTimeMillis());
// // 检测图片倾斜角度
// sw.start();
// vo.setDeskewAngel(Math.abs(Deskew.getDeskewAngle(src)));
// sw.stop();
// log.info("检测图片偏离度耗时为: {}", sw.getTotalTimeMillis());
// // 检测图片的黑边
// sw.start();
// vo.setBlack(ImageUtil.blackDetection2(src));
// sw.stop();
// log.info("检测图片黑边耗时为: {}", sw.getTotalTimeMillis());
// // 图片弯曲检测
// sw.start();
// BendResult bendResult = BendUtil.getBendResult(filePath);
// vo.setBend(bendResult.getConfidence());
// sw.stop();
// log.info("检测图片弯曲度耗时为: {}", sw.getTotalTimeMillis());
// FileUtil.del(filePath);
// } catch (Exception e) {
// log.error("图片检测出现异常", e);
// return ResultVo.fail("图片检测出现异常!");
// }
//
// return ResultVo.success(vo);
// }
/**
* 将字节数转换为MB
......@@ -81,4 +143,235 @@ public class ApiService {
BigDecimal mb = BigDecimal.valueOf(1024 * 1024);
return sizeDecimal.divide(mb, 2, RoundingMode.DOWN).doubleValue();
}
public OptimizationVO optimization(OptimizationReq req) throws IOException {
OptimizationVO res = new OptimizationVO();
// 1. 临时保存图片
String ext = FileUtil.extName(req.getFileName());
String filename = req.getFileName();
String yyyyMMdd = new SimpleDateFormat("/yyyyMM/dd/").format(new Date());
String savePath = "/data/temp" + yyyyMMdd + UuidUtils.uuidNoDash() + "/";
String filePath = savePath + filename;
FileUtil.writeBytes(Base64Decoder.decode(req.getFileContent()), filePath);
log.info("{}图片进行优化", filePath);
// 处理heic图片
if ("heic".equals(ext)) {
BufferedImage bufferedImage = ImageIO.read(new File(filePath));
ext = "jpg";
filename = FileUtil.mainName(filename) + ".jpg";
filePath = savePath + filename;
ImageIO.write(bufferedImage, "jpg", new File(filePath));
log.info("{}图片从heic转换为jpg", filePath);
}
String newPath = filePath;
// 2. 黑边处理
long start = System.currentTimeMillis();
String blackUrl = savePath + "(1)removeBlack." + ext;
Mat aMat = Imgcodecs.imread(newPath);
if (ImageUtil.blackDetection(aMat)) {
res.setRemoveBlack(true);
RemoveBlackUtil2.remove(newPath, blackUrl);
newPath = blackUrl;
} else {
res.setRemoveBlack(false);
}
aMat.release();
log.info("黑边处理消耗的时间【{}】", System.currentTimeMillis() - start);
// 3. 执行纠偏
start = System.currentTimeMillis();
String deskerFile = savePath + "(2)deskew." + ext;
Mat bMat = Imgcodecs.imread(newPath);
double skewAngle = Deskew.getDeskewAngle(bMat);
if (Double.compare(skewAngle, 1) < 0 && Double.compare(skewAngle, -1) > 0) {
res.setDeskewAngel(0);
} else {
Mat rotateMat = Deskew.rotate(bMat, skewAngle);
Imgcodecs.imwrite(deskerFile, rotateMat);
newPath = deskerFile;
res.setDeskewAngel(skewAngle);
rotateMat.release();
}
bMat.release();
log.info("纠偏所需时间【{}】", System.currentTimeMillis() - start);
// 4。 图片亮度检测
// 计算图像的平均亮度
start = System.currentTimeMillis();
Mat cMat = Imgcodecs.imread(newPath);
double brightness = ImageUtil.brightness(cMat);
res.setOriginalBrightnessVal(brightness);
// 亮度异常执行亮度矫正
if (brightness < 130 || brightness > 230) {
res.setBrightness(true);
// 计算亮度调整值
double alpha = 180 / brightness;
// 执行亮度调整
Mat grayImage = Imgcodecs.imread(newPath);
Mat adjustedImage = new Mat();
grayImage.convertTo(adjustedImage, -1, alpha, 0);
// 保存调整后的图像
Imgcodecs. imwrite(newPath, adjustedImage);
res.setBrightnessVal(ImageUtil.brightness(newPath));
adjustedImage.release();
grayImage.release();
} else {
res.setBrightness(false);
res.setBrightnessVal(0);
}
cMat.release();
log.info("亮度检测所需时间【{}】", System.currentTimeMillis() - start);
// 5. 图片清晰度检测
start = System.currentTimeMillis();
Mat dMat = Imgcodecs.imread(newPath);
double tenengrad = ImageUtil.tenengrad(dMat);
res.setOriginalClarityVal(tenengrad);
if (tenengrad < 2.5) {
res.setClarity(true);
Mat unsharpMaskingMat = ImageUtil.unsharpMasking(dMat);
// 保存调整后的图像
Imgcodecs.imwrite(newPath, unsharpMaskingMat);
res.setClarityVal(ImageUtil.tenengrad(unsharpMaskingMat));
unsharpMaskingMat.release();
} else {
res.setClarity(false);
res.setClarityVal(0);
}
dMat.release();
log.info("图片清晰度所需时间【{}】", System.currentTimeMillis() - start);
res.setFilename(filename);
res.setFileContent(Base64Encoder.encode(FileUtil.readBytes(newPath)));
res.setCorrect(false);
return res;
}
public ResultVo<String> deskew(OptimizationReq req) throws IOException {
OptimizationVO res = new OptimizationVO();
// 临时保存图片
String ext = FileUtil.extName(req.getFileName());
String filename = req.getFileName();
String yyyyMMdd = new SimpleDateFormat("/yyyyMM/dd/").format(new Date());
String savePath = "/data/temp" + yyyyMMdd + "/" + UuidUtils.uuidNoDash() + "." + ext;
String newPath = "/data/temp" + yyyyMMdd + "/" + UuidUtils.uuidNoDash() + "." + ext;
FileUtil.writeBytes(Base64Decoder.decode(req.getFileContent()), savePath);
// 处理heic图片
if ("heic".equals(ext)) {
BufferedImage bufferedImage = ImageIO.read(new File(savePath));
filename = FileUtil.mainName(filename) + ".jpg";
savePath = savePath + filename;
ImageIO.write(bufferedImage, "jpg", new File(savePath));
log.info("{}图片从heic转换为jpg", savePath);
}
Mat mat = Imgcodecs.imread(savePath);
double skewAngle = Deskew.getDeskewAngle(mat);
if (Double.compare(skewAngle, 1) < 0 && Double.compare(skewAngle, -1) > 0) {
res.setDeskewAngel(0);
} else {
Mat rotateMat = Deskew.rotate(mat, skewAngle);
Imgcodecs.imwrite(newPath, rotateMat);
rotateMat.release();
}
mat.release();
String baseImg = Base64Encoder.encode(FileUtil.readBytes(newPath));
FileUtil.del(newPath);
FileUtil.del(savePath);
return ResultVo.success(baseImg);
}
public ResultVo<String> removeBlack(OptimizationReq req) throws IOException {
// 临时保存图片
String ext = FileUtil.extName(req.getFileName());
String filename = req.getFileName();
String yyyyMMdd = new SimpleDateFormat("/yyyyMM/dd/").format(new Date());
String savePath = "/data/temp" + yyyyMMdd + "/" + UuidUtils.uuidNoDash() + "." + ext;
String newPath = "/data/temp" + yyyyMMdd + "/" + UuidUtils.uuidNoDash() + "." + ext;
FileUtil.writeBytes(Base64Decoder.decode(req.getFileContent()), savePath);
// 处理heic图片
if ("heic".equals(ext)) {
BufferedImage bufferedImage = ImageIO.read(new File(savePath));
filename = FileUtil.mainName(filename) + ".jpg";
savePath = savePath + filename;
ImageIO.write(bufferedImage, "jpg", new File(savePath));
log.info("{}图片从heic转换为jpg", savePath);
}
Mat mat = Imgcodecs.imread(savePath);
if (ImageUtil.blackDetection(mat)) {
RemoveBlackUtil2.remove(savePath, newPath);
}
mat.release();
String baseImg = Base64Encoder.encode(FileUtil.readBytes(newPath));
FileUtil.del(newPath);
FileUtil.del(savePath);
return ResultVo.success(baseImg);
}
public ResultVo<String> gray(OptimizationReq req) throws IOException {
// 临时保存图片
String ext = FileUtil.extName(req.getFileName());
String filename = req.getFileName();
String yyyyMMdd = new SimpleDateFormat("/yyyyMM/dd/").format(new Date());
String savePath = "/data/temp" + yyyyMMdd + "/" + UuidUtils.uuidNoDash() + "." + ext;
String newPath = "/data/temp" + yyyyMMdd + "/" + UuidUtils.uuidNoDash() + "." + ext;
FileUtil.writeBytes(Base64Decoder.decode(req.getFileContent()), savePath);
// 处理heic图片
if ("heic".equals(ext)) {
BufferedImage bufferedImage = ImageIO.read(new File(savePath));
filename = FileUtil.mainName(filename) + ".jpg";
savePath = savePath + filename;
ImageIO.write(bufferedImage, "jpg", new File(savePath));
log.info("{}图片从heic转换为jpg", savePath);
}
ImageUtil.gray(savePath, newPath);
String baseImg = Base64Encoder.encode(FileUtil.readBytes(newPath));
FileUtil.del(newPath);
FileUtil.del(savePath);
return ResultVo.success(baseImg);
}
public ResultVo<String> canny(OptimizationReq req) throws IOException {
// 临时保存图片
String ext = FileUtil.extName(req.getFileName());
String filename = req.getFileName();
String yyyyMMdd = new SimpleDateFormat("/yyyyMM/dd/").format(new Date());
String savePath = "/data/temp" + yyyyMMdd + "/" + UuidUtils.uuidNoDash() + "." + ext;
String newPath = "/data/temp" + yyyyMMdd + "/" + UuidUtils.uuidNoDash() + "." + ext;
FileUtil.writeBytes(Base64Decoder.decode(req.getFileContent()), savePath);
// 处理heic图片
if ("heic".equals(ext)) {
BufferedImage bufferedImage = ImageIO.read(new File(savePath));
filename = FileUtil.mainName(filename) + ".jpg";
savePath = savePath + filename;
ImageIO.write(bufferedImage, "jpg", new File(savePath));
log.info("{}图片从heic转换为jpg", savePath);
}
ImageUtil.canny(savePath, newPath);
String baseImg = Base64Encoder.encode(FileUtil.readBytes(newPath));
FileUtil.del(newPath);
FileUtil.del(savePath);
return ResultVo.success(baseImg);
}
}
......@@ -39,7 +39,7 @@ public class BendUtil {
BendResult res = null;
try {
String result = HttpUtil.post(MAIN_URL, param, 1000 * 20);
String result = HttpUtil.post(WANPRO_URL, param, 1000 * 20);
res = parseResult(result);
} catch (Exception e) {
log.error("图片弯曲检测失败!", e);
......
......@@ -10,17 +10,19 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static org.opencv.imgproc.Imgproc.LINE_AA;
public class Deskew {
public static void main(String[] args) {
System.load("D:/project/imgproc/lib/opencv_java460.dll");
Mat image = Imgcodecs.imread("C:/Users/11419/Desktop/test/dark.png");
System.load("C:/Users/11419/Desktop/test/opencv_java460.dll");
Mat image = Imgcodecs.imread("C:/Users/11419/Desktop/test/8.jpg");
long start = System.currentTimeMillis();
int angle = getDeskewAngle(image);
System.out.println("耗时为:" + String.valueOf(System.currentTimeMillis() - start));
System.out.println("耗时为:" + (System.currentTimeMillis() - start));
System.out.println(angle);
Mat roateMat = rotate(image, angle);
Imgcodecs.imwrite("C:/Users/11419/Desktop/test/bend2res.png", roateMat);
Imgcodecs.imwrite("C:/Users/11419/Desktop/test/res.jpg", roateMat);
}
public static Integer getDeskewAngle(Mat src) {
......@@ -51,14 +53,14 @@ public class Deskew {
// 5. 霍夫变换,通过步长为1,角度为PI/180来搜索可能的直线
Imgproc.HoughLinesP(canny, lines, 1, Math.PI / 180, threshold, minLineLength, maxLineGap);
// // 测试画图
// Mat mat = src.clone();
// Scalar color = new Scalar(0, 0, 255);
// for (int i = 0; i < lines.rows(); i++) {
// double[] line = lines.get(i, 0);
// Imgproc.line(mat, new Point(line[0], line[1]), new Point(line[2], line[3]), color,3, LINE_AA);
// }
// Imgcodecs.imwrite("C:\\Users\\11419\\Desktop\\test\\bend2Test.png", mat);
// 测试画图
Mat mat = src.clone();
Scalar color = new Scalar(0, 0, 255);
for (int i = 0; i < lines.rows(); i++) {
double[] line = lines.get(i, 0);
Imgproc.line(mat, new Point(line[0], line[1]), new Point(line[2], line[3]), color,3, LINE_AA);
}
Imgcodecs.imwrite("C:\\Users\\11419\\Desktop\\test\\test1.png", mat);
// 计算倾斜角度
List<Integer> angelList = new ArrayList<>();
......@@ -150,6 +152,4 @@ public class Deskew {
return rotatedImage;
}
}
package com.zq.imgproc.utils;
import cn.hutool.core.convert.Convert;
import org.opencv.core.*;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static org.opencv.imgproc.Imgproc.LINE_AA;
/**
* <p>
*
* </p>
*
* @author chenhao
* @since 2024/2/20
*/
public class Deskew2 {
public static void main(String[] args) {
System.load("C:/Users/11419/Desktop/test/opencv_java460.dll");
Mat image = Imgcodecs.imread("C:/Users/11419/Desktop/test/8.jpg");
long start = System.currentTimeMillis();
int angle = getDeskewAngle(image);
System.out.println("耗时为:" + (System.currentTimeMillis() - start));
System.out.println(angle);
Mat roateMat = rotate(image, angle);
Imgcodecs.imwrite("C:/Users/11419/Desktop/test/res.jpg", roateMat);
}
public static Integer getDeskewAngle(Mat src) {
// 图片灰度化
Mat gray = src.clone();
Imgproc.cvtColor(src, gray, Imgproc.COLOR_BGR2GRAY);
// 2.高斯滤波,降噪
Mat gaussianBlur = gray.clone();
Imgproc.GaussianBlur(gray, gaussianBlur, new Size(3,3),0);
Mat kernel = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(5, 5));
// 3. 图片腐蚀
Mat erode = gaussianBlur.clone();
Imgproc.erode(gaussianBlur, erode, kernel);
// 4. 图片膨胀
Mat dilate = erode.clone();
Imgproc.dilate(erode, dilate, kernel);
// 5. 边缘检测
Mat canny = dilate.clone();
Imgproc.Canny(dilate, canny, 50, 150);
// 6. 霍夫变换得到线条
// 霍夫变换得到线条
Mat lines = new Mat();
//累加器阈值参数,小于设置值不返回
int threshold = 30;
//最低线段长度,低于设置值则不返回
double minLineLength = 100;
//间距小于该值的线当成同一条线
double maxLineGap = 10;
// 霍夫变换,通过步长为0.8,角度为PI/180来搜索可能的直线
Imgproc.HoughLinesP(canny, lines, 0.8, Math.PI / 180, threshold, minLineLength, maxLineGap);
// 测试画图
Mat mat = src.clone();
Scalar color = new Scalar(0, 0, 255);
for (int i = 0; i < lines.rows(); i++) {
double[] line = lines.get(i, 0);
Imgproc.line(mat, new Point(line[0], line[1]), new Point(line[2], line[3]), color,3, LINE_AA);
}
Imgcodecs.imwrite("C:\\Users\\11419\\Desktop\\test\\test1.png", mat);
// 计算倾斜角度
List<Integer> angelList = new ArrayList<>();
for (int i = 0; i < lines.rows(); i++) {
double[] line = lines.get(i, 0);
int k = calculateAngle(line[0], line[1], line[2], line[3]);
angelList.add(k);
}
if (angelList.isEmpty()) {
return 0;
}
gray.release();
dilate.release();
canny.release();
lines.release();
// 可能还得需要考虑方差来决定选择平均数还是众数
return most(angelList);
}
/**
* 求数组众数
*
* @param angelList 数组
* @return 数组众数
*/
private static int most(List<Integer> angelList) {
if (angelList.isEmpty()) {
return 0;
}
int res = 0;
int max = Integer.MIN_VALUE;
Map<Integer, Integer> map = new HashMap<>();
for (int i : angelList) {
map.put(i, map.getOrDefault(i, 0) + 1);
}
for (Integer i : map.keySet()) {
int count = map.get(i);
if (count > max) {
max = count;
res = i;
}
}
return res;
}
/**
* 计算直线的倾斜角
*/
private static int calculateAngle(double x1, double y1, double x2, double y2) {
double dx = x2 - x1;
double dy = y2 - y1;
if (Math.abs(dx) < 1e-4) {
return 90;
} else if (Math.abs(dy) < 1e-4) {
return 0;
} else {
double radians = Math.atan2(dy, dx);
double degrees = Math.toDegrees(radians);
return Convert.toInt(Math.round(degrees));
}
}
/**
* 图片旋转
*
* @param image 输入图片
* @param angle 旋转角度
* @return 输出图片
*/
public static Mat rotate(Mat image, double angle) {
int w = image.cols();
int h = image.rows();
if (angle < 0) {
angle = 360 + angle;
}
Point center = new Point((double) w / 2, (double) h / 2);
double scale = 1.0;
Mat rotationMatrix = Imgproc.getRotationMatrix2D(center, angle, scale);
// 设置填充颜色为白色
Scalar backgroundColor = new Scalar(255, 255, 255);
Mat rotatedImage = new Mat();
Imgproc.warpAffine(image, rotatedImage, rotationMatrix, new Size(w, h), Imgproc.INTER_LINEAR, Core.BORDER_CONSTANT, backgroundColor);
rotationMatrix.release();
return rotatedImage;
}
}
......@@ -35,17 +35,17 @@ public class ApiDetectionVO {
@ApiModelProperty("DPI")
private Integer dpi;
@ApiModelProperty("图片清晰度")
private Double clarity;
@ApiModelProperty("图片亮度值")
private Double brightness;
@ApiModelProperty("图片弯曲置信度")
private Double bend;
@ApiModelProperty("图片亮度值")
private Integer brightness;
@ApiModelProperty("图片清晰度")
private Double clarity;
@ApiModelProperty("图片偏离角度")
private Integer deskewAngel;
private Integer angel;
@ApiModelProperty("图片黑边数量")
private Integer black;
......
......@@ -82,17 +82,20 @@ mybatis-plus:
ip:
local-parsing: true
# 内网
#imgconfig:
# opencv: /opt/services/tianjin-backend/lib/opencv_java460.so
# deskew: /opt/services/tianjin-backend/lib/Deskew/Bin/deskew
# deskewpy: /opt/services/tianjin-backend/lib/correct.py
imgconfig:
opencv: /opt/tianjin/lib/opencv_java460.so
deskew: /opt/tianjin/lib/Deskew/Bin/deskew
deskewpy: /opt/tianjin/lib/correct.py
# 172.28.1.171
#imgconfig:
# opencv: D:/project/image-backend/config/lib/opencv_java460.dll
# deskew: C:/Users/11419/Desktop/Deskew/Bin/deskew.exe
# deskewpy: D:/project/imgproc/lib/correct.py
# opencv: /opt/tianjin/lib/opencv_java460.so
# deskew: /opt/tianjin/lib/Deskew/Bin/deskew
# deskewpy: /opt/tianjin/lib/correct.py
# 本地
imgconfig:
opencv: D:/project/image-backend/config/lib/opencv_java460.dll
deskew: C:/Users/11419/Desktop/Deskew/Bin/deskew.exe
deskewpy: D:/project/imgproc/lib/correct.py
\ No newline at end of file
......@@ -20,54 +20,35 @@ public interface IApiLogic extends IApiCommon {
/**
* 图片质量检测
*/
ApiResp detection(ApiForm form);
//
// /**
// * 图片纠偏
// *
// * @param form
// * @return
// */
// ApiResp deskew(ApiForm form);
//
// /**
// * 去黑边
// *
// * @param form
// * @return
// */
// ApiResp removeBlack(ApiForm form);
//
// /**
// * 图片灰度化
// *
// * @param form
// * @return
// */
// ApiResp gray(ApiForm form);
//
// /**
// * 图片边缘检测
// *
// * @param form
// * @return
// */
// ApiResp canny(ApiForm form);
//
// /**
// * 图片弯曲矫正
// *
// * @param form
// * @return
// */
// ApiResp correct(ApiForm form);
//
// /**
// * 图片优化
// *
// * @param form
// * @return
// */
// ApiResp imageOptimization(ApiForm form);
ApiResp pictureQualityDetection(ApiForm form);
/**
* 图片优化
*/
ApiResp imageOptimization(ApiForm form);
/**
* 图片质量检测
*/
ApiResp deskew(ApiForm form);
/**
* 图片去黑边
*/
ApiResp removeBlack(ApiForm form);
/**
* 图片灰度化
*/
ApiResp gray(ApiForm form);
/**
* 图片边缘检测
*/
ApiResp canny(ApiForm form);
}
......@@ -41,66 +41,57 @@ public class ApiV1Logic extends BaseApiLogic implements IApiLogic {
@Override
@OpenApi("检测图片信息")
public ApiResp detection(ApiForm form) {
public ApiResp pictureQualityDetection(ApiForm form) {
ImageReq req = form.toBean(ImageReq.class);
AssertUtils.hasText(req.getFileContent(), "缺少文件内容");
AssertUtils.hasText(req.getFileName(), "缺少文件名");
return ApiUtils.toApiResp(form, imgProcService.detection(req));
return ApiUtils.toApiResp(form, imgProcService.pictureQualityDetection(req));
}
@Override
@OpenApi("图片优化")
public ApiResp imageOptimization(ApiForm form) {
ImageReq req = form.toBean(ImageReq.class);
AssertUtils.hasText(req.getFileContent(), "缺少文件内容");
AssertUtils.hasText(req.getFileName(), "缺少文件名");
return ApiUtils.toApiResp(form, imgProcService.imageOptimization(req));
}
@Override
@OpenApi("图片纠偏")
public ApiResp deskew(ApiForm form) {
ImageReq req = form.toBean(ImageReq.class);
AssertUtils.hasText(req.getFileContent(), "缺少文件内容");
AssertUtils.hasText(req.getFileName(), "缺少文件名");
return ApiUtils.toApiResp(form, imgProcService.deskew(req));
}
@Override
@OpenApi("图片去黑边")
public ApiResp removeBlack(ApiForm form) {
ImageReq req = form.toBean(ImageReq.class);
AssertUtils.hasText(req.getFileContent(), "缺少文件内容");
AssertUtils.hasText(req.getFileName(), "缺少文件名");
return ApiUtils.toApiResp(form, imgProcService.removeBlack(req));
}
@Override
@OpenApi("图片灰度化")
public ApiResp gray(ApiForm form) {
ImageReq req = form.toBean(ImageReq.class);
AssertUtils.hasText(req.getFileContent(), "缺少文件内容");
AssertUtils.hasText(req.getFileName(), "缺少文件名");
return ApiUtils.toApiResp(form, imgProcService.gray(req));
}
@Override
@OpenApi("图片边缘检测")
public ApiResp canny(ApiForm form) {
ImageReq req = form.toBean(ImageReq.class);
AssertUtils.hasText(req.getFileContent(), "缺少文件内容");
AssertUtils.hasText(req.getFileName(), "缺少文件名");
return ApiUtils.toApiResp(form, imgProcService.canny(req));
}
//
// @ApiMethod(name = "图片纠偏", filterRequestField = "fileContent")
// @Override
// public ApiResp deskew(ApiForm form) {
// DetectionVo vo = form.toBean(DetectionVo.class);
// AssertUtils.hasText(vo.getFileContent(), "缺少文件内容");
// AssertUtils.hasText(vo.getFilename(), "缺少文件名");
// return ApiUtils.toApiResp(form, imgProcService.apiService(vo, "imageCorrection"));
// }
//
// @ApiMethod(name = "去黑边", filterRequestField = "fileContent")
// @Override
// public ApiResp removeBlack(ApiForm form) {
// DetectionVo vo = form.toBean(DetectionVo.class);
// AssertUtils.hasText(vo.getFileContent(), "缺少文件内容");
// AssertUtils.hasText(vo.getFilename(), "缺少文件名");
// return ApiUtils.toApiResp(form, imgProcService.apiService(vo, "removeBlack"));
// }
//
// @ApiMethod(name = "图片灰度化", filterRequestField = "fileContent")
// @Override
// public ApiResp gray(ApiForm form) {
// DetectionVo vo = form.toBean(DetectionVo.class);
// AssertUtils.hasText(vo.getFileContent(), "缺少文件内容");
// AssertUtils.hasText(vo.getFilename(), "缺少文件名");
// return ApiUtils.toApiResp(form, imgProcService.apiService(vo, "gray"));
// }
//
// @ApiMethod(name = "图片边缘检测", filterRequestField = "fileContent")
// @Override
// public ApiResp canny(ApiForm form) {
// DetectionVo vo = form.toBean(DetectionVo.class);
// AssertUtils.hasText(vo.getFileContent(), "缺少文件内容");
// AssertUtils.hasText(vo.getFilename(), "缺少文件名");
// return ApiUtils.toApiResp(form, imgProcService.apiService(vo, "gray"));
// }
//
// @ApiMethod(name = "图片弯曲矫正", filterRequestField = "fileContent")
// @Override
// public ApiResp correct(ApiForm form) {
// DetectionVo vo = form.toBean(DetectionVo.class);
// AssertUtils.hasText(vo.getFileContent(), "缺少文件内容");
// AssertUtils.hasText(vo.getFilename(), "缺少文件名");
// return ApiUtils.toApiResp(form, imgProcService.apiService(vo, "correct"));
// }
//
// @ApiMethod(name = "图片优化", filterRequestField = "fileContent")
// @Override
// public ApiResp imageOptimization(ApiForm form) {
// DetectionVo vo = form.toBean(DetectionVo.class);
// AssertUtils.hasText(vo.getFileContent(), "缺少文件内容");
// AssertUtils.hasText(vo.getFilename(), "缺少文件名");
// return ApiUtils.toApiResp(form, imgProcService.imageOptimization(vo, "imageOptimization"));
// }
}
package com.zq.im.modules.im.controller;
import cn.hutool.core.codec.Base64;
import cn.hutool.core.io.FileUtil;
import com.zq.im.modules.im.req.ImageReq;
import com.zq.im.modules.im.service.ImgProcService;
import com.zq.im.modules.system.vo.ResultVo;
......@@ -7,10 +9,9 @@ import com.zq.im.utils.AssertUtils;
import io.swagger.annotations.Api;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import java.io.File;
/**
* <p>
......@@ -29,12 +30,29 @@ public class ImgProcController {
private final ImgProcService service;
@PostMapping(value = "/detection")
public ResultVo<?> detection(@RequestBody ImageReq req) {
@PostMapping(value = "/pictureQualityDetection")
public ResultVo<?> pictureQualityDetection(@RequestBody ImageReq req) {
AssertUtils.hasText(req.getFileContent(), "缺少文件内容");
AssertUtils.hasText(req.getFileName(), "缺少文件名");
return ResultVo.success(service.detection(req));
return ResultVo.success(service.pictureQualityDetection(req));
}
@PostMapping(value = "/demo/{filename}")
public ResultVo<?> demo(@PathVariable String filename) {
File file = FileUtil.file("/data/img/" + filename);
if (!file.exists()) {
return ResultVo.fail("文件不存在!");
}
if (!FileUtil.extName(file).equals("jpg") && !FileUtil.extName(file).equals("png")) {
return ResultVo.fail("暂不支持文件类型!");
}
ImageReq req = ImageReq.builder()
.fileName(filename)
.fileContent(Base64.encode(file))
.build();
return ResultVo.success(service.pictureQualityDetection(req));
}
}
......@@ -2,6 +2,7 @@ package com.zq.im.modules.im.feign;
import com.zq.im.modules.im.req.ImageReq;
import com.zq.im.modules.im.vo.DetectionResVo;
import com.zq.im.modules.im.vo.OptimizationVO;
import com.zq.im.modules.system.vo.ResultVo;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
......@@ -20,4 +21,33 @@ public interface ImgprocFeign {
@PostMapping(value = "/detection")
ResultVo<DetectionResVo> detection(ImageReq req);
/**
* 图片优化
*/
@PostMapping(value = "/imageOptimization")
ResultVo<OptimizationVO> imageOptimization(ImageReq req);
/**
* 图片纠偏
*/
@PostMapping(value = "/deskew")
ResultVo<String> deskew(ImageReq req);
/**
* 图片去黑边
*/
@PostMapping(value = "/removeBlack")
ResultVo<String> removeBlack(ImageReq req);
/**
* 图片灰度化
*/
@PostMapping(value = "/gray")
ResultVo<String> gray(ImageReq req);
/**
* 图片边缘检测
*/
@PostMapping(value = "/canny")
ResultVo<String> canny(ImageReq req);
}
......@@ -3,6 +3,7 @@ package com.zq.im.modules.im.service;
import com.zq.im.modules.im.feign.ImgprocFeign;
import com.zq.im.modules.im.req.ImageReq;
import com.zq.im.modules.im.vo.DetectionResVo;
import com.zq.im.modules.im.vo.OptimizationVO;
import com.zq.im.modules.system.vo.ResultVo;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
......@@ -25,7 +26,7 @@ public class ImgProcService {
@Autowired
ImgprocFeign feign;
public ResultVo<?> detection(ImageReq req) {
public ResultVo<?> pictureQualityDetection(ImageReq req) {
ResultVo<DetectionResVo> resultVo = feign.detection(req);
if (!resultVo.isSuccess()) {
return ResultVo.fail(resultVo.getErrMsg());
......@@ -33,4 +34,43 @@ public class ImgProcService {
return resultVo;
}
public ResultVo<?> imageOptimization(ImageReq req) {
ResultVo<OptimizationVO> resultVo = feign.imageOptimization(req);
if (!resultVo.isSuccess()) {
return ResultVo.fail(resultVo.getErrMsg());
}
return resultVo;
}
public ResultVo<?> deskew(ImageReq req) {
ResultVo<String> resultVo = feign.deskew(req);
if (!resultVo.isSuccess()) {
return ResultVo.fail(resultVo.getErrMsg());
}
return resultVo;
}
public Object removeBlack(ImageReq req) {
ResultVo<String> resultVo = feign.removeBlack(req);
if (!resultVo.isSuccess()) {
return ResultVo.fail(resultVo.getErrMsg());
}
return resultVo;
}
public Object gray(ImageReq req) {
ResultVo<String> resultVo = feign.gray(req);
if (!resultVo.isSuccess()) {
return ResultVo.fail(resultVo.getErrMsg());
}
return resultVo;
}
public Object canny(ImageReq req) {
ResultVo<String> resultVo = feign.canny(req);
if (!resultVo.isSuccess()) {
return ResultVo.fail(resultVo.getErrMsg());
}
return resultVo;
}
}
......@@ -36,17 +36,17 @@ public class DetectionResVo {
@ApiModelProperty("DPI")
private Integer dpi;
@ApiModelProperty("图片清晰度")
private Double clarity;
@ApiModelProperty("图片亮度值")
private Double brightness;
@ApiModelProperty("图片弯曲置信度")
private Double bend;
@ApiModelProperty("图片亮度值")
private Integer brightness;
@ApiModelProperty("图片清晰度")
private Double clarity;
@ApiModelProperty("图片偏离角度")
private Integer deskewAngel;
private Integer angel;
@ApiModelProperty("图片黑边数量")
private Integer black;
......
package com.zq.im.modules.im.vo;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* <p>
* 图片优化结果类
* </p>
*
* @author chenhao
* @since 2023/4/20
*/
@NoArgsConstructor
@AllArgsConstructor
@Data
@Builder
public class OptimizationVO {
@ApiModelProperty("base64图片")
private String fileContent;
@ApiModelProperty("文件名称")
private String filename;
@ApiModelProperty("是否经过亮度调整")
private boolean isBrightness;
@ApiModelProperty("图片原始平均亮度值")
private double originalBrightnessVal;
@ApiModelProperty("图片修正后的平均亮度值")
private double brightnessVal;
@ApiModelProperty("是否经过清晰度调整")
private boolean isClarity;
@ApiModelProperty("图片原始清晰度值")
private double originalClarityVal;
@ApiModelProperty("图片清晰度调整过后的清晰度值")
private double clarityVal;
@ApiModelProperty("是否经过黑边处理")
private boolean isRemoveBlack;
@ApiModelProperty("图片纠偏的角度,纠偏出错返回-1")
private double deskewAngel;
@ApiModelProperty("图片是否经过弯曲矫正")
private boolean isCorrect;
}
......@@ -5,7 +5,6 @@ import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.net.url.UrlQuery;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.URLUtil;
......@@ -14,11 +13,10 @@ import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.zq.im.modules.im.vo.DetectionResVo;
import lombok.Data;
import io.swagger.annotations.ApiModelProperty;
import lombok.*;
import java.io.File;
import java.io.InputStream;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
......@@ -41,6 +39,7 @@ public class V1Demo {
private static final String APP_ID = "ec3f54b398e64fbeb9ed00bb0144a91b";
private static final String APP_SECRET = "4c0d6c2a99e541c8a1affc3c8d8dcddb";
private static final String URL = "http://127.0.0.1:9900/api/v1/action";
// private static final String URL = "http://172.28.1.171:8855/api/v1/action";
public static ApiInfo getApiInfo() {
ApiInfo apiInfo = API_INFO_MAP.get(APP_ID);
......@@ -66,12 +65,12 @@ public class V1Demo {
HttpRequest request = HttpRequest.post(URL)
.contentType("application/x-www-form-urlencoded")
.form(params);
System.out.println("请求报文 => " + UrlQuery.of(params));
// System.out.println("请求报文 => " + UrlQuery.of(params));
HttpResponse execute = request.execute();
String body = execute.body();
System.out.println("响应报文 => " + body);
int status = execute.getStatus();
@Cleanup HttpResponse response = request.execute();
String body = response.body();
// System.out.println("响应报文 => " + body);
int status = response.getStatus();
if (status == 200) {
JSONObject obj = JSONUtil.parseObj(body);
Integer code = obj.getInt("code");
......@@ -108,14 +107,14 @@ public class V1Demo {
// POST的Content-Type默认是application/x-www-form-urlencoded,有文件则是multipart/form-data
HttpRequest request = HttpRequest.post(URL)
.form(params);
System.out.println("请求报文 => " + UrlQuery.of(params));
// System.out.println("请求报文 => " + UrlQuery.of(params));
HttpResponse execute = request.execute();
String body = execute.body();
System.out.println("响应报文 => " + body);
HttpResponse response = request.execute();
String body = response.body();
// System.out.println("响应报文 => " + body);
// 失败 => {"apiNo":"09c1ad82ec0f4b2d80cae0cfb1d7059b","code":"103","msg":"调用方法异常","timestamp":1638176339560,"data":null,"success":false}
// 成功 => {"apiNo":"bc070a7c31ac4b8eb1180b2d82a2096b","code":"200","msg":"成功","timestamp":1638176552353,"data":{"userId":"123","username":"admin@gxfy.com"},"success":true}
int status = execute.getStatus();
int status = response.getStatus();
if (status == 200) {
JSONObject obj = JSONUtil.parseObj(body);
Integer code = obj.getInt("code");
......@@ -127,51 +126,7 @@ public class V1Demo {
}
/**
* 下载文件
*
* @param method
* @param bizContentMap
* @param sessionKey
* @return
*/
public static InputStream download(String method, Map<String, Object> bizContentMap, String sessionKey) {
String apiNo = IdUtil.simpleUUID();
String timestamp = DateUtil.format(DateUtil.date(), DatePattern.PURE_DATETIME_PATTERN);
//JSON字符串
String bizContent = bizContentMap == null ? "" : JSONUtil.toJsonStr(bizContentMap);
Map<String, Object> params = new HashMap<>(6);
params.put("appId", APP_ID);
params.put("apiNo", apiNo);
params.put("method", method);
params.put("timestamp", timestamp);
params.put("bizContent", URLUtil.encode(Base64.encode(bizContent)));
params.put("sign", getSign(bizContent, method, timestamp, apiNo, sessionKey, null, null));
// POST的Content-Type默认是application/x-www-form-urlencoded,有文件则是multipart/form-data
HttpRequest request = HttpRequest.post(URL)
.form(params);
System.out.println("请求报文 => " + UrlQuery.of(params));
HttpResponse execute = request.execute();
if (!execute.isOk()) {
String body = execute.body();
System.out.println("响应报文 => " + body);
return null;
}
return execute.bodyStream();
}
/**
* 获取签名
*
* @param bizContent
* @param method
* @param timestamp
* @param apiNo
* @param sessionKey
* @return
*/
public static String getSign(String bizContent, String method, String timestamp, String apiNo, String sessionKey, File file, File[] fileList) {
// 参与签名的参数排序
......@@ -209,12 +164,14 @@ public class V1Demo {
System.out.println(sessionKey);
// String sessionKey = "860a013f4e7344bca5869b361a186648";
Map<String, Object> params = new HashMap<>(2);
params.put("filename", "6.png");
params.put("fileContent", Base64.encode(FileUtil.file("C:\\Users\\11419\\Desktop\\test\\bend1.jpg")));
Object o = doPost("detection", params, sessionKey);
params.put("filename", "8.jpg");
params.put("fileContent", Base64.encode(FileUtil.file("C:\\Users\\11419\\Desktop\\图片检测\\test\\8.jpg")));
for (int i = 0; i < 500; i++) {
Object o = doPost("pictureQualityDetection", params, sessionKey);
DetectionResVo convert = Convert.convert(DetectionResVo.class, o);
System.out.println(JSONUtil.toJsonStr(convert));
}
}
@Data
public static class ApiInfo {
......@@ -230,6 +187,44 @@ public class V1Demo {
private String unit;
private Date dueTime;
}
@NoArgsConstructor
@AllArgsConstructor
@Data
@Builder
public static class DetectionResVo {
@ApiModelProperty("文件名称")
private String fileName;
@ApiModelProperty("图片大小")
private Double size;
@ApiModelProperty("水平分辨率")
private Integer widthResolution;
@ApiModelProperty("垂直分辨率")
private Integer heightResolution;
@ApiModelProperty("DPI")
private Integer dpi;
@ApiModelProperty("图片亮度值")
private Double brightness;
@ApiModelProperty("图片弯曲置信度")
private Double bend;
@ApiModelProperty("图片清晰度")
private Double clarity;
@ApiModelProperty("图片偏离角度")
private Integer angel;
@ApiModelProperty("图片黑边数量")
private Integer black;
}
......
......@@ -101,6 +101,15 @@
</activation>
</profile>
<profile>
<!--172.28.1.171外网环境-->
<id>wanpro</id>
<properties>
<profiles.active>wanpro</profiles.active>
<logging.level>info</logging.level>
<register.url>http://admin:GXfy2022@172.28.1.171:8800/eureka/</register.url>
</properties>
</profile>
<profile>
<!--生产环境-->
<id>product</id>
<properties>
......
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