Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
I
imgproc
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
陈皓
imgproc
Commits
a9ca035e
Commit
a9ca035e
authored
Nov 24, 2023
by
陈皓
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
更新
parent
4ba97838
Show whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
456 additions
and
242 deletions
+456
-242
gateway-server/src/main/resources/application.yml
+4
-0
imgproc-server/pom.xml
+11
-0
imgproc-server/src/main/java/com/zq/imgproc/controller/ApiController.java
+1
-11
imgproc-server/src/main/java/com/zq/imgproc/controller/FileController.java
+51
-0
imgproc-server/src/main/java/com/zq/imgproc/controller/ImgProcController.java
+50
-25
imgproc-server/src/main/java/com/zq/imgproc/server/ImgProcService.java
+54
-8
imgproc-server/src/main/java/com/zq/imgproc/utils/Deskew.java
+3
-3
imgproc-server/src/main/java/com/zq/imgproc/utils/ImageUtil.java
+10
-7
imgproc-server/src/main/java/com/zq/imgproc/utils/RemoveBlackUtil.java
+28
-34
imgproc-server/src/main/java/com/zq/imgproc/utils/RemoveBlackUtil2.java
+1
-1
imgproc-server/src/main/java/com/zq/imgproc/utils/Test2.java
+57
-0
imgproc-server/src/main/java/com/zq/imgproc/utils/TestUtil.java
+130
-136
imgproc-server/src/main/java/com/zq/imgproc/vo/DetectionDTO.java
+42
-0
imgproc-server/src/main/java/com/zq/imgproc/vo/DetectionResVo2.java
+2
-5
imgproc-server/src/main/java/com/zq/imgproc/vo/SettingVO.java
+4
-4
imgproc-server/src/main/resources/application.yml
+8
-8
No files found.
gateway-server/src/main/resources/application.yml
View file @
a9ca035e
...
@@ -23,4 +23,8 @@ spring:
...
@@ -23,4 +23,8 @@ spring:
uri
:
lb://IMGPROC-SERVER
uri
:
lb://IMGPROC-SERVER
predicates
:
predicates
:
-
Path=/imgproc/**
-
Path=/imgproc/**
-
id
:
file
uri
:
lb://IMGPROC-SERVER
predicates
:
-
Path=/file/**
imgproc-server/pom.xml
View file @
a9ca035e
...
@@ -92,6 +92,11 @@
...
@@ -92,6 +92,11 @@
<version>
5.8.19
</version>
<version>
5.8.19
</version>
</dependency>
</dependency>
<dependency>
<dependency>
<groupId>
com.alibaba
</groupId>
<artifactId>
easyexcel
</artifactId>
<version>
3.3.2
</version>
</dependency>
<dependency>
<groupId>
com.drewnoakes
</groupId>
<groupId>
com.drewnoakes
</groupId>
<artifactId>
metadata-extractor
</artifactId>
<artifactId>
metadata-extractor
</artifactId>
<version>
2.18.0
</version>
<version>
2.18.0
</version>
...
@@ -111,6 +116,12 @@
...
@@ -111,6 +116,12 @@
<artifactId>
springfox-swagger-ui
</artifactId>
<artifactId>
springfox-swagger-ui
</artifactId>
<version>
2.9.2
</version>
<version>
2.9.2
</version>
</dependency>
</dependency>
<!-- guava -->
<dependency>
<groupId>
com.google.guava
</groupId>
<artifactId>
guava
</artifactId>
<version>
32.1.3-jre
</version>
</dependency>
</dependencies>
</dependencies>
<build>
<build>
...
...
imgproc-server/src/main/java/com/zq/imgproc/controller/ApiController.java
View file @
a9ca035e
...
@@ -91,17 +91,7 @@ public class ApiController {
...
@@ -91,17 +91,7 @@ public class ApiController {
// 去黑边
// 去黑边
RemoveBlackUtil2
.
remove
(
imgPath
,
savePath
);
RemoveBlackUtil2
.
remove
(
imgPath
,
savePath
);
// 图片弯曲矫正
return
ResultVo
.
success
(
Base64Encoder
.
encode
(
savePath
));
HashMap
<
String
,
Object
>
map
=
new
HashMap
<>();
map
.
put
(
"file"
,
FileUtil
.
file
(
savePath
));
String
response
=
HttpUtil
.
post
(
"http://ddns.gxmailu.com:18888/api/correct"
,
map
);
JSONObject
res
=
JSONUtil
.
parseObj
(
response
);
if
(
res
.
get
(
"success"
,
Boolean
.
class
))
{
String
base64
=
res
.
get
(
"data"
,
String
.
class
);
return
ResultVo
.
success
(
base64
);
}
else
{
return
ResultVo
.
fail
(
res
.
get
(
"msg"
,
String
.
class
));
}
}
}
@ApiOperation
(
"图片灰度化"
)
@ApiOperation
(
"图片灰度化"
)
...
...
imgproc-server/src/main/java/com/zq/imgproc/controller/FileController.java
0 → 100644
View file @
a9ca035e
package
com
.
zq
.
imgproc
.
controller
;
import
cn.hutool.core.util.URLUtil
;
import
com.zq.imgproc.utils.AssertUtils
;
import
io.swagger.annotations.Api
;
import
org.springframework.core.io.FileSystemResource
;
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.web.bind.annotation.CrossOrigin
;
import
org.springframework.web.bind.annotation.GetMapping
;
import
org.springframework.web.bind.annotation.RequestMapping
;
import
org.springframework.web.bind.annotation.RestController
;
import
javax.servlet.http.HttpServletRequest
;
import
java.io.File
;
/**
* <p>
*
* </p>
*
* @author zq
* @since 2023/11/15
*/
@Api
(
tags
=
"访问文件"
)
@RestController
@CrossOrigin
@RequestMapping
(
"/"
)
public
class
FileController
{
@GetMapping
(
value
=
"/file/**"
)
public
ResponseEntity
<
Resource
>
archive
(
HttpServletRequest
request
)
{
String
requestURI
=
request
.
getRequestURI
();
requestURI
=
URLUtil
.
decode
(
requestURI
);
File
file
=
new
File
(
requestURI
);
AssertUtils
.
isTrue
(
file
.
exists
(),
"访问文件不存在"
);
String
contentDisposition
=
ContentDisposition
.
builder
(
"attachment"
)
.
filename
(
requestURI
)
.
build
().
toString
();
return
ResponseEntity
.
ok
()
.
header
(
HttpHeaders
.
CONTENT_DISPOSITION
,
contentDisposition
)
.
contentType
(
MediaType
.
APPLICATION_OCTET_STREAM
)
.
body
(
new
FileSystemResource
(
file
));
}
}
imgproc-server/src/main/java/com/zq/imgproc/controller/ImgProcController.java
View file @
a9ca035e
package
com
.
zq
.
imgproc
.
controller
;
package
com
.
zq
.
imgproc
.
controller
;
import
cn.hutool.core.convert.Convert
;
import
cn.hutool.core.io.FileUtil
;
import
cn.hutool.core.io.FileUtil
;
import
cn.hutool.extra.servlet.ServletUtil
;
import
cn.hutool.extra.servlet.ServletUtil
;
import
com.google.common.cache.Cache
;
import
com.google.common.cache.CacheBuilder
;
import
com.zq.imgproc.server.ImgProcService
;
import
com.zq.imgproc.server.ImgProcService
;
import
com.zq.imgproc.utils.AssertUtils
;
import
com.zq.imgproc.utils.AssertUtils
;
import
com.zq.imgproc.utils.DecompressUtil
;
import
com.zq.imgproc.utils.DecompressUtil
;
...
@@ -11,6 +14,8 @@ import com.zq.imgproc.vo.*;
...
@@ -11,6 +14,8 @@ import com.zq.imgproc.vo.*;
import
io.swagger.annotations.Api
;
import
io.swagger.annotations.Api
;
import
io.swagger.annotations.ApiOperation
;
import
io.swagger.annotations.ApiOperation
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.core.io.Resource
;
import
org.springframework.http.ResponseEntity
;
import
org.springframework.web.bind.annotation.*
;
import
org.springframework.web.bind.annotation.*
;
import
org.springframework.web.multipart.MultipartFile
;
import
org.springframework.web.multipart.MultipartFile
;
...
@@ -18,8 +23,10 @@ import javax.servlet.http.HttpServletResponse;
...
@@ -18,8 +23,10 @@ import javax.servlet.http.HttpServletResponse;
import
java.io.IOException
;
import
java.io.IOException
;
import
java.io.InputStream
;
import
java.io.InputStream
;
import
java.nio.charset.StandardCharsets
;
import
java.nio.charset.StandardCharsets
;
import
java.time.Duration
;
import
java.util.ArrayList
;
import
java.util.ArrayList
;
import
java.util.List
;
import
java.util.List
;
import
java.util.concurrent.TimeUnit
;
/**
/**
* <p>
* <p>
...
@@ -35,11 +42,20 @@ import java.util.List;
...
@@ -35,11 +42,20 @@ import java.util.List;
@RestController
@RestController
public
class
ImgProcController
{
public
class
ImgProcController
{
// @Resource
/**
// RedisUtils redisUtils;
* 普通的缓存 Cache
// private final double CAST = 1;
*/
// private final double DA = 1;
private
final
Cache
<
String
,
Double
>
cache
=
CacheBuilder
.
newBuilder
()
// private final double CLARITY = 10;
.
expireAfterAccess
(
Duration
.
ofMinutes
(
30
))
.
expireAfterWrite
(
Duration
.
ofHours
(
48
))
.
maximumSize
(
1024
)
.
concurrencyLevel
(
4
)
.
initialCapacity
(
1024
)
.
build
();
private
final
double
START_VALUE
=
75
;
private
final
double
END_VALUE
=
175
;
private
final
double
CLARITY
=
2.5
;
private
final
ImgProcService
service
;
private
final
ImgProcService
service
;
@Autowired
@Autowired
...
@@ -89,6 +105,12 @@ public class ImgProcController {
...
@@ -89,6 +105,12 @@ public class ImgProcController {
return
ResultVo
.
success
(
service
.
detection
(
pathList
));
return
ResultVo
.
success
(
service
.
detection
(
pathList
));
}
}
@ApiOperation
(
"导出检测结果"
)
@PostMapping
(
"/getDetection"
)
public
ResponseEntity
<
Resource
>
getDetection
(
@RequestBody
List
<
ImgVO
>
pathList
)
throws
Exception
{
return
service
.
getDetection
(
pathList
);
}
@ApiOperation
(
"图片校正(deskew工具)"
)
@ApiOperation
(
"图片校正(deskew工具)"
)
@PostMapping
(
"/imageCorrection"
)
@PostMapping
(
"/imageCorrection"
)
public
ResultVo
<?>
imageCorrection
(
@RequestBody
List
<
ImgVO
>
pathList
)
throws
IOException
{
public
ResultVo
<?>
imageCorrection
(
@RequestBody
List
<
ImgVO
>
pathList
)
throws
IOException
{
...
@@ -107,26 +129,29 @@ public class ImgProcController {
...
@@ -107,26 +129,29 @@ public class ImgProcController {
return
ResultVo
.
success
(
service
.
removeBlack
(
pathList
));
return
ResultVo
.
success
(
service
.
removeBlack
(
pathList
));
}
}
// @ApiOperation("获取配置")
@ApiOperation
(
"获取配置"
)
// @PostMapping("/getSetting")
@GetMapping
(
"/getSetting"
)
// public ResultVo<?> getSetting() {
public
ResultVo
<?>
getSetting
()
{
// double cast = Convert.toDouble(redisUtils.get("img-cast")) == null ? CAST : Convert.toDouble(redisUtils.get("img-cast"));
Double
temp1
=
cache
.
getIfPresent
(
"img-start"
);
// double da = Convert.toDouble(redisUtils.get("img-da")) == null ? DA : Convert.toDouble(redisUtils.get("img-da"));
Double
temp2
=
cache
.
getIfPresent
(
"img-end"
);
// double clarity = Convert.toDouble(redisUtils.get("img-clarity")) == null ? CLARITY : Convert.toDouble(redisUtils.get("img-clarity"));
Double
temp3
=
cache
.
getIfPresent
(
"img-clarity"
);
// return ResultVo.success(SettingVO.builder().cast(cast).da(da).clarity(clarity).build());
double
start
=
temp1
==
null
?
START_VALUE
:
temp1
;
// }
double
end
=
temp2
==
null
?
END_VALUE
:
temp2
;
//
double
clarity
=
temp3
==
null
?
CLARITY
:
temp3
;
// @ApiOperation("设置配置")
return
ResultVo
.
success
(
SettingVO
.
builder
().
startValue
(
start
).
endValue
(
end
).
clarity
(
clarity
).
build
());
// @PostMapping("/setSetting")
}
// public ResultVo<?> setSetting(@RequestBody SettingVO setting) {
// if (setting == null) {
@ApiOperation
(
"设置配置"
)
// return ResultVo.fail("配置不能为空!");
@PostMapping
(
"/setSetting"
)
// }
public
ResultVo
<?>
setSetting
(
@RequestBody
SettingVO
setting
)
{
// redisUtils.setStr("img-cast", String.valueOf(setting.getCast()));
if
(
setting
==
null
)
{
// redisUtils.setStr("img-da", String.valueOf(setting.getDa()));
return
ResultVo
.
fail
(
"配置不能为空!"
);
// redisUtils.setStr("img-clarity", String.valueOf(setting.getClarity()));
}
// return ResultVo.success();
cache
.
put
(
"img-start"
,
setting
.
getStartValue
());
// }
cache
.
put
(
"img-end"
,
setting
.
getEndValue
());
cache
.
put
(
"img-clarity"
,
setting
.
getClarity
());
return
ResultVo
.
success
();
}
@ApiOperation
(
"图片旋转"
)
@ApiOperation
(
"图片旋转"
)
@PostMapping
(
"/rotate"
)
@PostMapping
(
"/rotate"
)
...
...
imgproc-server/src/main/java/com/zq/imgproc/server/ImgProcService.java
View file @
a9ca035e
...
@@ -6,6 +6,7 @@ import cn.hutool.core.codec.Base64Encoder;
...
@@ -6,6 +6,7 @@ import cn.hutool.core.codec.Base64Encoder;
import
cn.hutool.core.convert.Convert
;
import
cn.hutool.core.convert.Convert
;
import
cn.hutool.core.img.ImgUtil
;
import
cn.hutool.core.img.ImgUtil
;
import
cn.hutool.core.io.FileUtil
;
import
cn.hutool.core.io.FileUtil
;
import
com.alibaba.excel.EasyExcel
;
import
com.drew.imaging.ImageMetadataReader
;
import
com.drew.imaging.ImageMetadataReader
;
import
com.drew.metadata.Directory
;
import
com.drew.metadata.Directory
;
import
com.drew.metadata.Metadata
;
import
com.drew.metadata.Metadata
;
...
@@ -23,13 +24,22 @@ import org.opencv.core.MatOfDouble;
...
@@ -23,13 +24,22 @@ import org.opencv.core.MatOfDouble;
import
org.opencv.imgcodecs.Imgcodecs
;
import
org.opencv.imgcodecs.Imgcodecs
;
import
org.opencv.imgproc.Imgproc
;
import
org.opencv.imgproc.Imgproc
;
import
org.springframework.beans.factory.annotation.Value
;
import
org.springframework.beans.factory.annotation.Value
;
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.stereotype.Service
;
import
org.springframework.web.multipart.MultipartFile
;
import
org.springframework.web.multipart.MultipartFile
;
import
javax.imageio.ImageIO
;
import
javax.imageio.ImageIO
;
import
java.awt.image.BufferedImage
;
import
java.awt.image.BufferedImage
;
import
java.io.BufferedInputStream
;
import
java.io.File
;
import
java.io.File
;
import
java.io.IOException
;
import
java.io.IOException
;
import
java.math.BigDecimal
;
import
java.math.RoundingMode
;
import
java.text.SimpleDateFormat
;
import
java.text.SimpleDateFormat
;
import
java.util.*
;
import
java.util.*
;
import
java.util.regex.Matcher
;
import
java.util.regex.Matcher
;
...
@@ -56,7 +66,6 @@ public class ImgProcService {
...
@@ -56,7 +66,6 @@ public class ImgProcService {
public
List
<
ImgVO
>
detection
(
List
<
ImgVO
>
pathList
)
throws
Exception
{
public
List
<
ImgVO
>
detection
(
List
<
ImgVO
>
pathList
)
throws
Exception
{
List
<
ImgVO
>
res
=
new
ArrayList
<>(
pathList
.
size
());
List
<
ImgVO
>
res
=
new
ArrayList
<>(
pathList
.
size
());
for
(
ImgVO
one
:
pathList
)
{
for
(
ImgVO
one
:
pathList
)
{
DetectionResVo2
vo
=
new
DetectionResVo2
();
DetectionResVo2
vo
=
new
DetectionResVo2
();
String
path
=
one
.
getUrl
();
String
path
=
one
.
getUrl
();
Mat
image
=
Imgcodecs
.
imread
(
path
);
Mat
image
=
Imgcodecs
.
imread
(
path
);
...
@@ -66,13 +75,10 @@ public class ImgProcService {
...
@@ -66,13 +75,10 @@ public class ImgProcService {
// 检测图片的DPI
// 检测图片的DPI
vo
.
setDpi
(
getDpi
(
FileUtil
.
file
(
path
)));
vo
.
setDpi
(
getDpi
(
FileUtil
.
file
(
path
)));
// 检测图片清晰度
// 检测图片清晰度
vo
.
setClarity
(
ImageUtil
.
tenengrad
(
image
));
BigDecimal
clarity
=
BigDecimal
.
valueOf
(
ImageUtil
.
tenengrad
(
image
));
vo
.
setClarity
(
clarity
.
setScale
(
2
,
RoundingMode
.
HALF_UP
).
doubleValue
());
// 检测图片的亮度
// 检测图片的亮度
double
[]
arr
=
brightnessDetection
(
image
);
vo
.
setBrightness
(
Convert
.
toInt
(
ImageUtil
.
brightness
(
image
)));
if
(
arr
!=
null
)
{
vo
.
setCast
(
arr
[
0
]);
vo
.
setDa
(
arr
[
1
]);
}
// 检测图片倾斜角度
// 检测图片倾斜角度
vo
.
setAngle
(
getAngle
(
image
));
vo
.
setAngle
(
getAngle
(
image
));
// 检测图片的黑边
// 检测图片的黑边
...
@@ -438,7 +444,7 @@ public class ImgProcService {
...
@@ -438,7 +444,7 @@ public class ImgProcService {
index
++;
index
++;
}
}
// 修正
// 修正
return
ImageUtil
.
correct
(
pathList
)
;
return
pathList
;
}
}
public
List
<
ImgVO
>
deskew
(
List
<
ImgVO
>
pathList
)
{
public
List
<
ImgVO
>
deskew
(
List
<
ImgVO
>
pathList
)
{
...
@@ -693,5 +699,45 @@ public class ImgProcService {
...
@@ -693,5 +699,45 @@ public class ImgProcService {
return
Base64Encoder
.
encode
(
FileUtil
.
readBytes
(
dst
));
return
Base64Encoder
.
encode
(
FileUtil
.
readBytes
(
dst
));
}
}
public
ResponseEntity
<
Resource
>
getDetection
(
List
<
ImgVO
>
pathList
)
throws
Exception
{
if
(
pathList
==
null
||
pathList
.
size
()
==
0
)
{
return
ResponseEntity
.
badRequest
().
build
();
}
pathList
=
detection
(
pathList
);
String
filePath
=
"/data/temp/"
+
UuidUtils
.
uuidNoDash
()
+
".xlsx"
;
EasyExcel
.
write
(
filePath
,
DetectionDTO
.
class
).
sheet
(
"图片检测报告"
).
doWrite
(
getData
(
pathList
));
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
<
DetectionDTO
>
getData
(
List
<
ImgVO
>
pathList
)
{
List
<
DetectionDTO
>
dtos
=
new
ArrayList
<>(
pathList
.
size
());
for
(
ImgVO
imgVO
:
pathList
)
{
DetectionResVo2
detectionRes
=
imgVO
.
getDetectionRes
();
DetectionDTO
dto
=
new
DetectionDTO
();
dto
.
setFilename
(
imgVO
.
getFileName
());
dto
.
setResolution
(
detectionRes
.
getWidthResolution
()
+
" x "
+
detectionRes
.
getHeightResolution
());
dto
.
setDpi
(
detectionRes
.
getDpi
());
dto
.
setBrightness
(
detectionRes
.
getBrightness
());
dto
.
setClarity
(
detectionRes
.
getClarity
());
dto
.
setAngle
(
detectionRes
.
getAngle
());
dto
.
setBlack
(
detectionRes
.
getBlack
()
?
"是"
:
"否"
);
dtos
.
add
(
dto
);
}
return
dtos
;
}
}
}
imgproc-server/src/main/java/com/zq/imgproc/utils/Deskew.java
View file @
a9ca035e
...
@@ -10,9 +10,6 @@ import java.util.HashMap;
...
@@ -10,9 +10,6 @@ import java.util.HashMap;
import
java.util.List
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Map
;
import
static
org
.
opencv
.
highgui
.
HighGui
.
imshow
;
import
static
org
.
opencv
.
highgui
.
HighGui
.
waitKey
;
public
class
Deskew
{
public
class
Deskew
{
public
static
void
main
(
String
[]
args
)
{
public
static
void
main
(
String
[]
args
)
{
...
@@ -136,6 +133,9 @@ public class Deskew {
...
@@ -136,6 +133,9 @@ public class Deskew {
int
w
=
image
.
cols
();
int
w
=
image
.
cols
();
int
h
=
image
.
rows
();
int
h
=
image
.
rows
();
if
(
angle
<
0
)
{
angle
=
360
+
angle
;
}
Point
center
=
new
Point
((
double
)
w
/
2
,
(
double
)
h
/
2
);
Point
center
=
new
Point
((
double
)
w
/
2
,
(
double
)
h
/
2
);
double
scale
=
1.0
;
double
scale
=
1.0
;
...
...
imgproc-server/src/main/java/com/zq/imgproc/utils/ImageUtil.java
View file @
a9ca035e
...
@@ -152,14 +152,17 @@ public class ImageUtil {
...
@@ -152,14 +152,17 @@ public class ImageUtil {
// 灰度化
// 灰度化
Mat
mat
=
Imgcodecs
.
imread
(
src
);
Mat
mat
=
Imgcodecs
.
imread
(
src
);
Mat
gray
=
mat
.
clone
();
Mat
gray
=
mat
.
clone
();
if
(
mat
.
channels
()
==
4
||
mat
.
channels
()
==
3
)
{
// if (mat.channels() == 4 || mat.channels() == 3) {
// Imgproc.cvtColor(mat, gray, Imgproc.COLOR_BGR2GRAY);
// } else if (mat.channels() == 2) {
// Imgproc.cvtColor(mat, gray, Imgproc.COLOR_BGR5652GRAY);
// } else {
// gray = mat;
// }
Imgproc
.
cvtColor
(
mat
,
gray
,
Imgproc
.
COLOR_BGR2GRAY
);
Imgproc
.
cvtColor
(
mat
,
gray
,
Imgproc
.
COLOR_BGR2GRAY
);
}
else
if
(
mat
.
channels
()
==
2
)
{
Imgproc
.
cvtColor
(
mat
,
gray
,
Imgproc
.
COLOR_BGR5652GRAY
);
}
else
{
gray
=
mat
;
}
saveImage
(
gray
,
dst
);
saveImage
(
gray
,
dst
);
gray
.
release
();
mat
.
release
();
}
}
/**
/**
...
@@ -383,7 +386,7 @@ public class ImageUtil {
...
@@ -383,7 +386,7 @@ public class ImageUtil {
}
}
/**
/**
* 计算图片平均亮度
* 计算图片平均亮度
,范围是0到255
*
*
* @param path 图片路径
* @param path 图片路径
* @return 图片平均亮度
* @return 图片平均亮度
...
...
imgproc-server/src/main/java/com/zq/imgproc/utils/RemoveBlackUtil.java
View file @
a9ca035e
...
@@ -17,14 +17,12 @@ import java.util.Random;
...
@@ -17,14 +17,12 @@ import java.util.Random;
* @author chenhao
* @author chenhao
* @since 2023/3/8 9:31
* @since 2023/3/8 9:31
*/
*/
@SuppressWarnings
(
"all"
)
public
class
RemoveBlackUtil
{
public
class
RemoveBlackUtil
{
public
static
void
main
(
String
[]
args
)
{
public
static
void
main
(
String
[]
args
)
{
long
start
=
System
.
currentTimeMillis
();
String
testImg
=
"C:\\Users\\11419\\Desktop\\test\\a.jpg"
;
String
testImg
=
"C:\\Users\\11419\\Desktop\\project\\company\\test\\9.jpg"
;
String
resImg
=
"C:\\Users\\11419\\Desktop\\test\\8.jpg"
;
String
resImg
=
"C:\\Users\\11419\\Desktop\\project\\company\\test\\res9.jpg"
;
System
.
load
(
"D:\\project\\imgproc\\lib\\opencv_java460.dll"
);
System
.
load
(
"C:\\Users\\11419\\Desktop\\project\\company\\imgproc\\lib\\opencv_java460.dll"
);
remove
(
testImg
,
resImg
);
remove
(
testImg
,
resImg
);
}
}
...
@@ -36,21 +34,21 @@ public class RemoveBlackUtil {
...
@@ -36,21 +34,21 @@ public class RemoveBlackUtil {
Mat
greyImg
=
img
.
clone
();
Mat
greyImg
=
img
.
clone
();
//1.彩色转灰色
//1.彩色转灰色
Imgproc
.
cvtColor
(
img
,
greyImg
,
Imgproc
.
COLOR_BGR2GRAY
);
Imgproc
.
cvtColor
(
img
,
greyImg
,
Imgproc
.
COLOR_BGR2GRAY
);
// ImageUtil.saveImage(greyImg, "C:\\Users\\11419\\Desktop\\project\\company\\test\\guoc
\\1.jpg");
ImageUtil
.
saveImage
(
greyImg
,
"C:\\Users\\11419\\Desktop\\test
\\1.jpg"
);
Mat
gaussianBlurImg
=
greyImg
.
clone
();
Mat
gaussianBlurImg
=
greyImg
.
clone
();
// 2.高斯滤波,降噪
// 2.高斯滤波,降噪
Imgproc
.
GaussianBlur
(
greyImg
,
gaussianBlurImg
,
new
Size
(
3
,
3
),
2
,
2
);
Imgproc
.
GaussianBlur
(
greyImg
,
gaussianBlurImg
,
new
Size
(
3
,
3
),
0
);
// ImageUtil.saveImage(gaussianBlurImg, "C:\\Users\\11419\\Desktop\\project\\company\\test\\guoc\\2.jpg");
ImageUtil
.
saveImage
(
greyImg
,
"C:\\Users\\11419\\Desktop\\test\\2.jpg"
);
Mat
cannyImg
=
gaussianBlurImg
.
clone
();
// 3.Canny边缘检测
// 3.Canny边缘检测
Imgproc
.
Canny
(
gaussianBlurImg
,
cannyImg
,
20
,
60
,
3
,
false
);
Mat
cannyImg
=
gaussianBlurImg
.
clone
();
// ImageUtil.saveImage(cannyImg, "C:\\Users\\11419\\Desktop\\project\\company\\test\\guoc\\3.jpg");
Imgproc
.
Canny
(
gaussianBlurImg
,
cannyImg
,
50
,
200
);
ImageUtil
.
saveImage
(
cannyImg
,
"C:\\Users\\11419\\Desktop\\test\\3.jpg"
);
// 4.膨胀,连接边缘
// 4.膨胀,连接边缘
Mat
dilateImg
=
cannyImg
.
clone
();
Mat
dilateImg
=
cannyImg
.
clone
();
Imgproc
.
dilate
(
cannyImg
,
dilateImg
,
new
Mat
(),
new
Point
(-
1
,
-
1
),
2
,
1
,
new
Scalar
(
1
));
Imgproc
.
dilate
(
cannyImg
,
dilateImg
,
new
Mat
(),
new
Point
(-
1
,
-
1
),
3
,
1
,
new
Scalar
(
1
));
// ImageUtil.saveImage(dilateImg, "C:\\Users\\11419\\Desktop\\project\\company\\test\\guoc\\4.jpg");
ImageUtil
.
saveImage
(
dilateImg
,
"C:\\Users\\11419\\Desktop\\test\\4.jpg"
);
//5.对边缘检测的结果图再进行轮廓提取
//5.对边缘检测的结果图再进行轮廓提取
List
<
MatOfPoint
>
contours
=
new
ArrayList
<>();
List
<
MatOfPoint
>
contours
=
new
ArrayList
<>();
List
<
MatOfPoint
>
drawContours
=
new
ArrayList
<>();
List
<
MatOfPoint
>
drawContours
=
new
ArrayList
<>();
...
@@ -64,8 +62,7 @@ public class RemoveBlackUtil {
...
@@ -64,8 +62,7 @@ public class RemoveBlackUtil {
MatOfPoint2f
approx
=
new
MatOfPoint2f
();
MatOfPoint2f
approx
=
new
MatOfPoint2f
();
approx
.
convertTo
(
approx
,
CvType
.
CV_32F
);
approx
.
convertTo
(
approx
,
CvType
.
CV_32F
);
for
(
int
i
=
0
;
i
<
contours
.
size
();
i
++)
{
for
(
MatOfPoint
contour
:
contours
)
{
MatOfPoint
contour
=
contours
.
get
(
i
);
// 边框的凸包
// 边框的凸包
Imgproc
.
convexHull
(
contour
,
hull
);
Imgproc
.
convexHull
(
contour
,
hull
);
// 用凸包计算出新的轮廓点
// 用凸包计算出新的轮廓点
...
@@ -78,7 +75,7 @@ public class RemoveBlackUtil {
...
@@ -78,7 +75,7 @@ public class RemoveBlackUtil {
MatOfPoint2f
contourHull
=
new
MatOfPoint2f
();
MatOfPoint2f
contourHull
=
new
MatOfPoint2f
();
contourHull
.
fromList
(
newPoints
);
contourHull
.
fromList
(
newPoints
);
// 多边形拟合凸包边框(此时的拟合的精度较低)
// 多边形拟合凸包边框(此时的拟合的精度较低)
Imgproc
.
approxPolyDP
(
contourHull
,
approx
,
Imgproc
.
arcLength
(
contourHull
,
true
)
*
0.02
,
true
);
Imgproc
.
approxPolyDP
(
contourHull
,
approx
,
Imgproc
.
arcLength
(
contourHull
,
true
)
*
0.02
,
true
);
MatOfPoint
mat
=
new
MatOfPoint
();
MatOfPoint
mat
=
new
MatOfPoint
();
mat
.
fromArray
(
approx
.
toArray
());
mat
.
fromArray
(
approx
.
toArray
());
drawContours
.
add
(
mat
);
drawContours
.
add
(
mat
);
...
@@ -89,7 +86,7 @@ public class RemoveBlackUtil {
...
@@ -89,7 +86,7 @@ public class RemoveBlackUtil {
Imgproc
.
isContourConvex
(
approxf1
))
{
Imgproc
.
isContourConvex
(
approxf1
))
{
double
maxCosine
=
0
;
double
maxCosine
=
0
;
for
(
int
j
=
2
;
j
<
5
;
j
++)
{
for
(
int
j
=
2
;
j
<
5
;
j
++)
{
double
cosine
=
Math
.
abs
(
getAngle
(
approxf1
.
toArray
()[
j
%
4
],
approxf1
.
toArray
()[
j
-
2
],
approxf1
.
toArray
()[
j
-
1
]));
double
cosine
=
Math
.
abs
(
getAngle
(
approxf1
.
toArray
()[
j
%
4
],
approxf1
.
toArray
()[
j
-
2
],
approxf1
.
toArray
()[
j
-
1
]));
maxCosine
=
Math
.
max
(
maxCosine
,
cosine
);
maxCosine
=
Math
.
max
(
maxCosine
,
cosine
);
}
}
// 角度大概72度
// 角度大概72度
...
@@ -103,38 +100,35 @@ public class RemoveBlackUtil {
...
@@ -103,38 +100,35 @@ public class RemoveBlackUtil {
}
}
//这里是把提取出来的轮廓通过不同颜色的线描述出来,具体效果可以自己去看
//这里是把提取出来的轮廓通过不同颜色的线描述出来,具体效果可以自己去看
Random
r
=
new
Random
();
Random
r
=
new
Random
();
//
for (int i = 0; i < drawContours.size(); i++) {
for
(
int
i
=
0
;
i
<
drawContours
.
size
();
i
++)
{
//
Imgproc.drawContours(linePic, drawContours, i, new Scalar(r.nextInt(255),r.nextInt(255), r.nextInt(255)));
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");
ImageUtil
.
saveImage
(
linePic
,
"C:\\Users\\11419\\Desktop\\test
\\5.jpg"
);
//7.找出最大的矩形
//7.找出最大的矩形
int
index
=
findLargestSquare
(
squares
);
int
index
=
findLargestSquare
(
squares
);
MatOfPoint
largest_square
=
null
;
MatOfPoint
largest_square
;
if
(
squares
!=
null
&&
squares
.
size
()
>
0
){
if
(
squares
.
size
()
>
0
){
largest_square
=
squares
.
get
(
index
);
largest_square
=
squares
.
get
(
index
);
}
else
{
}
else
{
System
.
out
.
println
(
"图片无法识别"
);
System
.
out
.
println
(
"图片无法识别"
);
return
;
return
;
}
}
Mat
polyPic
=
Mat
.
zeros
(
img
.
size
(),
CvType
.
CV_8UC3
);
Mat
polyPic
=
Mat
.
zeros
(
img
.
size
(),
CvType
.
CV_8UC3
);
//
Imgproc.drawContours(polyPic, squares, index, new Scalar(0, 0,255), 2);
Imgproc
.
drawContours
(
polyPic
,
squares
,
index
,
new
Scalar
(
0
,
0
,
255
),
2
);
// ImageUtil.saveImage(polyPic, "C:\\Users\\11419\\Desktop\\project\\company\\test\\guoc
\\6.jpg");
ImageUtil
.
saveImage
(
polyPic
,
"C:\\Users\\11419\\Desktop\\test
\\6.jpg"
);
//存储矩形的四个凸点
//存储矩形的四个凸点
hull
=
new
MatOfInt
();
hull
=
new
MatOfInt
();
Imgproc
.
convexHull
(
largest_square
,
hull
,
false
);
Imgproc
.
convexHull
(
largest_square
,
hull
,
false
);
List
<
Integer
>
hullList
=
hull
.
toList
();
List
<
Integer
>
hullList
=
hull
.
toList
();
List
<
Point
>
polyContoursList
=
largest_square
.
toList
();
List
<
Point
>
polyContoursList
=
largest_square
.
toList
();
List
<
Point
>
hullPointList
=
new
ArrayList
<>();
List
<
Point
>
hullPointList
=
new
ArrayList
<>();
List
<
Point
>
lastHullPointList
=
new
ArrayList
<>();
for
(
Integer
integer
:
hullList
)
{
for
(
int
i
=
0
;
i
<
hullList
.
size
();
i
++){
Imgproc
.
circle
(
polyPic
,
polyContoursList
.
get
(
integer
),
10
,
new
Scalar
(
r
.
nextInt
(
255
),
r
.
nextInt
(
255
),
r
.
nextInt
(
255
),
3
));
Imgproc
.
circle
(
polyPic
,
polyContoursList
.
get
(
hullList
.
get
(
i
)),
10
,
new
Scalar
(
r
.
nextInt
(
255
),
r
.
nextInt
(
255
),
r
.
nextInt
(
255
),
3
));
hullPointList
.
add
(
polyContoursList
.
get
(
integer
));
hullPointList
.
add
(
polyContoursList
.
get
(
hullList
.
get
(
i
)));
}
}
Core
.
addWeighted
(
polyPic
,
1
,
img
,
1
,
0
,
img
);
Core
.
addWeighted
(
polyPic
,
1
,
img
,
1
,
0
,
img
);
// ImageUtil.saveImage(img, "C:\\Users\\11419\\Desktop\\project\\company\\test\\guoc\\7.jpg");
ImageUtil
.
saveImage
(
img
,
"C:\\Users\\11419\\Desktop\\test\\7.jpg"
);
for
(
int
i
=
0
;
i
<
hullPointList
.
size
();
i
++){
List
<
Point
>
lastHullPointList
=
new
ArrayList
<>(
hullPointList
);
lastHullPointList
.
add
(
hullPointList
.
get
(
i
));
}
//dstPoints储存的是变换后各点的坐标,依次为左上,右上,右下, 左下
//dstPoints储存的是变换后各点的坐标,依次为左上,右上,右下, 左下
//srcPoints储存的是上面得到的四个角的坐标
//srcPoints储存的是上面得到的四个角的坐标
Point
[]
dstPoints
=
{
new
Point
(
0
,
0
),
new
Point
(
img
.
cols
(),
0
),
new
Point
(
img
.
cols
(),
img
.
rows
()),
new
Point
(
0
,
img
.
rows
())};
Point
[]
dstPoints
=
{
new
Point
(
0
,
0
),
new
Point
(
img
.
cols
(),
0
),
new
Point
(
img
.
cols
(),
img
.
rows
()),
new
Point
(
0
,
img
.
rows
())};
...
...
imgproc-server/src/main/java/com/zq/imgproc/utils/RemoveBlackUtil2.java
View file @
a9ca035e
...
@@ -18,7 +18,7 @@ public class RemoveBlackUtil2 {
...
@@ -18,7 +18,7 @@ public class RemoveBlackUtil2 {
/**
/**
* 去黑边"全黑"阈值
* 去黑边"全黑"阈值
*/
*/
private
static
final
Integer
BLACK_VALUE
=
2
00
;
private
static
final
Integer
BLACK_VALUE
=
1
00
;
public
static
void
remove
(
String
src
,
String
dst
)
{
public
static
void
remove
(
String
src
,
String
dst
)
{
Mat
mat
=
Imgcodecs
.
imread
(
src
);
Mat
mat
=
Imgcodecs
.
imread
(
src
);
...
...
imgproc-server/src/main/java/com/zq/imgproc/utils/Test2.java
0 → 100644
View file @
a9ca035e
package
com
.
zq
.
imgproc
.
utils
;
import
org.opencv.core.Core
;
import
org.opencv.core.CvType
;
import
org.opencv.core.Mat
;
import
org.opencv.imgcodecs.Imgcodecs
;
import
org.opencv.imgproc.Imgproc
;
import
java.io.IOException
;
/**
* <p>
*
* </p>
*
* @author chenhao
* @since 2023/11/20
*/
public
class
Test2
{
public
static
void
main
(
String
[]
args
)
throws
IOException
{
System
.
load
(
"D:\\project\\imgproc\\lib\\opencv_java460.dll"
);
String
src
=
"C:\\Users\\11419\\Desktop\\Deskew\\TestImages\\6.png"
;
String
dst
=
"C:\\Users\\11419\\Desktop\\Deskew\\TestImages\\6res.png"
;
// 读取输入图像
Mat
inputImage
=
Imgcodecs
.
imread
(
src
);
// 将图像转换为灰度图像
Mat
grayImage
=
new
Mat
();
Imgproc
.
cvtColor
(
inputImage
,
grayImage
,
Imgproc
.
COLOR_BGR2GRAY
);
// 对灰度图像进行高斯模糊处理
Mat
blurredImage
=
new
Mat
();
Imgproc
.
GaussianBlur
(
grayImage
,
blurredImage
,
new
org
.
opencv
.
core
.
Size
(
3
,
3
),
0
);
// 使用拉普拉斯算子进行边缘检测
Mat
laplacianImage
=
new
Mat
();
Imgproc
.
Laplacian
(
blurredImage
,
laplacianImage
,
CvType
.
CV_16S
,
3
,
1
,
0
,
Core
.
BORDER_DEFAULT
);
Core
.
convertScaleAbs
(
laplacianImage
,
laplacianImage
);
// 对滤波后的图像进行阈值处理,找到孤立点
double
threshold
=
30.0
;
Mat
binaryImage
=
new
Mat
();
Imgproc
.
threshold
(
laplacianImage
,
binaryImage
,
threshold
,
255
,
Imgproc
.
THRESH_BINARY
);
// 计算检测到的孤立点数量
int
isolatedPointCount
=
Core
.
countNonZero
(
binaryImage
);
// 输出孤立点数量
System
.
out
.
println
(
"检测到的孤立点数量:"
+
isolatedPointCount
);
// 可以在结果图像上标记检测到的孤立点,或者保存结果图像以便查看
Imgcodecs
.
imwrite
(
dst
,
binaryImage
);
}
}
imgproc-server/src/main/java/com/zq/imgproc/utils/TestUtil.java
View file @
a9ca035e
package
com
.
zq
.
imgproc
.
utils
;
package
com
.
zq
.
imgproc
.
utils
;
import
cn.hutool.core.convert.Convert
;
import
cn.hutool.core.convert.Convert
;
import
cn.hutool.core.io.FileUtil
;
import
com.drew.imaging.ImageMetadataReader
;
import
com.drew.metadata.Directory
;
import
com.drew.metadata.Metadata
;
import
com.drew.metadata.Tag
;
import
com.zq.imgproc.vo.DetectionResVo3
;
import
lombok.extern.slf4j.Slf4j
;
import
lombok.extern.slf4j.Slf4j
;
import
org.opencv.core.*
;
import
org.apache.commons.imaging.ImageInfo
;
import
org.apache.commons.imaging.Imaging
;
import
org.opencv.core.Mat
;
import
org.opencv.imgcodecs.Imgcodecs
;
import
org.opencv.imgcodecs.Imgcodecs
;
import
org.opencv.imgproc.Imgproc
;
import
java.util.ArrayList
;
import
java.io.File
;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.Map
;
import
static
org
.
opencv
.
highgui
.
HighGui
.
imshow
;
import
static
org
.
opencv
.
highgui
.
HighGui
.
waitKey
;
@Slf4j
@Slf4j
public
class
TestUtil
{
public
class
TestUtil
{
public
static
void
main
(
String
[]
args
)
{
public
static
void
main
(
String
[]
args
)
throws
Exception
{
System
.
load
(
"C:/Users/11419/Desktop/lib/opencv_java460.dll"
);
System
.
load
(
"D:/project/imgproc/lib/opencv_java460.dll"
);
Mat
image
=
Imgcodecs
.
imread
(
"C:/Users/11419/Desktop/Deskew/TestImages/res.png"
);
String
src
=
"C:\\Users\\11419\\Desktop\\4.png"
;
String
dst
=
"C:\\Users\\11419\\Desktop\\res.png"
;
// 转换为灰度图像
// deskew(src, dst);
Mat
grayImage
=
new
Mat
();
RemoveBlackUtil2
.
remove
(
src
,
dst
);
Imgproc
.
cvtColor
(
image
,
grayImage
,
Imgproc
.
COLOR_BGR2GRAY
);
// bright(src, dst);
// im(src, dst);
// 创建一个掩码,初始化为全黑
}
Mat
mask
=
Mat
.
zeros
(
new
Size
(
grayImage
.
cols
()
+
2
,
grayImage
.
rows
()
+
2
),
CvType
.
CV_8U
);
// 执行漫水填充算法
Imgproc
.
floodFill
(
grayImage
,
mask
,
new
org
.
opencv
.
core
.
Point
(
0
,
0
),
new
Scalar
(
255
),
null
,
new
Scalar
(
5
,
5
,
5
,
5
),
new
Scalar
(
5
,
5
,
5
,
5
));
// 进行二值化处理
Mat
binaryImage
=
new
Mat
();
Imgproc
.
threshold
(
grayImage
,
binaryImage
,
1
,
255
,
Imgproc
.
THRESH_BINARY
);
// 创建一个与二值化图像大小相同的全白图像
Mat
filledImage
=
Mat
.
zeros
(
binaryImage
.
size
(),
CvType
.
CV_8U
);
filledImage
.
setTo
(
new
Scalar
(
255
));
// 将非黑色区域从二值化图像复制到全白图像中
binaryImage
.
copyTo
(
filledImage
,
binaryImage
);
imshow
(
"test"
,
binaryImage
);
public
static
void
deskew
(
String
src
,
String
dst
)
{
waitKey
();
Mat
mat
=
Imgcodecs
.
imread
(
src
);
double
skewAngle
=
Deskew
.
getDeskewAngle
(
mat
);
Mat
rotateMat
=
Deskew
.
rotate
(
mat
,
skewAngle
);
Imgcodecs
.
imwrite
(
dst
,
rotateMat
);
}
public
static
void
removeBlack
(
String
src
,
String
dst
)
{
RemoveBlackUtil2
.
remove
(
src
,
dst
);
}
}
private
static
void
test
()
{
public
static
void
bright
(
String
src
,
String
dst
)
{
String
testImg
=
"C:/Users/11419/Desktop/Deskew/TestImages/4.png"
;
double
brightness
=
ImageUtil
.
brightness
(
src
);
String
resImg
=
"C:/Users/11419/Desktop/Deskew/TestImages/res.png"
;
System
.
out
.
println
(
brightness
);
long
start
=
System
.
currentTimeMillis
();
// 亮度异常执行亮度矫正
Mat
src
=
Imgcodecs
.
imread
(
testImg
);
if
(
brightness
<
100
||
brightness
>
500
)
{
// 图片灰度化
// 计算亮度调整值
Mat
gray
=
src
.
clone
();
double
alpha
=
300
/
brightness
;
Imgproc
.
cvtColor
(
src
,
gray
,
Imgproc
.
COLOR_BGR2GRAY
);
// 执行亮度调整
Mat
grayImage
=
Imgcodecs
.
imread
(
src
);
Mat
adjustedImage
=
new
Mat
();
grayImage
.
convertTo
(
adjustedImage
,
-
1
,
alpha
,
0
);
// 保存调整后的图像
Imgcodecs
.
imwrite
(
dst
,
adjustedImage
);
}
}
// // 高斯模糊(?)
public
static
void
im
(
String
src
,
String
dst
)
{
// @Cleanup
double
laplacianScore
=
ImageUtil
.
imageSharpnessDetector
(
src
);
// UMat blur = gray.clone();
System
.
out
.
println
(
laplacianScore
);
// GaussianBlur(gray, blur, new Size(9, 9), 0);
if
(
laplacianScore
<
500
)
{
// // 二值化(?)
Mat
unsharpMaskingMat
=
ImageUtil
.
unsharpMasking
(
src
);
// @Cleanup
// 保存调整后的图像
// UMat thresh = blur.clone();
Imgcodecs
.
imwrite
(
dst
,
unsharpMaskingMat
);
// threshold(blur, thresh, 0, 255, THRESH_BINARY_INV + THRESH_OTSU);
}
}
Mat
kernel
=
Imgproc
.
getStructuringElement
(
Imgproc
.
MORPH_RECT
,
new
Size
(
5
,
5
));
public
static
DetectionResVo3
detection
(
String
src
)
throws
Exception
{
// 图片膨胀
DetectionResVo3
res
=
new
DetectionResVo3
();
Mat
erode
=
gray
.
clone
();
Mat
image
=
Imgcodecs
.
imread
(
src
);
Imgproc
.
erode
(
gray
,
erode
,
kernel
);
// 检测图片的分辨率
// 图片腐蚀
res
.
setWidthResolution
(
image
.
width
());
Mat
dilate
=
erode
.
clone
();
res
.
setHeightResolution
(
image
.
height
());
Imgproc
.
dilate
(
erode
,
dilate
,
kernel
);
// 检测图片的DPI
// 边缘检测
res
.
setDpi
(
getDpi
(
FileUtil
.
file
(
src
)));
Mat
canny
=
dilate
.
clone
();
// 检测图片清晰度
Imgproc
.
Canny
(
dilate
,
canny
,
50
,
150
);
res
.
setClarity
(
ImageUtil
.
imageSharpnessDetector
(
image
));
// 霍夫变换得到线条
// 检测图片的亮度
Mat
lines
=
new
Mat
();
res
.
setBrightness
(
ImageUtil
.
brightness
(
image
));
//累加器阈值参数,小于设置值不返回
// 检测图片倾斜角度
int
threshold
=
90
;
res
.
setAngle
(
Deskew
.
getDeskewAngle
(
image
));
//最低线段长度,低于设置值则不返回
// 检测图片的黑边
double
minLineLength
=
100
;
res
.
setBlack
(
blackDetection
(
image
));
//间距小于该值的线当成同一条线
return
res
;
double
maxLineGap
=
10
;
// 霍夫变换,通过步长为1,角度为PI/180来搜索可能的直线
Imgproc
.
HoughLinesP
(
canny
,
lines
,
1
,
Math
.
PI
/
180
,
threshold
,
minLineLength
,
maxLineGap
);
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.0;
// }
// 可能还得需要考虑方差来决定选择平均数还是众数
int
angle
=
most
(
angelList
);
Mat
rotated
=
rotate
(
src
,
angle
,
1.0
);
gray
.
release
();
kernel
.
release
();
erode
.
release
();
dilate
.
release
();
lines
.
release
();
canny
.
release
();
}
}
/**
/**
*
求数组众数
*
获取图片DPI
*
*
* @param
angelList 数组
* @param
file 图片文件
* @return
数组众数
* @return
[水平DPI,垂直DPI]
*/
*/
private
static
int
most
(
List
<
Integer
>
angelList
)
{
private
static
Integer
getDpi
(
File
file
)
throws
Exception
{
if
(
angelList
.
isEmpty
())
{
int
res
;
return
0
;
ImageInfo
imageInfo
=
Imaging
.
getImageInfo
(
file
);
res
=
imageInfo
.
getPhysicalWidthDpi
();
if
(
res
==
-
1
)
{
Metadata
metadata
=
ImageMetadataReader
.
readMetadata
(
file
);
for
(
Directory
directory
:
metadata
.
getDirectories
())
{
for
(
Tag
tag
:
directory
.
getTags
())
{
if
(
"X Resolution"
.
equals
(
tag
.
getTagName
()))
{
res
=
Convert
.
toInt
(
tag
.
getDescription
());
}
}
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
;
return
res
;
}
}
/**
/**
* 计算直线的倾斜角
* 黑边像素阈值
*/
private
static
final
Integer
THRESHOLD
=
30
;
/**
* 黑边检测
*
* @param src 图片矩阵
* @return true表示可能存在黑边
*/
*/
private
static
int
calculateAngle
(
double
x1
,
double
y1
,
double
x2
,
double
y2
)
{
public
static
boolean
blackDetection
(
Mat
src
)
{
double
dx
=
x2
-
x1
;
int
width
=
src
.
width
();
double
dy
=
y2
-
y1
;
int
height
=
src
.
height
();
if
(
Math
.
abs
(
dx
)
<
1
e
-
4
)
{
// 定义初始边界
return
90
;
int
top
=
0
;
}
else
if
(
Math
.
abs
(
dy
)
<
1
e
-
4
)
{
int
left
=
0
;
return
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
{
}
else
{
double
radians
=
Math
.
atan2
(
dy
,
dx
);
break
;
double
degrees
=
Math
.
toDegrees
(
radians
);
return
Convert
.
toInt
(
Math
.
round
(
degrees
));
}
}
}
}
// 左边黑边判断
public
static
Mat
rotate
(
Mat
image
,
double
angle
,
double
scale
)
{
for
(
int
col
=
0
;
col
<
width
;
col
++)
{
int
w
=
image
.
cols
();
if
(
ImageUtil
.
sum
(
src
.
col
(
col
))
/
height
<
THRESHOLD
)
{
int
h
=
image
.
rows
();
left
=
col
;
}
else
{
Point
center
=
new
Point
((
double
)
w
/
2
,
(
double
)
h
/
2
);
break
;
}
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
);
imshow
(
"test"
,
rotatedImage
);
waitKey
();
return
rotatedImage
;
}
}
// 右边黑边判断
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
;
}
}
}
imgproc-server/src/main/java/com/zq/imgproc/vo/DetectionDTO.java
0 → 100644
View file @
a9ca035e
package
com
.
zq
.
imgproc
.
vo
;
import
com.alibaba.excel.annotation.ExcelIgnore
;
import
com.alibaba.excel.annotation.ExcelProperty
;
import
io.swagger.annotations.ApiModelProperty
;
import
lombok.Data
;
import
lombok.EqualsAndHashCode
;
/**
* <p>
*
* </p>
*
* @author chenhao
* @since 2023/11/24
*/
@Data
@EqualsAndHashCode
public
class
DetectionDTO
{
@ExcelProperty
(
"文件名称"
)
private
String
filename
;
@ExcelProperty
(
"分辨率"
)
private
String
resolution
;
@ExcelProperty
(
"DPI"
)
private
Integer
dpi
;
@ExcelProperty
(
"平均亮度值"
)
private
double
brightness
;
@ExcelProperty
(
"清晰度值"
)
private
double
clarity
;
@ExcelProperty
(
"倾斜角度"
)
private
double
angle
;
@ExcelProperty
(
"黑边情况"
)
private
String
black
;
}
imgproc-server/src/main/java/com/zq/imgproc/vo/DetectionResVo2.java
View file @
a9ca035e
...
@@ -27,11 +27,8 @@ public class DetectionResVo2 {
...
@@ -27,11 +27,8 @@ public class DetectionResVo2 {
@ApiModelProperty
(
"图片的DPI"
)
@ApiModelProperty
(
"图片的DPI"
)
private
Integer
dpi
;
private
Integer
dpi
;
@ApiModelProperty
(
"亮度值"
)
@ApiModelProperty
(
"平均亮度值"
)
private
double
cast
;
private
double
brightness
;
@ApiModelProperty
(
"亮度异常值"
)
private
double
da
;
@ApiModelProperty
(
"图片的清晰度指标,值越大越清晰"
)
@ApiModelProperty
(
"图片的清晰度指标,值越大越清晰"
)
private
double
clarity
;
private
double
clarity
;
...
...
imgproc-server/src/main/java/com/zq/imgproc/vo/SettingVO.java
View file @
a9ca035e
...
@@ -20,11 +20,11 @@ import lombok.NoArgsConstructor;
...
@@ -20,11 +20,11 @@ import lombok.NoArgsConstructor;
@Builder
@Builder
public
class
SettingVO
{
public
class
SettingVO
{
@ApiModelProperty
(
"亮度值"
)
@ApiModelProperty
(
"亮度值
起始范围
"
)
private
double
cast
;
private
double
startValue
;
@ApiModelProperty
(
"亮度
异常值
"
)
@ApiModelProperty
(
"亮度
值结束范围
"
)
private
double
da
;
private
double
endValue
;
@ApiModelProperty
(
"图片的清晰度指标,值越大越清晰"
)
@ApiModelProperty
(
"图片的清晰度指标,值越大越清晰"
)
private
double
clarity
;
private
double
clarity
;
...
...
imgproc-server/src/main/resources/application.yml
View file @
a9ca035e
...
@@ -18,12 +18,12 @@ spring:
...
@@ -18,12 +18,12 @@ spring:
ip
:
ip
:
local-parsing
:
true
local-parsing
:
true
#imgconfig:
# opencv: /opt/services/tianjin-backend/lib/opencv_java460.so
# deskew: /opt/services/tianjin-backend/lib/Deskew/Bin/deskew
# deskewpy: /opt/tianjin/lib/correct.py
imgconfig
:
imgconfig
:
opencv
:
D:/project/imgproc/lib/opencv_java460.dll
opencv
:
/opt/tianjin/lib/opencv_java460.so
deskew
:
C:/Users/11419/Desktop/Deskew/Bin/deskew.exe
deskew
:
/opt/tianjin/lib/Deskew/Bin/deskew
deskewpy
:
D:/project/imgproc/lib/correct.py
deskewpy
:
/opt/tianjin/lib/correct.py
#imgconfig:
# opencv: D:/project/imgproc/lib/opencv_java460.dll
# deskew: C:/Users/11419/Desktop/Deskew/Bin/deskew.exe
# deskewpy: D:/project/imgproc/lib/correct.py
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment