Commit fec235bb by 陈皓

init

parent 003b7634
......@@ -13,6 +13,7 @@
<properties>
<http.client.version>4.5.12</http.client.version>
<lombok.version>1.18.24</lombok.version>
</properties>
<dependencies>
......@@ -90,6 +91,12 @@
<version>${hutool.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</dependency>
<!-- jwt -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
......
......@@ -12,6 +12,7 @@ import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
/**
* <p>
......@@ -24,6 +25,7 @@ import springfox.documentation.spring.web.plugins.Docket;
*/
@Configuration
@EnableWebMvc
@EnableSwagger2
public class SwaggerConfig implements WebMvcConfigurer {
@Value("${spring.cloud.config.profile:product}")
......@@ -48,7 +50,7 @@ public class SwaggerConfig implements WebMvcConfigurer {
// 生产环境关闭
.enable(!"product".equals(profile))
.select()
.apis(RequestHandlerSelectors.basePackage("com.zq.archive.controller"))
.apis(RequestHandlerSelectors.basePackage("com.zq.imgproc.controller"))
.paths(PathSelectors.any())
.build()
.apiInfo(apiInfo());
......
......@@ -11,35 +11,36 @@ import lombok.Getter;
* @since 2023/11/26
*/
@Getter
public enum Threshold {
public class Threshold {
/**
* 亮度过低阈值
* 清晰度默认指标
*/
START_VALUE("img-start", 75),
public static final double CLARITY = 2.5;
/**
* 亮度过低阈值
* 亮度过低指标
*/
END_VALUE("img-end", 175),
public static final int BRIGHTNESS_START = 140;
/**
* 清晰度阈值
* 亮度过高指标
*/
CLARITY("img-clarity", 2.5),
public static final int BRIGHTNESS_END = 230;
/**
* 弯曲度阈值
* 弯曲度指标
*/
BEND("img-clarity", 2.5);
public static final double BEND = 0.75;
private final String key;
private final double value;
Threshold(String key, double value) {
this.key = key;
this.value = value;
}
/**
* 偏离度指标
*/
public static final int DESKEW = 1;
/**
* 黑边数量指标
*/
public static final int BLACK = 100;
}
package com.zq.imgproc.controller;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zq.common.utils.AssertUtils;
import com.zq.common.vo.PageVo;
import com.zq.common.vo.ResultVo;
import com.zq.imgproc.dao.ImageBatchDao;
import com.zq.imgproc.dao.ImageDetectionDao;
import com.zq.imgproc.entity.ImageBatch;
import com.zq.imgproc.entity.ImageDetection;
import com.zq.imgproc.vo.BatchPageReq;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.stream.Collectors;
/**
* <p>
*
* </p>
*
* @author chenhao
* @since 2023/11/29
*/
@RestController
@Api(tags = "图片批次")
@RequiredArgsConstructor
@RequestMapping("/imgproc/batch")
public class ImageBatchController {
private final ImageDetectionDao imageDetectionDao;
private final ImageBatchDao imageBatchDao;
@ApiOperation("根据ID查询")
@GetMapping("/unqualified/{id}")
public ResultVo<Long> unqualified(@PathVariable Long id) {
return ResultVo.success(imageDetectionDao.selectCount(
Wrappers.lambdaQuery(ImageDetection.builder().batchId(id).qualified(0).build())
));
}
@ApiOperation("根据ID查询")
@GetMapping("/sele/{id}")
public ResultVo<ImageBatch> selectOne(@PathVariable Long id) {
return ResultVo.success(imageBatchDao.selectById(id));
}
@ApiOperation("分页查询批次")
@PostMapping("/selectPage")
public ResultVo<PageVo<ImageBatch>> selectPage(@RequestBody BatchPageReq req) {
LambdaQueryWrapper<ImageBatch> wrapper = Wrappers.lambdaQuery();
if (StrUtil.isNotBlank(req.getName())) {
wrapper.like(ImageBatch::getName, req.getName());
}
if (StrUtil.isNotBlank(req.getNickName())) {
wrapper.like(ImageBatch::getNickName, req.getNickName());
}
if (StrUtil.isNotBlank(req.getStartTime())) {
wrapper.gt(ImageBatch::getCreateTime, req.getStartTime());
}
if (StrUtil.isNotBlank(req.getEndTime())) {
wrapper.lt(ImageBatch::getCreateTime, req.getEndTime());
}
IPage<ImageBatch> page = new Page<>(req.getPage(), req.getSize());
page = imageBatchDao.selectPage(page, wrapper);
return ResultVo.success(PageVo.ofReqVo(req, page.getRecords(), Convert.toInt(page.getSize())));
}
@ApiOperation("删除批次")
@GetMapping("/deleteById/{id}")
public ResultVo<?> detection(@PathVariable Long id) {
AssertUtils.notNull(id, "批次ID不能为空!");
// 删除批次里面的检测记录
List<ImageDetection> detections = imageDetectionDao.selectList(Wrappers.lambdaQuery(
ImageDetection.builder().batchId(id).build()
));
for (ImageDetection imageDetection : detections) {
if (StrUtil.isNotBlank(imageDetection.getFileUrl())){
FileUtil.del(imageDetection.getFileUrl());
}
}
imageDetectionDao.deleteBatchIds(
detections.stream().map(ImageDetection::getId).collect(Collectors.toList())
);
int res = imageBatchDao.deleteById(id);
if (res > 0) {
return ResultVo.success();
} else {
return ResultVo.fail("删除失败");
}
}
}
......@@ -6,8 +6,11 @@ import com.zq.common.vo.ResultVo;
import com.zq.imgproc.entity.ImageDetection;
import com.zq.imgproc.server.ImageDetectionService;
import com.zq.imgproc.vo.DetectionPageReq;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import lombok.RequiredArgsConstructor;
import org.springframework.core.io.Resource;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
......@@ -19,16 +22,18 @@ import org.springframework.web.multipart.MultipartFile;
* @author chenhao
* @since 2023/11/28
*/
@RequestMapping("/imgproc/detection")
@RestController
@Api(tags = "图片检测")
@RequiredArgsConstructor
@RequestMapping("/imgproc/detection")
public class ImageDetectionController {
@Autowired
ImageDetectionService service;
private final ImageDetectionService service;
@ApiOperation("分页查询")
@PostMapping("/selectPage")
public ResultVo<PageVo<ImageDetection>> selectPage(@RequestBody DetectionPageReq req) {
AssertUtils.notNull(req.getBatchId(), "批次ID不能为空!");
return ResultVo.success(service.selectPage(req));
}
......@@ -43,9 +48,17 @@ public class ImageDetectionController {
@PostMapping("/upload")
public ResultVo<?> upload(@RequestParam Long userId,
@RequestParam String nickName,
@RequestParam String batchName,
@RequestPart MultipartFile[] file) throws Exception {
AssertUtils.notNull(userId, "用户ID不能为空!");
return service.detection(userId, nickName, file);
return service.detection(userId, nickName, batchName, file);
}
@ApiOperation("导出检测结果")
@GetMapping("/getDetection/{batchId}")
public ResponseEntity<Resource> getDetection(@PathVariable Long batchId) {
AssertUtils.notNull(batchId, "批次ID不能为空!");
return service.getDetection(batchId);
}
}
......@@ -2,8 +2,6 @@ package com.zq.imgproc.controller;
import cn.hutool.core.io.FileUtil;
import cn.hutool.extra.servlet.ServletUtil;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.zq.common.utils.AssertUtils;
import com.zq.common.vo.ResultVo;
import com.zq.imgproc.server.ImgProcService;
......@@ -21,12 +19,11 @@ import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.util.List;
/**
* <p>
* 图片检测接口
* 图片检测接口 废弃
* </p>
*
* @author chenhao
......@@ -38,17 +35,6 @@ import java.util.List;
@RestController
public class ImgProcController {
/**
* 普通的缓存 Cache
*/
private final Cache<String, Double> cache = CacheBuilder.newBuilder()
.expireAfterAccess(Duration.ofMinutes(30))
.expireAfterWrite(Duration.ofHours(48))
.maximumSize(1024)
.concurrencyLevel(4)
.initialCapacity(1024)
.build();
private final ImgProcService service;
@Autowired
public ImgProcController(ImgProcService service) {
......
......@@ -3,10 +3,12 @@ package com.zq.imgproc.controller;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.zq.common.vo.ResultVo;
import com.zq.imgproc.constant.Threshold;
import com.zq.imgproc.dao.ImgSettingDao;
import com.zq.imgproc.entity.ImgSetting;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
/**
......@@ -17,20 +19,30 @@ import org.springframework.web.bind.annotation.*;
* @author chenhao
* @since 2023/11/28
*/
@io.swagger.annotations.Api(tags = "图片指标")
@RequestMapping("/imgproc/setting")
@RestController
@Api(tags = "图片指标")
@RequiredArgsConstructor
@RequestMapping("/imgproc/setting")
public class ImgSettingController {
@Autowired
ImgSettingDao imgSettingDao;
private final ImgSettingDao imgSettingDao;
@ApiOperation("根据用户ID获取指标")
@GetMapping("/getSetting/{userId}")
public ResultVo<?> getSetting(@PathVariable long userId) {
return ResultVo.success(
imgSettingDao.selectOne(Wrappers.lambdaQuery(ImgSetting.builder().userId(userId).build()))
);
ImgSetting setting = imgSettingDao.selectOne(Wrappers.lambdaQuery(ImgSetting.builder().userId(userId).build()));
// 找寻不到用户的指标,则返回默认值
if (setting == null) {
setting = ImgSetting.builder()
.clarity(Threshold.CLARITY)
.brightnessStart(Threshold.BRIGHTNESS_START)
.brightnessEnd(Threshold.BRIGHTNESS_END)
.bend(Threshold.BEND)
.deskewAngel(Threshold.DESKEW)
.black(Threshold.BLACK)
.build();
}
return ResultVo.success(setting);
}
@ApiOperation("设置或更新图片指标")
......
package com.zq.imgproc.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.zq.imgproc.entity.ImageBatch;
/**
* <p>
*
* </p>
*
* @author chenhao
* @since 2023/11/29
*/
public interface ImageBatchDao extends BaseMapper<ImageBatch> {
}
package com.zq.imgproc.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.Date;
/**
* <p>
*
* </p>
*
* @author chenhao
* @since 2023/11/29
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
@TableName("image_batch")
public class ImageBatch implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty("数据ID")
@TableId(value = "id", type = IdType.AUTO)
private Long id;
@ApiModelProperty("用户ID")
@TableField("user_id")
private Long userId;
@ApiModelProperty("用户名称")
@TableField("nick_name")
private String nickName;
@ApiModelProperty("批次名称")
@TableField("name")
private String name;
@ApiModelProperty("创建时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date createTime;
}
......@@ -35,6 +35,10 @@ public class ImageDetection implements Serializable {
@TableId(value = "id", type = IdType.AUTO)
private Long id;
@ApiModelProperty("批次ID")
@TableField("batch_id")
private Long batchId;
@ApiModelProperty("用户ID")
@TableField("user_id")
private Long userId;
......@@ -79,7 +83,7 @@ public class ImageDetection implements Serializable {
@TableField("bend")
private Double bend;
@ApiModelProperty("图片亮度起始范围")
@ApiModelProperty("图片亮度")
@TableField("brightness")
private Integer brightness;
......
......@@ -3,27 +3,38 @@ package com.zq.imgproc.server;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zq.common.utils.AssertUtils;
import com.zq.common.utils.UuidUtils;
import com.zq.common.vo.PageVo;
import com.zq.common.vo.ResultVo;
import com.zq.imgproc.constant.Threshold;
import com.zq.imgproc.dao.ImageBatchDao;
import com.zq.imgproc.dao.ImageDetectionDao;
import com.zq.imgproc.dao.ImgSettingDao;
import com.zq.imgproc.entity.ImageBatch;
import com.zq.imgproc.entity.ImageDetection;
import com.zq.imgproc.entity.ImgSetting;
import com.zq.imgproc.utils.DecompressUtil;
import com.zq.imgproc.utils.Deskew;
import com.zq.imgproc.utils.ImageUtil;
import com.zq.imgproc.vo.DetectionPageReq;
import com.zq.imgproc.vo.ImgVO;
import com.zq.imgproc.vo.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.opencv.core.Mat;
import org.opencv.imgcodecs.Imgcodecs;
import org.springframework.core.io.InputStreamResource;
import org.springframework.core.io.Resource;
import org.springframework.http.ContentDisposition;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.io.BufferedInputStream;
import java.io.File;
import java.math.BigDecimal;
import java.math.RoundingMode;
......@@ -45,14 +56,33 @@ public class ImageDetectionService {
private final ImgSettingDao imgSettingDao;
private final ImageDetectionDao imageDetectionDao;
private final ImageBatchDao imageBatchDao;
public ResultVo<?> detection(long userId, String nickName, MultipartFile[] file) throws Exception {
public ResultVo<?> detection(long userId, String nickName, String batchName, MultipartFile[] file) throws Exception {
ImageBatch imageBatch = ImageBatch.builder()
.name(batchName)
.nickName(nickName)
.userId(userId)
.createTime(DateUtil.date())
.build();
int count = imageBatchDao.insert(imageBatch);
if (count <= 0) {
return ResultVo.fail("创建批次失败!");
}
// 查询用户配置
ImgSetting imgSetting = imgSettingDao.selectOne(
Wrappers.lambdaQuery(ImgSetting.builder().userId(userId).build())
);
// 查询不到用户配置,使用默认值进行检测
if (imgSetting == null) {
return ResultVo.fail("查询不到用户的配置信息!");
imgSetting = ImgSetting.builder()
.clarity(Threshold.CLARITY)
.brightnessStart(Threshold.BRIGHTNESS_START)
.brightnessEnd(Threshold.BRIGHTNESS_END)
.bend(Threshold.BEND)
.deskewAngel(Threshold.DESKEW)
.black(Threshold.BLACK)
.build();
}
// 解压文件
List<ImgVO> imgs = new ArrayList<>();
......@@ -77,6 +107,7 @@ public class ImageDetectionService {
// 图片检测
ImageDetection detection = new ImageDetection();
// 设置上传信息
detection.setBatchId(imageBatch.getId());
detection.setUserId(userId);
detection.setNickName(nickName);
detection.setUploadTime(DateUtil.date());
......@@ -166,4 +197,47 @@ public class ImageDetectionService {
public ImageDetection selectOne(Long id) {
return imageDetectionDao.selectById(id);
}
public ResponseEntity<Resource> getDetection(Long batchId) {
String filePath = "/data/temp/" + UuidUtils.uuidNoDash() + ".xlsx";
List<ImageDetection> imageDetections = imageDetectionDao.selectList(
Wrappers.lambdaQuery(ImageDetection.builder().batchId(batchId).build())
);
EasyExcel
.write(filePath, ImageDetectionDTO.class)
.sheet("图片检测报告")
.doWrite(getData(imageDetections));
BufferedInputStream stream = FileUtil.getInputStream(filePath);
if (stream == null) {
return ResponseEntity.notFound().build();
}
String contentDisposition = ContentDisposition
.builder("attachment")
.filename("图片检测报告.xlsx")
.build().toString();
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_DISPOSITION, contentDisposition)
.contentType(MediaType.APPLICATION_OCTET_STREAM)
.body(new InputStreamResource(stream));
}
private List<ImageDetectionDTO> getData(List<ImageDetection> imageList) {
List<ImageDetectionDTO> dtos = new ArrayList<>(imageList.size());
for (ImageDetection img : imageList) {
ImageDetectionDTO dto = new ImageDetectionDTO();
dto.setImgName(img.getImgName());
dto.setSize(img.getSize() + " MB");
dto.setWidthResolution(img.getWidthResolution());
dto.setHeightResolution(img.getHeightResolution());
dto.setDpi(img.getDpi());
dto.setClarity(img.getClarity());
dto.setBend(img.getBend());
dto.setBrightness(img.getBrightness());
dto.setDeskewAngel(img.getDeskewAngel());
dto.setBlack(img.getBlack());
dto.setQualified(img.getQualified() == 0 ? "不合格" : "合格");
dtos.add(dto);
}
return dtos;
}
}
package com.zq.imgproc.vo;
import com.zq.common.vo.PageReqVo;
import lombok.Getter;
/**
* <p>
*
* </p>
*
* @author chenhao
* @since 2023/11/29
*/
public class BatchPageReq extends PageReqVo {
/**
* 批次名称
*/
@Getter
String name;
/**
* 用户昵称
*/
@Getter
String nickName;
/**
* 上传日期起始
*/
@Getter
String startTime;
/**
* 上传日期结束
*/
@Getter
String endTime;
}
......@@ -19,9 +19,9 @@ import lombok.NoArgsConstructor;
public class DetectionPageReq extends PageReqVo {
/**
* 用户名称
* 批次ID
*/
String nickName;
Long batchId;
/**
* 图片名称
......@@ -34,24 +34,6 @@ public class DetectionPageReq extends PageReqVo {
*/
String fileName;
/**
* 上传日期起始
*/
String startTime;
/**
* 上传日期结束
*/
String endTime;
public String getNickName() {
return nickName;
}
public void setNickName(String nickName) {
this.nickName = nickName;
}
public String getImgName() {
return imgName;
}
......@@ -68,20 +50,12 @@ public class DetectionPageReq extends PageReqVo {
this.fileName = fileName;
}
public String getStartTime() {
return startTime;
}
public void setStartTime(String startTime) {
this.startTime = startTime;
}
public String getEndTime() {
return endTime;
public Long getBatchId() {
return batchId;
}
public void setEndTime(String endTime) {
this.endTime = endTime;
public void setBatchId(Long batchId) {
this.batchId = batchId;
}
}
package com.zq.imgproc.vo;
import com.alibaba.excel.annotation.ExcelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* <p>
*
* </p>
*
* @author chenhao
* @since 2023/11/29
*/
@Data
@EqualsAndHashCode
public class ImageDetectionDTO {
@ExcelProperty("图片名称")
private String imgName;
@ExcelProperty("图片大小")
private String size;
@ExcelProperty("水平分辨率")
private Integer widthResolution;
@ExcelProperty("垂直分辨率")
private Integer heightResolution;
@ExcelProperty("DPI")
private Integer dpi;
@ExcelProperty("清晰度")
private Double clarity;
@ExcelProperty("弯曲置信度")
private Double bend;
@ExcelProperty("亮度值")
private Integer brightness;
@ExcelProperty("偏离度")
private Integer deskewAngel;
@ExcelProperty("黑边数值")
private Integer black;
@ExcelProperty("是否合格,0不合格,1合格")
private String qualified;
}
......@@ -2,6 +2,10 @@ server:
port: 9999
# 配置数据源
spring:
servlet:
multipart:
max-file-size: 6MB
max-request-size: -1
application:
name: IMGPROC-SERVER
jackson:
......
......@@ -8,8 +8,8 @@
SELECT *
FROM image_detection AS detection
<where>
<if test="req.nickName != null and req.nickName != ''">
AND detection.nick_name like concat('%', #{req.nickName}, '%')
<if test="req.batchId != null">
AND detection.batch_id = #{req.batchId}
</if>
<if test="req.imgName != null and req.imgName != ''">
AND detection.img_name like concat('%', #{req.imgName}, '%')
......@@ -17,22 +17,16 @@
<if test="req.fileName != null and req.fileName != ''">
AND detection.file_name like concat('%', #{req.fileName}, '%')
</if>
<if test="req.startTime != null and req.startTime != ''">
AND detection.upload_time &gt;= #{req.startTime}
</if>
<if test="req.endTime != null and req.endTime != ''">
AND detection.upload_time &lt;= #{req.endTime}
</if>
</where>
</select>
<insert id="insertBatch" parameterType="java.util.List">
insert into image_detection (user_id, nick_name, img_name, file_name, file_url,
insert into image_detection (user_id, batch_id, nick_name, img_name, file_name, file_url,
size, width_resolution, height_resolution, dpi, clarity, bend, brightness,
deskew_angel, black, qualified, upload_time)
values
<foreach collection="list" item="item" separator=",">
(#{item.userId}, #{item.nickName}, #{item.imgName}, #{item.fileName},
(#{item.userId},#{item.batchId},#{item.nickName}, #{item.imgName}, #{item.fileName},
#{item.fileUrl}, #{item.size}, #{item.widthResolution}, #{item.heightResolution},
#{item.dpi}, #{item.clarity}, #{item.bend}, #{item.brightness},
#{item.deskewAngel}, #{item.black}, #{item.qualified}, #{item.uploadTime})
......
......@@ -61,10 +61,6 @@
<artifactId>fastjson</artifactId>
<version>${fastjson.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
......
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