Browse Source

feat:根据图片名称查询当前同级目录下的images文件夹内的图片进行车牌识别

根据相机ffmpeg所需的ip进行取流抽帧,进行车牌识别。
master
温小超 4 months ago
parent
commit
bb5893a3cc
  1. 30
      open-anpr-client/pom.xml
  2. 47
      open-anpr-client/src/main/java/com/visual/open/anpr/PlateRecognition.java
  3. 12
      open-anpr-client/src/main/java/com/visual/open/anpr/common/Api.java
  4. 63
      open-anpr-client/src/main/java/com/visual/open/anpr/handle/RecognitionHandler.java
  5. 207
      open-anpr-client/src/main/java/com/visual/open/anpr/http/HttpClient.java
  6. 4
      open-anpr-client/src/main/java/com/visual/open/anpr/http/HttpClientResult.java
  7. 455
      open-anpr-client/src/main/java/com/visual/open/anpr/http/HttpClientUtils.java
  8. 34
      open-anpr-client/src/main/java/com/visual/open/anpr/model/LocationPoint.java
  9. 17
      open-anpr-client/src/main/java/com/visual/open/anpr/model/MapParam.java
  10. 31
      open-anpr-client/src/main/java/com/visual/open/anpr/model/PlateColor.java
  11. 8
      open-anpr-client/src/main/java/com/visual/open/anpr/model/PlateLayout.java
  12. 96
      open-anpr-client/src/main/java/com/visual/open/anpr/model/PlateLocation.java
  13. 40
      open-anpr-client/src/main/java/com/visual/open/anpr/model/Recognition.java
  14. 36
      open-anpr-client/src/main/java/com/visual/open/anpr/model/RecognitionInfo.java
  15. 40
      open-anpr-client/src/main/java/com/visual/open/anpr/model/RecognitionRep.java
  16. 13
      open-anpr-client/src/main/java/com/visual/open/anpr/model/RecognitionReq.java
  17. 62
      open-anpr-client/src/main/java/com/visual/open/anpr/model/Response.java
  18. 48
      open-anpr-client/src/main/java/com/visual/open/anpr/utils/Base64Util.java
  19. 40
      open-anpr-core/pom.xml
  20. 10
      open-anpr-core/src/main/java/com/visual/open/anpr/core/base/PlateRecognition.java
  21. 131
      open-anpr-core/src/main/java/com/visual/open/anpr/core/domain/DrawImage.java
  22. 128
      open-anpr-core/src/main/java/com/visual/open/anpr/core/utils/JsonUtil.java
  23. 28
      open-anpr-core/src/test/java/com/visual/open/anpr/core/base/BaseTest.java
  24. 77
      open-anpr-core/src/test/java/com/visual/open/anpr/core/extract/PlateExtractorTest.java
  25. 42
      open-anpr-core/src/test/java/com/visual/open/anpr/core/models/TorchPlateDetectionTest.java
  26. 28
      open-anpr-core/src/test/java/com/visual/open/anpr/core/models/TorchPlateRecognitionTest.java
  27. BIN
      open-anpr-core/src/test/resources/images/image001.jpg
  28. BIN
      open-anpr-core/src/test/resources/images/image002.jpg
  29. BIN
      open-anpr-core/src/test/resources/images/image003.jpg
  30. BIN
      open-anpr-core/src/test/resources/images/image004.jpg
  31. BIN
      open-anpr-core/src/test/resources/images/image005.jpg
  32. BIN
      open-anpr-core/src/test/resources/images/image006.jpg
  33. BIN
      open-anpr-core/src/test/resources/images/image007.png
  34. BIN
      open-anpr-core/src/test/resources/images/image008.png
  35. BIN
      open-anpr-core/src/test/resources/images/image009.jpg
  36. BIN
      open-anpr-core/src/test/resources/images/image010.jpg
  37. BIN
      open-anpr-core/src/test/resources/images/image011.jpg
  38. BIN
      open-anpr-core/src/test/resources/images/image012.jpg
  39. BIN
      open-anpr-core/src/test/resources/images/image013.jpg
  40. BIN
      open-anpr-core/src/test/resources/images/image014.png
  41. BIN
      open-anpr-core/src/test/resources/images/image015.jpg
  42. 125
      open-anpr-server/pom.xml
  43. 4
      open-anpr-server/src/main/java/com/visual/open/anpr/server/base/BaseOnnxInfer.java
  44. 2
      open-anpr-server/src/main/java/com/visual/open/anpr/server/base/OpenCVLoader.java
  45. 6
      open-anpr-server/src/main/java/com/visual/open/anpr/server/base/PlateDetection.java
  46. 11
      open-anpr-server/src/main/java/com/visual/open/anpr/server/base/PlateRecognition.java
  47. 5
      open-anpr-server/src/main/java/com/visual/open/anpr/server/bootstrap/OpenAnprApplication.java
  48. 80
      open-anpr-server/src/main/java/com/visual/open/anpr/server/bootstrap/conf/ModelConfig.java
  49. 36
      open-anpr-server/src/main/java/com/visual/open/anpr/server/controller/server/restful/PlateController.java
  50. 2
      open-anpr-server/src/main/java/com/visual/open/anpr/server/domain/BorderMat.java
  51. 2
      open-anpr-server/src/main/java/com/visual/open/anpr/server/domain/DrawImage.java
  52. 2
      open-anpr-server/src/main/java/com/visual/open/anpr/server/domain/ExtParam.java
  53. 4
      open-anpr-server/src/main/java/com/visual/open/anpr/server/domain/ImageMat.java
  54. 2
      open-anpr-server/src/main/java/com/visual/open/anpr/server/domain/PlateImage.java
  55. 2
      open-anpr-server/src/main/java/com/visual/open/anpr/server/domain/PlateInfo.java
  56. 9
      open-anpr-server/src/main/java/com/visual/open/anpr/server/extract/PlateExtractor.java
  57. 16
      open-anpr-server/src/main/java/com/visual/open/anpr/server/extract/PlateExtractorImpl.java
  58. 19
      open-anpr-server/src/main/java/com/visual/open/anpr/server/models/TorchPlateDetection.java
  59. 19
      open-anpr-server/src/main/java/com/visual/open/anpr/server/models/TorchPlateRecognition.java
  60. 7
      open-anpr-server/src/main/java/com/visual/open/anpr/server/service/impl/PlateServiceImpl.java
  61. 2
      open-anpr-server/src/main/java/com/visual/open/anpr/server/utils/AlignUtil.java
  62. 2
      open-anpr-server/src/main/java/com/visual/open/anpr/server/utils/ArrayUtil.java
  63. 4
      open-anpr-server/src/main/java/com/visual/open/anpr/server/utils/CropUtil.java
  64. 324
      open-anpr-server/src/main/java/com/visual/open/anpr/server/utils/FfmpegUtil.java
  65. 173
      open-anpr-server/src/main/java/com/visual/open/anpr/server/utils/FileCopyUtil.java
  66. 140
      open-anpr-server/src/main/java/com/visual/open/anpr/server/utils/FreeMarkerUtil.java
  67. 82
      open-anpr-server/src/main/java/com/visual/open/anpr/server/utils/ImageUtil.java
  68. 2
      open-anpr-server/src/main/java/com/visual/open/anpr/server/utils/JsonUtil.java
  69. 2
      open-anpr-server/src/main/java/com/visual/open/anpr/server/utils/MatUtil.java
  70. 2
      open-anpr-server/src/main/java/com/visual/open/anpr/server/utils/MathUtil.java
  71. 6
      open-anpr-server/src/main/java/com/visual/open/anpr/server/utils/ReleaseUtil.java
  72. 2
      open-anpr-server/src/main/java/com/visual/open/anpr/server/utils/SigmoidUtil.java
  73. 4
      open-anpr-server/src/main/java/com/visual/open/anpr/server/utils/Similarity.java
  74. 2
      open-anpr-server/src/main/java/com/visual/open/anpr/server/utils/SoftMaxUtil.java
  75. 2
      open-anpr-server/src/main/java/com/visual/open/anpr/server/utils/ThreadUtil.java
  76. 170
      open-anpr-server/src/main/java/com/visual/open/anpr/server/utils/VideoUtil.java
  77. 2
      open-anpr-server/src/main/resources/application-local.yml
  78. 0
      open-anpr-server/src/main/resources/models/plate_detect.onnx
  79. 0
      open-anpr-server/src/main/resources/models/plate_rec_color.onnx
  80. 32
      open-anpr-test/pom.xml
  81. 84
      open-anpr-test/src/main/java/com/visual/open/anpr/exps/PlateRecognitionExample.java
  82. 107
      open-anpr-test/src/main/java/com/visual/open/anpr/utils/MatUtil.java
  83. BIN
      open-anpr-test/src/main/resources/image/image001.jpg
  84. BIN
      open-anpr-test/src/main/resources/image/image002.jpg
  85. BIN
      open-anpr-test/src/main/resources/image/image003.jpg
  86. BIN
      open-anpr-test/src/main/resources/image/image004.jpg
  87. BIN
      open-anpr-test/src/main/resources/image/image005.jpg
  88. BIN
      open-anpr-test/src/main/resources/image/image006.jpg
  89. BIN
      open-anpr-test/src/main/resources/image/image007.png
  90. BIN
      open-anpr-test/src/main/resources/image/image008.png
  91. BIN
      open-anpr-test/src/main/resources/image/image009.jpg
  92. BIN
      open-anpr-test/src/main/resources/image/image010.jpg
  93. BIN
      open-anpr-test/src/main/resources/image/image011.jpg
  94. BIN
      open-anpr-test/src/main/resources/image/image012.jpg
  95. BIN
      open-anpr-test/src/main/resources/image/image013.jpg
  96. BIN
      open-anpr-test/src/main/resources/image/image014.png
  97. BIN
      open-anpr-test/src/main/resources/image1/75a6f232_7346047.jpeg
  98. BIN
      open-anpr-test/src/main/resources/image1/c4145e27_7346047.jpeg
  99. BIN
      open-anpr-test/src/main/resources/image1/f7759908_7346047.png
  100. 3
      pom.xml

30
open-anpr-client/pom.xml

@ -1,30 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.visual.open.anpr</groupId>
<artifactId>open-anpr-client</artifactId>
<version>1.1.0</version>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.58</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5</version>
</dependency>
</dependencies>
</project>

47
open-anpr-client/src/main/java/com/visual/open/anpr/PlateRecognition.java

@ -1,47 +0,0 @@
package com.visual.open.anpr;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import com.visual.open.anpr.handle.RecognitionHandler;
public class PlateRecognition {
/**服务地址**/
private String serverHost;
/**实例对象**/
private final static Map<String, PlateRecognition> ins = new ConcurrentHashMap<>();
/**
* 构建集合对象
* @param serverHost 服务地址
* @return
*/
private PlateRecognition(String serverHost){
this.serverHost = serverHost;
}
/**
* 构建集合对象
* @param serverHost 服务地址
* @return
*/
public static PlateRecognition build (String serverHost){
String key = serverHost;
if(!ins.containsKey(key)){
synchronized (PlateRecognition.class){
if(!ins.containsKey(key)){
ins.put(key, new PlateRecognition(serverHost));
}
}
}
return ins.get(key);
}
/**
* 车牌检测操作对象
* @return CollectHandler
*/
public RecognitionHandler detection(){
return RecognitionHandler.build(serverHost);
}
}

12
open-anpr-client/src/main/java/com/visual/open/anpr/common/Api.java

@ -1,12 +0,0 @@
package com.visual.open.anpr.common;
public class Api {
public static final String plate_recognition = "/visual/plate/recognition";
public static String getUrl(String host, String uri){
host = host.replaceAll ("/+$", "");
return host + uri;
}
}

63
open-anpr-client/src/main/java/com/visual/open/anpr/handle/RecognitionHandler.java

@ -1,63 +0,0 @@
package com.visual.open.anpr.handle;
import com.alibaba.fastjson.TypeReference;
import com.visual.open.anpr.common.Api;
import com.visual.open.anpr.http.HttpClient;
import com.visual.open.anpr.model.Recognition;
import com.visual.open.anpr.model.RecognitionRep;
import com.visual.open.anpr.model.RecognitionReq;
import com.visual.open.anpr.model.Response;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class RecognitionHandler {
/**服务地址**/
protected String serverHost;
/**实例对象**/
private final static Map<String, RecognitionHandler> ins = new ConcurrentHashMap<>();
public String getServerHost() {
return serverHost;
}
public RecognitionHandler setServerHost(String serverHost) {
this.serverHost = serverHost;
return this;
}
/**
* 构建车牌检测对象
* @param serverHost 服务地址
* @return
*/
public static RecognitionHandler build(String serverHost){
String key = serverHost;
if(!ins.containsKey(key)){
synchronized (RecognitionHandler.class){
if(!ins.containsKey(key)){
ins.put(key, new RecognitionHandler().setServerHost(serverHost));
}
}
}
return ins.get(key);
}
/**
* 车牌检测
* @param recognition 待检测的数据信息
* @return 车牌检测结果
*/
public Response<List<RecognitionRep>> recognition(Recognition recognition){
RecognitionReq compareReq = RecognitionReq.build()
.setImage(recognition.getImage())
.setLimit(recognition.getLimit());
return HttpClient.post(
Api.getUrl(this.serverHost, Api.plate_recognition),
compareReq,
new TypeReference<Response<List<RecognitionRep>>>() {});
}
}

207
open-anpr-client/src/main/java/com/visual/open/anpr/http/HttpClient.java

@ -1,207 +0,0 @@
package com.visual.open.anpr.http;
import com.alibaba.fastjson.TypeReference;
import com.visual.open.anpr.model.MapParam;
import com.visual.open.anpr.model.Response;
import com.visual.open.anpr.utils.JsonUtil;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.IOException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.LinkedList;
import java.util.List;
public class HttpClient {
/**编码方式*/
private static final String ENCODING = "UTF-8";
/**连接超时时间,10秒*/
public static final int DEFAULT_CONNECT_TIMEOUT = 10 * 1000;
/**socket连接超时时间,10秒*/
public static final int DEFAULT_READ_TIMEOUT = 10 * 000;
/**请求超时时间,60秒*/
public static final int DEFAULT_CONNECT_REQUEST_TIMEOUT = 30 * 000;
/**最大连接数,默认为2*/
private static final int MAX_TOTAL = 8;
/**设置指向特定路由的并发连接总数,默认为2*/
private static final int MAX_PER_ROUTE = 4;
private static RequestConfig requestConfig;
private static PoolingHttpClientConnectionManager connectionManager;
private static BasicCookieStore cookieStore;
private static HttpClientBuilder httpBuilder;
private static CloseableHttpClient httpClient;
private static CloseableHttpClient httpsClient;
private static SSLContext sslContext;
/**
* 创建SSLContext对象用来绕过https证书认证实现访问
*/
static {
try {
sslContext = SSLContext.getInstance("TLS");
// 实现一个X509TrustManager接口,用于绕过验证,不用修改里面的方法
X509TrustManager tm = new X509TrustManager() {
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType)
throws CertificateException {
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType)
throws CertificateException {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return null;
}
};
sslContext.init(null, new TrustManager[] {tm}, null);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 初始化httpclient对象以及在创建httpclient对象之前的一些自定义配置
*/
static {
// 自定义配置信息
requestConfig = RequestConfig.custom()
.setSocketTimeout(DEFAULT_READ_TIMEOUT)
.setConnectTimeout(DEFAULT_CONNECT_TIMEOUT)
.setConnectionRequestTimeout(DEFAULT_CONNECT_REQUEST_TIMEOUT)
.build();
//设置协议http和https对应的处理socket链接工厂的对象
Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory> create()
.register("http", new PlainConnectionSocketFactory())
.register("https", new SSLConnectionSocketFactory(sslContext))
.build();
connectionManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
// 设置cookie存储对像,在需要获取cookie信息时,可以使用这个对象。
cookieStore = new BasicCookieStore();
// 设置最大连接数
connectionManager.setMaxTotal(MAX_TOTAL);
// 设置路由并发数
connectionManager.setDefaultMaxPerRoute(MAX_PER_ROUTE);
httpBuilder = HttpClientBuilder.create();
httpBuilder.setDefaultRequestConfig(requestConfig);
httpBuilder.setConnectionManager(connectionManager);
httpBuilder.setDefaultCookieStore(cookieStore);
// 实例化http 和 https的对象。
httpClient = httpBuilder.build();
httpsClient = httpBuilder.build();
}
/**
* post请求
* @param url
* @param data
* @param <T>
* @return
*/
public static <T> Response<T> post(String url, Object data) {
return post(url, data, new TypeReference<Response<T>>() {});
}
/**
* post请求
* @param url
* @param data
* @param <T>
* @return
*/
public static <T> Response<T> post(String url, Object data, TypeReference<Response<T>> type) {
// 创建HTTP对象
HttpPost httpPost = new HttpPost(url);
httpPost.setConfig(requestConfig);
httpPost.addHeader("Content-Type", "application/json;charset=UTF-8");
// 设置请求头
if(null != data){
String json = data instanceof String ? String.valueOf(data) : JsonUtil.toString(data);
StringEntity stringEntity = new StringEntity(json, ENCODING);
stringEntity.setContentEncoding(ENCODING);
httpPost.setEntity(stringEntity);
}
// 创建httpResponse对象
CloseableHttpClient client = url.toLowerCase().startsWith("https") ? httpsClient : httpClient;
try {
CloseableHttpResponse httpResponse = client.execute(httpPost);
String content = EntityUtils.toString(httpResponse.getEntity(), ENCODING);
return JsonUtil.toEntity(content, type);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
/**
* get
* @param url
* @param param
* @param <T>
* @return
*/
public static <T> Response<T> get(String url, MapParam param) {
return get(url, param, new TypeReference<Response<T>>() {});
}
/**
* get
* @param url
* @param param
* @param <T>
* @return
*/
public static <T> Response<T> get(String url, MapParam param, TypeReference<Response<T>> type) {
try {
//参数构建
URIBuilder uriBuilder = new URIBuilder(url);
if(null != param && !param.isEmpty()){
List<NameValuePair> list = new LinkedList<>();
for(String key : param.keySet()){
Object value = param.get(key);
if(null == value){
list.add(new BasicNameValuePair(key, null));
}else{
list.add(new BasicNameValuePair(key, String.valueOf(value)));
}
}
uriBuilder.setParameters(list);
}
//构建请求
HttpGet httpGet = new HttpGet(uriBuilder.build());
httpGet.setConfig(requestConfig);
httpGet.addHeader("Content-Type", "application/json;charset=UTF-8");
// 创建httpResponse对象
CloseableHttpClient client = url.toLowerCase().startsWith("https") ? httpsClient : httpClient;
CloseableHttpResponse httpResponse = client.execute(httpGet);
String content = EntityUtils.toString(httpResponse.getEntity(), ENCODING);
return JsonUtil.toEntity(content, type);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}

4
open-anpr-client/src/main/java/com/visual/open/anpr/http/HttpClientResult.java

@ -1,4 +0,0 @@
package com.visual.open.anpr.http;
public class HttpClientResult {
}

455
open-anpr-client/src/main/java/com/visual/open/anpr/http/HttpClientUtils.java

@ -1,455 +0,0 @@
package com.visual.open.anpr.http;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.*;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.cookie.Cookie;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.*;
/**
* @Description: httpclient常用方法封装,
* @Author: ggf
* @Date: 2020/06/06
*/
public class HttpClientUtils {
/**
* 编码方式
*/
private static final String ENCODING = "UTF-8";
/**
* 连接超时时间60秒
*/
public static final int DEFAULT_CONNECT_TIMEOUT = 6000;
/**
* socket连接超时时间60秒
*/
public static final int DEFAULT_READ_TIMEOUT = 6000;
/**
* 请求超时时间60秒
*/
public static final int DEFAULT_CONNECT_REQUEST_TIMEOUT = 6000;
/**
* 最大连接数,默认为2
*/
private static final int MAX_TOTAL = 64;
/**
* 设置指向特定路由的并发连接总数默认为2
*/
private static final int MAX_PER_ROUTE = 32;
private static RequestConfig requestConfig;
private static PoolingHttpClientConnectionManager connectionManager;
private static BasicCookieStore cookieStore;
private static HttpClientBuilder httpBuilder;
private static CloseableHttpClient httpClient;
private static CloseableHttpClient httpsClient;
private static SSLContext sslContext;
/**
* 创建SSLContext对象用来绕过https证书认证实现访问
*/
static {
try {
sslContext = SSLContext.getInstance("TLS");
// 实现一个X509TrustManager接口,用于绕过验证,不用修改里面的方法
X509TrustManager tm = new X509TrustManager() {
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType)
throws CertificateException {
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType)
throws CertificateException {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return null;
}
};
sslContext.init(null, new TrustManager[] {tm}, null);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 初始化httpclient对象以及在创建httpclient对象之前的一些自定义配置
*/
static {
// 自定义配置信息
requestConfig = RequestConfig.custom()
.setSocketTimeout(DEFAULT_READ_TIMEOUT)
.setConnectTimeout(DEFAULT_CONNECT_TIMEOUT)
.setConnectionRequestTimeout(DEFAULT_CONNECT_REQUEST_TIMEOUT)
.build();
//设置协议http和https对应的处理socket链接工厂的对象
Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory> create()
.register("http", new PlainConnectionSocketFactory())
.register("https", new SSLConnectionSocketFactory(sslContext))
.build();
connectionManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
// 设置cookie存储对像,在需要获取cookie信息时,可以使用这个对象。
cookieStore = new BasicCookieStore();
// 设置最大连接数
connectionManager.setMaxTotal(MAX_TOTAL);
// 设置路由并发数
connectionManager.setDefaultMaxPerRoute(MAX_PER_ROUTE);
httpBuilder = HttpClientBuilder.create();
httpBuilder.setDefaultRequestConfig(requestConfig);
httpBuilder.setConnectionManager(connectionManager);
httpBuilder.setDefaultCookieStore(cookieStore);
// 实例化http 和 https的对象。
httpClient = httpBuilder.build();
httpsClient = httpBuilder.build();
}
/**
* 封装无参数的get请求http
* @param url 请求url
* @return 返回对象HttpClientResult
*/
public static HttpClientResult doGet(String url) {
return doGet(url, false);
}
/**
* 封装无参get请求支持https协议
* @param url 请求url
* @param https 请求的是否是https协议true 否false
* @return
*/
public static HttpClientResult doGet(String url, boolean https){
return doGet(url, null, null, https);
}
/**
* 封装带参数的get请求支持https协议
* @param url 请求url
* @param params 请求参数
* @param https 是否是https协议
*/
public static HttpClientResult doGet(String url, Map<String, String> params, boolean https){
return doGet(url, null, params, https);
}
/**
* 封装带参数和带请求头信息的GET方法支持https协议请求
* @param url 请求url
* @param headers 请求头信息
* @param params 请求参数
* @param https 是否使用https协议
*/
public static HttpClientResult doGet(String url, Map<String, String> headers, Map<String, String> params, boolean https){
// 创建HttpGet
HttpGet httpGet = null;
// 创建httpResponse对象
CloseableHttpResponse httpResponse = null;
try {
// 创建访问的地址
URIBuilder uriBuilder = new URIBuilder(url);
if (params != null) {
Set<Map.Entry<String, String>> entrySet = params.entrySet();
for (Map.Entry<String, String> entry : entrySet) {
uriBuilder.setParameter(entry.getKey(), entry.getValue());
}
}
// 创建HTTP对象
httpGet = new HttpGet(uriBuilder.build());
httpGet.setConfig(requestConfig);
// 设置请求头
setHeader(headers, httpGet);
// 使用不同的协议进行请求,返回自定义的响应对象
if (https) {
return getHttpClientResult(httpResponse, httpsClient, httpGet);
} else {
return getHttpClientResult(httpResponse, httpClient, httpGet);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
// 释放资源
if (httpGet != null) {
httpGet.releaseConnection();
}
release(httpResponse);
}
return null;
}
/**
* POST不带参数只支持http协议
* @param url 请求url
*/
public static HttpClientResult doPost(String url) {
return doPost(url, Boolean.FALSE);
}
/**
* 封装不带参数的post请求支持https协议
* @param url 请求url
* @param https 是否是https协议
*/
public static HttpClientResult doPost(String url, boolean https) {
return doPost(url, null, (Map<String, String>)null, https);
}
/**
* 带参数的post请求支持https协议
* @param url 请求url
* @param params 请求参数
* @param https 是否是https协议
*/
public static HttpClientResult doPost(String url, Map<String, String> params, boolean https) {
return doPost(url, null, params, https);
}
/**
* 带参数和请求头的POST请求支持https
*
* @param url 请求url
* @param headers 请求头
* @param params 请求参数参数为K=V格式
* @param https 是否https协议
*/
public static HttpClientResult doPost(String url, Map<String, String> headers, Map<String, String> params, boolean https) {
// 创建HTTP对象
HttpPost httpPost = new HttpPost(url);
httpPost.setConfig(requestConfig);
// 设置请求头
setHeader(headers, httpPost);
// 封装请求参数
setParam(params, httpPost);
// 创建httpResponse对象
CloseableHttpResponse httpResponse = null;
try {
if (https) {
return getHttpClientResult(httpResponse, httpsClient, httpPost);
} else {
return getHttpClientResult(httpResponse, httpClient, httpPost);
}
} finally {
httpPost.releaseConnection();
release(httpResponse);
}
}
/**
* 带参数带请求头的POST请求支持https协议
*
* @param url 请求url
* @param headers 请求头
* @param json 请求参数为json格式
* @param https 是否使用https协议
* @throws Exception
*/
public static HttpClientResult doPost(String url, Map<String, String> headers, String json, boolean https) {
// 创建HTTP对象
HttpPost httpPost = new HttpPost(url);
httpPost.setConfig(requestConfig);
// 设置请求头
setHeader(headers, httpPost);
StringEntity stringEntity = new StringEntity(json, ENCODING);
stringEntity.setContentEncoding(ENCODING);
httpPost.setEntity(stringEntity);
// 创建httpResponse对象
CloseableHttpResponse httpResponse = null;
try {
if (https) {
return getHttpClientResult(httpResponse, httpsClient, httpPost);
} else {
return getHttpClientResult(httpResponse, httpClient, httpPost);
}
} finally {
httpPost.releaseConnection();
release(httpResponse);
}
}
/**
* 发送put请求不带请求参数
*
* @param url 请求地址
* @return
* @throws Exception
*/
public static HttpClientResult doPut(String url) {
return doPut(url);
}
/**
* 发送put请求带请求参数
*
* @param url 请求地址
* @param params 参数集合
* @return
* @throws Exception
*/
public static HttpClientResult doPut(String url, Map<String, String> params) {
HttpPut httpPut = new HttpPut(url);
httpPut.setConfig(requestConfig);
setParam(params, httpPut);
CloseableHttpResponse httpResponse = null;
try {
return getHttpClientResult(httpResponse, httpClient, httpPut);
} finally {
httpPut.releaseConnection();
release(httpResponse);
}
}
/**
* 发送delete请求不带请求参数
*
* @param url 请求url
* @return
* @throws Exception
*/
public static HttpClientResult doDelete(String url) {
HttpDelete httpDelete = new HttpDelete(url);
httpDelete.setConfig(requestConfig);
CloseableHttpResponse httpResponse = null;
try {
return getHttpClientResult(httpResponse, httpClient, httpDelete);
} finally {
httpDelete.releaseConnection();
release(httpResponse);
}
}
/**
* 发送delete请求带请求参数 支持https协议
*
* @param url 请求url
* @param params 请求参数
* @param https 是否https
* @return
* @throws Exception
*/
public static HttpClientResult doDelete(String url, Map<String, String> params, boolean https) {
if (params == null) {
params = new HashMap<String, String>();
}
params.put("_method", "delete");
return doPost(url, params, https);
}
/**
* 获取cookie信息
* @return 返回所有cookie集合
*/
public static List<Cookie> getCookies() {
return cookieStore.getCookies();
}
/**
* 设置封装请求头
*
* @param params 头信息
* @param httpMethod 请求对象
*/
public static void setHeader(Map<String, String> params, HttpRequestBase httpMethod) {
// 封装请求头
if (null != params && !params.isEmpty()) {
Set<Map.Entry<String, String>> entrySet = params.entrySet();
for (Map.Entry<String, String> entry : entrySet) {
// 设置到请求头到HttpRequestBase对象中
httpMethod.setHeader(entry.getKey(), entry.getValue());
}
}
}
/**
* 封装请求参数
*
* @param params 请求参数
* @param httpMethod 请求方法
*/
public static void setParam(Map<String, String> params, HttpEntityEnclosingRequestBase httpMethod) {
// 封装请求参数
if (null != params && !params.isEmpty()) {
List<NameValuePair> nvps = new ArrayList<NameValuePair>();
Set<Map.Entry<String, String>> entrySet = params.entrySet();
for (Map.Entry<String, String> entry : entrySet) {
nvps.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
}
UrlEncodedFormEntity entity = null;
try {
entity = new UrlEncodedFormEntity(nvps, ENCODING);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
// 设置到请求的http对象中
httpMethod.setEntity(entity);
}
}
/**
* 获得响应结果
*
* @param httpResponse 响应对象
* @param httpClient httpclient对象
* @param httpMethod 请求方法
* @return
* @throws Exception
*/
public static HttpClientResult getHttpClientResult(CloseableHttpResponse httpResponse, CloseableHttpClient httpClient, HttpRequestBase httpMethod) {
try {
// 执行请求
httpResponse = httpClient.execute(httpMethod);
// 获取返回结果
if (httpResponse != null && httpResponse.getStatusLine() != null) {
String content = "";
if (httpResponse.getEntity() != null) {
content = EntityUtils.toString(httpResponse.getEntity(), ENCODING);
}
// return new HttpClientResult(httpResponse.getStatusLine().getStatusCode(), content);
}
} catch (IOException e) {
e.printStackTrace();
}
// return new HttpClientResult(HttpStatus.SC_INTERNAL_SERVER_ERROR);
return null;
}
/**
* 释放资源
*
* @param httpResponse 响应对象
*/
public static void release(CloseableHttpResponse httpResponse) {
// 释放资源
if (httpResponse != null) {
try {
httpResponse.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

34
open-anpr-client/src/main/java/com/visual/open/anpr/model/LocationPoint.java

@ -1,34 +0,0 @@
package com.visual.open.anpr.model;
import java.io.Serializable;
public class LocationPoint implements Serializable {
/**坐标X的值**/
private int x;
/**坐标Y的值**/
private int y;
public LocationPoint(){}
public LocationPoint(float x, float y) {
this.x = (int)x;
this.y = (int)y;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
}

17
open-anpr-client/src/main/java/com/visual/open/anpr/model/MapParam.java

@ -1,17 +0,0 @@
package com.visual.open.anpr.model;
import java.util.HashMap;
public class MapParam extends HashMap<String, Object> {
public static MapParam build(){
return new MapParam();
}
public MapParam put(String key, Object value){
super.put(key, value);
return this;
}
}

31
open-anpr-client/src/main/java/com/visual/open/anpr/model/PlateColor.java

@ -1,31 +0,0 @@
package com.visual.open.anpr.model;
public enum PlateColor {
BLACK("黑色"),
BLUE("蓝色"),
GREEN("绿色"),
WHITE("白色"),
YELLOW("黄色"),
UNKNOWN("未知");
private String name;
PlateColor(String name){
this.name = name;
}
public String getName(){
return this.name;
}
public static PlateColor valueOfName(String name){
for (PlateColor item : PlateColor.values()){
if(item.name.equals(name)){
return item;
}
}
return UNKNOWN;
}
}

8
open-anpr-client/src/main/java/com/visual/open/anpr/model/PlateLayout.java

@ -1,8 +0,0 @@
package com.visual.open.anpr.model;
public enum PlateLayout {
SINGLE, //单排
DOUBLE, //双排
UNKNOWN; //未知
}

96
open-anpr-client/src/main/java/com/visual/open/anpr/model/PlateLocation.java

@ -1,96 +0,0 @@
package com.visual.open.anpr.model;
import java.io.Serializable;
public class PlateLocation implements Serializable {
/**左上角坐标值**/
private LocationPoint leftTop;
/**右上角坐标**/
private LocationPoint rightTop;
/**右下角坐标**/
private LocationPoint rightBottom;
/**左下角坐标**/
private LocationPoint leftBottom;
public LocationPoint getLeftTop() {
return leftTop;
}
public void setLeftTop(LocationPoint leftTop) {
this.leftTop = leftTop;
}
public LocationPoint getRightTop() {
return rightTop;
}
public void setRightTop(LocationPoint rightTop) {
this.rightTop = rightTop;
}
public LocationPoint getRightBottom() {
return rightBottom;
}
public void setRightBottom(LocationPoint rightBottom) {
this.rightBottom = rightBottom;
}
public LocationPoint getLeftBottom() {
return leftBottom;
}
public void setLeftBottom(LocationPoint leftBottom) {
this.leftBottom = leftBottom;
}
/**
* x的最小坐标
* @return
*/
public int minX(){
return Math.min(Math.min(Math.min(leftTop.getX(), rightTop.getX()), rightBottom.getX()), leftBottom.getX());
}
/**
* y的最小坐标
* @return
*/
public int minY(){
return Math.min(Math.min(Math.min(leftTop.getY(), rightTop.getY()), rightBottom.getY()), leftBottom.getY());
}
/**
* x的最大坐标
* @return
*/
public int maxX(){
return Math.max(Math.max(Math.max(leftTop.getX(), rightTop.getX()), rightBottom.getX()), leftBottom.getX());
}
/**
* y的最大坐标
* @return
*/
public int maxY(){
return Math.max(Math.max(Math.max(leftTop.getY(), rightTop.getY()), rightBottom.getY()), leftBottom.getY());
}
/**
* 获取宽度
* @return
*/
public float width(){
return (float) Math.sqrt(Math.pow((rightTop.getX()-leftTop.getX()), 2)+Math.pow((rightTop.getY()-leftTop.getY()), 2));
}
/**
* 获取高度
* @return
*/
public float height(){
return (float) Math.sqrt(Math.pow((rightTop.getX()-rightBottom.getX()), 2)+Math.pow((rightTop.getY()-rightBottom.getY()), 2));
}
}

40
open-anpr-client/src/main/java/com/visual/open/anpr/model/Recognition.java

@ -1,40 +0,0 @@
package com.visual.open.anpr.model;
import java.io.Serializable;
public class Recognition<ExtendsVo extends Recognition<ExtendsVo>> implements Serializable {
/**图像Base64编码值**/
private String image;
/**搜索条数:默认5**/
private Integer limit = 5;
/**
* 构建比对对象
* @return
*/
public static Recognition build(){
return new Recognition();
}
public String getImage() {
return image;
}
public ExtendsVo setImage(String image) {
this.image = image;
return (ExtendsVo) this;
}
public Integer getLimit() {
return limit;
}
public ExtendsVo setLimit(Integer limit) {
this.limit = limit;
return (ExtendsVo) this;
}
}

36
open-anpr-client/src/main/java/com/visual/open/anpr/model/RecognitionInfo.java

@ -1,36 +0,0 @@
package com.visual.open.anpr.model;
import java.io.Serializable;
public class RecognitionInfo implements Serializable {
/**车牌布局,单排还是双排**/
private PlateLayout layout;
/**车牌文本信息**/
private String plateNo;
/**车牌的颜色信息**/
private PlateColor plateColor;
public PlateLayout getLayout() {
return layout;
}
public void setLayout(PlateLayout layout) {
this.layout = layout;
}
public String getPlateNo() {
return plateNo;
}
public void setPlateNo(String plateNo) {
this.plateNo = plateNo;
}
public PlateColor getPlateColor() {
return plateColor;
}
public void setPlateColor(PlateColor plateColor) {
this.plateColor = plateColor;
}
}

40
open-anpr-client/src/main/java/com/visual/open/anpr/model/RecognitionRep.java

@ -1,40 +0,0 @@
package com.visual.open.anpr.model;
import java.io.Serializable;
public class RecognitionRep implements Serializable {
/**车牌置信分数**/
private Float score;
/**车牌位置信息**/
private PlateLocation location;
/**车牌识别信息**/
private RecognitionInfo recognition;
public Float getScore() {
return score;
}
public void setScore(Float score) {
this.score = score;
}
public PlateLocation getLocation() {
return location;
}
public void setLocation(PlateLocation location) {
this.location = location;
}
public RecognitionInfo getRecognition() {
return recognition;
}
public void setRecognition(RecognitionInfo recognition) {
this.recognition = recognition;
}
}

13
open-anpr-client/src/main/java/com/visual/open/anpr/model/RecognitionReq.java

@ -1,13 +0,0 @@
package com.visual.open.anpr.model;
public class RecognitionReq extends Recognition<RecognitionReq>{
/**
* 构建比对对象
* @return
*/
public static RecognitionReq build(){
return new RecognitionReq();
}
}

62
open-anpr-client/src/main/java/com/visual/open/anpr/model/Response.java

@ -1,62 +0,0 @@
package com.visual.open.anpr.model;
import java.io.Serializable;
/**
* des:接口返回对象
* @author diven
* @date 上午9:34 2018/7/12
*/
public class Response<T> implements Serializable{
private static final long serialVersionUID = -6919611972884058300L;
private Integer code = -1;
private String message;
private T data;
public Response(){}
public Response(Integer code, String message, T data) {
if(null != code) {
this.code = code;
}
this.message = message;
this.data = data;
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
if(null != code){
this.code = code;
}
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
public boolean ok(){
return new Integer(0).equals(code);
}
@Override
public String toString() {
return "Response{" + "code=" + code + ", message='" + message + '\'' + ", data=" + data + '}';
}
}

48
open-anpr-client/src/main/java/com/visual/open/anpr/utils/Base64Util.java

@ -1,48 +0,0 @@
package com.visual.open.anpr.utils;
import org.apache.commons.codec.binary.Base64;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
public class Base64Util {
public static String encode(byte[] binaryData) {
byte[] bytes = Base64.encodeBase64(binaryData);
return new String(bytes);
}
public static String encode(InputStream in) {
// 读取图片字节数组
try {
ByteArrayOutputStream swapStream = new ByteArrayOutputStream();
byte[] buff = new byte[100];
int rc;
while ((rc = in.read(buff, 0, 100)) > 0) {
swapStream.write(buff, 0, rc);
}
return encode(swapStream.toByteArray());
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public static String encode(String filePath){
try {
return encode(new FileInputStream(filePath));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}

40
open-anpr-core/pom.xml

@ -1,40 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>open-anpr</artifactId>
<groupId>com.visual.open.anpr</groupId>
<version>1.1.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>open-anpr-core</artifactId>
<dependencies>
<dependency>
<groupId>org.openpnp</groupId>
<artifactId>opencv</artifactId>
</dependency>
<dependency>
<groupId>com.microsoft.onnxruntime</groupId>
<artifactId>onnxruntime</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-math3</artifactId>
</dependency>
</dependencies>
</project>

10
open-anpr-core/src/main/java/com/visual/open/anpr/core/base/PlateRecognition.java

@ -1,10 +0,0 @@
package com.visual.open.anpr.core.base;
import java.util.Map;
import com.visual.open.anpr.core.domain.ImageMat;
import com.visual.open.anpr.core.domain.PlateInfo.ParseInfo;
public interface PlateRecognition {
ParseInfo inference(ImageMat image, Boolean single, Map<String, Object> params);
}

131
open-anpr-core/src/main/java/com/visual/open/anpr/core/domain/DrawImage.java

@ -1,131 +0,0 @@
package com.visual.open.anpr.core.domain;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferByte;
import java.io.File;
import java.io.IOException;
public class DrawImage {
private BufferedImage image;
private DrawImage(BufferedImage image){
this.image = image;
}
public static DrawImage build(String image){
try {
return build(ImageIO.read(new File(image)));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public static DrawImage build(BufferedImage image){
return new DrawImage(image);
}
private static int getLength(String text) {
int textLength = text.length();
int length = textLength;
for (int i = 0; i < textLength; i++) {
if (String.valueOf(text.charAt(i)).getBytes().length > 1) {
length++;
}
}
return (length % 2 == 0) ? length / 2 : length / 2 + 1;
}
public DrawImage drawRect(Rect rect, int lineWidth, Color color){
Graphics2D g = (Graphics2D)image.getGraphics();
g.setColor(color);
g.setStroke(new BasicStroke(lineWidth));
g.drawRect(rect.x, rect.y, rect.width, rect.height);
return this;
}
public DrawImage drawLine(Point point1, Point point2, int lineWidth, Color color){
Graphics2D g = (Graphics2D)image.getGraphics();
g.setColor(color);
g.setStroke(new BasicStroke(lineWidth));
g.drawLine(point1.x, point1.y, point2.x, point2.y);
return this;
}
public DrawImage drawText(String text, Point point, int fontSize, Color color){
Graphics2D g = image.createGraphics();
g.setColor(color);
g.setFont(new Font("微软雅黑", Font.PLAIN, fontSize));
g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 1));
int width_1 = fontSize * getLength(text);
int height_1 = fontSize;
int widthDiff = image.getWidth() - width_1;
int heightDiff = image.getHeight() - height_1;
if(point.x < 0){
point.x = widthDiff / 2;
}else if(point.x > widthDiff){
point.x = widthDiff;
}
if(point.y < 0){
point.y = heightDiff / 2;
}else if(point.y > heightDiff){
point.y = heightDiff;
}
g.drawString(text, point.x, point.y + height_1);
return this;
}
public Mat toMat(){
try {
if(image.getType() != BufferedImage.TYPE_3BYTE_BGR){
BufferedImage temp = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_3BYTE_BGR);
Graphics2D g = temp.createGraphics();
try {
g.setComposite(AlphaComposite.Src);
g.drawImage(image, 0, 0, null);
} finally {
g.dispose();
}
image = temp;
}
byte[] pixels = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();
Mat mat = Mat.eye(image.getHeight(), image.getWidth(), CvType.CV_8UC3);
mat.put(0, 0, pixels);
return mat;
}catch (Exception e){
throw new RuntimeException(e);
}
}
public static class Rect{
public int x;
public int y;
public int width;
public int height;
public Rect(int x, int y, int width, int height) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
}
public static class Point{
public int x;
public int y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
}
}

128
open-anpr-core/src/main/java/com/visual/open/anpr/core/utils/JsonUtil.java

@ -1,128 +0,0 @@
package com.visual.open.anpr.core.utils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.alibaba.fastjson.serializer.SerializerFeature;
import java.util.List;
import java.util.Map;
public class JsonUtil {
/**
* 将Bean转化为json字符串
*
* @param obj bean对象
* @return json
*/
public static String toString(Object obj) {
return toString(obj, false, false);
}
public static String toSimpleString(Object obj) {
return toString(obj, false, true);
}
/**
* 将Bean转化为json字符串
*
* @param obj bean对象
* @param prettyFormat 是否格式化
* @return json
*/
public static String toString(Object obj, boolean prettyFormat, boolean noNull) {
if (prettyFormat) {
if (noNull) {
return JSON.toJSONString(obj, SerializerFeature.DisableCircularReferenceDetect, SerializerFeature.PrettyFormat);
} else {
return JSON.toJSONString(obj, SerializerFeature.WriteMapNullValue, SerializerFeature.WriteNullListAsEmpty, SerializerFeature.DisableCircularReferenceDetect, SerializerFeature.PrettyFormat);
}
} else {
if (noNull) {
return JSON.toJSONString(obj, SerializerFeature.DisableCircularReferenceDetect);
} else {
return JSON.toJSONString(obj, SerializerFeature.WriteMapNullValue, SerializerFeature.WriteNullListAsEmpty, SerializerFeature.DisableCircularReferenceDetect);
}
}
}
/**
* 将字符串转换为Entity
*
* @param json 数据字符串
* @param clazz Entity class
* @return
*/
public static <T> T toEntity(String json, Class<T> clazz) {
return JSON.parseObject(json, clazz);
}
/**
* 将字符串转换为Entity
*
* @param json 数据字符串
* @param typeReference Entity class
* @return
*/
public static <T> T toEntity(String json, TypeReference<T> typeReference) {
return JSON.parseObject(json, typeReference);
}
/**
* 将字符串转换为Map
*
* @param json 数据字符串
* @return Map
*/
public static Map<String, Object> toMap(String json) {
return JSON.parseObject(json, new TypeReference<Map<String, Object>>() {
});
}
/**
* 将字符串转换为List<T>
*
* @param json 数据字符串
* @param collectionClass 泛型
* @return list<T>
*/
public static <T> List<T> toList(String json, Class<T> collectionClass) {
return JSON.parseArray(json, collectionClass);
}
/**
* 将字符串转换为List<Map<String, Object>>
*
* @param json 数据字符串
* @return list<map>
*/
public static List<Map<String, Object>> toListMap(String json) {
return JSON.parseObject(json, new TypeReference<List<Map<String, Object>>>() {
});
}
/**
* 将字符串转换为Object
*
* @param json 数据字符串
* @return list<map>
*/
public static JSONObject toJsonObject(String json) {
return JSON.parseObject(json);
}
/**
* 将字符串转换为Array
*
* @param json 数据字符串
* @return list<map>
*/
public static JSONArray toJsonArray(String json) {
return JSON.parseArray(json);
}
}

28
open-anpr-core/src/test/java/com/visual/open/anpr/core/base/BaseTest.java

@ -1,28 +0,0 @@
package com.visual.open.anpr.core.base;
import ai.onnxruntime.OrtEnvironment;
import java.io.File;
import java.util.Map;
import java.util.TreeMap;
public abstract class BaseTest {
//静态加载动态链接库
static{ nu.pattern.OpenCV.loadShared(); }
private OrtEnvironment env = OrtEnvironment.getEnvironment();
public static Map<String, String> getImagePathMap(String imagePath){
Map<String, String> map = new TreeMap<>();
File file = new File(imagePath);
if(file.isFile()){
map.put(file.getName(), file.getAbsolutePath());
}else if(file.isDirectory()){
for(File tmpFile : file.listFiles()){
map.putAll(getImagePathMap(tmpFile.getPath()));
}
}
return map;
}
}

77
open-anpr-core/src/test/java/com/visual/open/anpr/core/extract/PlateExtractorTest.java

@ -1,77 +0,0 @@
package com.visual.open.anpr.core.extract;
import com.visual.open.anpr.core.base.BaseTest;
import com.visual.open.anpr.core.domain.*;
import com.visual.open.anpr.core.models.TorchPlateDetection;
import com.visual.open.anpr.core.models.TorchPlateRecognition;
import org.opencv.core.Mat;
import org.opencv.core.Point;
import org.opencv.core.Scalar;
import org.opencv.highgui.HighGui;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
import java.awt.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class PlateExtractorTest extends BaseTest {
private static String plateDetectionPath = "open-anpr-core/src/main/resources/models/plate_detect.onnx";
private static String plateRecognitionPath = "open-anpr-core/src/main/resources/models/plate_rec_color.onnx";
public static void main(String[] args) {
TorchPlateDetection torchPlateDetection = new TorchPlateDetection(plateDetectionPath, 1);
TorchPlateRecognition torchPlateRecognition = new TorchPlateRecognition(plateRecognitionPath, 1);
PlateExtractor extractor = new PlateExtractorImpl(torchPlateDetection, torchPlateRecognition);
String imagePath = "open-anpr-core/src/test/resources/images";
Map<String, String> map = getImagePathMap(imagePath);
for(String fileName : map.keySet()) {
String imageFilePath = map.get(fileName);
System.out.println(imageFilePath);
Mat image = Imgcodecs.imread(imageFilePath);
long startTime = System.currentTimeMillis();
ExtParam extParam = ExtParam.build()
.setTopK(20)
.setScoreTh(0.3f)
.setIouTh(0.5f);
//推理
PlateImage plateImage = extractor.extract(ImageMat.fromCVMat(image), extParam, new HashMap<>());
System.out.println("cost:" + (System.currentTimeMillis()-startTime));
List<PlateInfo> plateInfos = plateImage.PlateInfos();
//可视化
DrawImage drawImage = DrawImage.build(imageFilePath);
for(PlateInfo plateInfo: plateInfos){
//画框
PlateInfo.Point [] points = plateInfo.box.toArray();
for(int i =0; i< points.length; i++){
if(i+1 == points.length){
drawImage.drawLine(
new DrawImage.Point((int)points[i].x, (int)points[i].y),
new DrawImage.Point((int)points[0].x, (int)points[0].y),
2, Color.RED
);
}else{
drawImage.drawLine(
new DrawImage.Point((int)points[i].x, (int)points[i].y),
new DrawImage.Point((int)points[i+1].x, (int)points[i+1].y),
2, Color.RED
);
}
}
//添加文本
PlateInfo.ParseInfo parseInfo = plateInfo.parseInfo;
int fonSize = Float.valueOf(plateInfo.box.width() / parseInfo.plateNo.length() * 1.4f).intValue();
drawImage.drawText(parseInfo.plateNo,
new DrawImage.Point((int)points[0].x, (int)points[0].y-(int)(fonSize*2.2)), fonSize, Color.RED);
drawImage.drawText((plateInfo.single ? "单排" : "双排") + ":" + parseInfo.plateColor,
new DrawImage.Point((int)points[0].x, (int)points[0].y-(int)(fonSize*1.2)), fonSize, Color.RED);
}
//show
ImageMat.fromCVMat(drawImage.toMat()).imShow();
image.release();
}
}
}

42
open-anpr-core/src/test/java/com/visual/open/anpr/core/models/TorchPlateDetectionTest.java

@ -1,42 +0,0 @@
package com.visual.open.anpr.core.models;
import com.visual.open.anpr.core.domain.DrawImage;
import com.visual.open.anpr.core.domain.ImageMat;
import com.visual.open.anpr.core.domain.PlateInfo;
import java.awt.*;
import java.util.HashMap;
import java.util.List;
public class TorchPlateDetectionTest {
public static void main(String[] args) {
TorchPlateDetection torchPlateDetection = new TorchPlateDetection("open-anpr-core/src/main/resources/models/plate_detect.onnx", 1);
String imagePath = "open-anpr-core/src/test/resources/images/image001.jpg";
ImageMat imageMat = ImageMat.fromImage(imagePath);
List<PlateInfo> plateInfos = torchPlateDetection.inference(imageMat, 0.3f,0.5f, new HashMap<>());
System.out.println(plateInfos);
DrawImage drawImage = DrawImage.build(imagePath);
for(PlateInfo plateInfo : plateInfos){
PlateInfo.Point [] points = plateInfo.box.toArray();
for(int i =0; i< points.length; i++){
if(i+1 == points.length){
drawImage.drawLine(
new DrawImage.Point((int)points[i].x, (int)points[i].y),
new DrawImage.Point((int)points[0].x, (int)points[0].y),
2, Color.RED
);
}else{
drawImage.drawLine(
new DrawImage.Point((int)points[i].x, (int)points[i].y),
new DrawImage.Point((int)points[i+1].x, (int)points[i+1].y),
2, Color.RED
);
}
}
}
ImageMat.fromCVMat(drawImage.toMat()).imShow();
}
}

28
open-anpr-core/src/test/java/com/visual/open/anpr/core/models/TorchPlateRecognitionTest.java

@ -1,28 +0,0 @@
package com.visual.open.anpr.core.models;
import com.visual.open.anpr.core.domain.ImageMat;
import com.visual.open.anpr.core.domain.PlateInfo;
import com.visual.open.anpr.core.utils.CropUtil;
import org.opencv.core.Mat;
import java.util.HashMap;
import java.util.List;
public class TorchPlateRecognitionTest {
public static void main(String[] args) {
TorchPlateDetection torchPlateDetection = new TorchPlateDetection("open-anpr-core/src/main/resources/models/plate_detect.onnx", 1);
TorchPlateRecognition torchPlateRecognition = new TorchPlateRecognition("open-anpr-core/src/main/resources/models/plate_rec_color.onnx", 1);
String imagePath = "open-anpr-core/src/test/resources/images";
ImageMat imageMat = ImageMat.fromImage(imagePath);
List<PlateInfo> plateInfos = torchPlateDetection.inference(imageMat, 0.3f,0.5f, new HashMap<>());
System.out.println(plateInfos);
for(PlateInfo plateInfo : plateInfos){
Mat crop = CropUtil.crop(imageMat.toCvMat(), plateInfo.box);
// ImageMat.fromCVMat(crop).imShow();
PlateInfo.ParseInfo parseInfo = torchPlateRecognition.inference(ImageMat.fromCVMat(crop), plateInfo.single, new HashMap<>());
System.out.println(parseInfo);
}
}
}

BIN
open-anpr-core/src/test/resources/images/image001.jpg

Binary file not shown.

Before

Width:  |  Height:  |  Size: 107 KiB

BIN
open-anpr-core/src/test/resources/images/image002.jpg

Binary file not shown.

Before

Width:  |  Height:  |  Size: 64 KiB

BIN
open-anpr-core/src/test/resources/images/image003.jpg

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

BIN
open-anpr-core/src/test/resources/images/image004.jpg

Binary file not shown.

Before

Width:  |  Height:  |  Size: 390 KiB

BIN
open-anpr-core/src/test/resources/images/image005.jpg

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

BIN
open-anpr-core/src/test/resources/images/image006.jpg

Binary file not shown.

Before

Width:  |  Height:  |  Size: 64 KiB

BIN
open-anpr-core/src/test/resources/images/image007.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 671 KiB

BIN
open-anpr-core/src/test/resources/images/image008.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 328 KiB

BIN
open-anpr-core/src/test/resources/images/image009.jpg

Binary file not shown.

Before

Width:  |  Height:  |  Size: 382 KiB

BIN
open-anpr-core/src/test/resources/images/image010.jpg

Binary file not shown.

Before

Width:  |  Height:  |  Size: 85 KiB

BIN
open-anpr-core/src/test/resources/images/image011.jpg

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

BIN
open-anpr-core/src/test/resources/images/image012.jpg

Binary file not shown.

Before

Width:  |  Height:  |  Size: 999 KiB

BIN
open-anpr-core/src/test/resources/images/image013.jpg

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

BIN
open-anpr-core/src/test/resources/images/image014.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 400 KiB

BIN
open-anpr-core/src/test/resources/images/image015.jpg

Binary file not shown.

Before

Width:  |  Height:  |  Size: 116 KiB

125
open-anpr-server/pom.xml

@ -12,6 +12,18 @@
<artifactId>open-anpr-server</artifactId> <artifactId>open-anpr-server</artifactId>
<properties>
<opencv.version>4.6.0-0</opencv.version>
<onnxruntime.version>1.13.1</onnxruntime.version>
<fastjson.version>1.2.83</fastjson.version>
<hibernate.version>6.0.21.Final</hibernate.version>
<commons-math3.version>3.6.1</commons-math3.version>
<commons-collections4.version>4.3</commons-collections4.version>
<swagger.version>3.0.0</swagger.version>
<knife4j-ui.version>3.0.3</knife4j-ui.version>
<java.version>8</java.version>
<maven-resources-plugin.version>2.6</maven-resources-plugin.version>
</properties>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
@ -40,11 +52,87 @@
<artifactId>hibernate-validator</artifactId> <artifactId>hibernate-validator</artifactId>
</dependency> </dependency>
<!-- <dependency>-->
<!-- <groupId>com.visual.open.anpr</groupId>-->
<!-- <artifactId>open-anpr-core</artifactId>-->
<!-- </dependency>-->
<dependency>
<groupId>org.openpnp</groupId>
<artifactId>opencv</artifactId>
</dependency>
<dependency>
<groupId>com.microsoft.onnxruntime</groupId>
<artifactId>onnxruntime</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-math3</artifactId>
</dependency>
<dependency> <dependency>
<groupId>com.visual.open.anpr</groupId> <groupId>com.visual.open.anpr</groupId>
<artifactId>open-anpr-core</artifactId> <artifactId>open-anpr-client</artifactId>
<version>${project.version}</version>
</dependency> </dependency>
<dependency>
<groupId>org.openpnp</groupId>
<artifactId>opencv</artifactId>
<version>${opencv.version}</version>
</dependency>
<dependency>
<groupId>com.microsoft.onnxruntime</groupId>
<artifactId>onnxruntime</artifactId>
<version>${onnxruntime.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${fastjson.version}</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>${commons-collections4.version}</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-math3</artifactId>
<version>${commons-math3.version}</version>
</dependency>
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>${hibernate.version}</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<version>${swagger.version}</version>
</dependency>
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
<version>${knife4j-ui.version}</version>
</dependency>
<!--常用工具类 --> <!--常用工具类 -->
<dependency> <dependency>
<groupId>org.apache.commons</groupId> <groupId>org.apache.commons</groupId>
@ -64,6 +152,41 @@
<groupId>com.github.xiaoymin</groupId> <groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId> <artifactId>knife4j-spring-boot-starter</artifactId>
</dependency> </dependency>
<dependency>
<groupId>ws.schild</groupId>
<artifactId>jave-all-deps</artifactId>
<version>3.0.1</version>
<exclusions>
<!-- 排除windows 32位系统 -->
<exclusion>
<groupId>ws.schild</groupId>
<artifactId>jave-nativebin-win32</artifactId>
</exclusion>
<!-- 排除linux 32位系统 -->
<exclusion>
<groupId>ws.schild</groupId>
<artifactId>jave-nativebin-linux32</artifactId>
</exclusion>
<!-- 排除Mac系统-->
<exclusion>
<groupId>ws.schild</groupId>
<artifactId>jave-nativebin-osx64</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
</dependencies> </dependencies>
<build> <build>

4
open-anpr-core/src/main/java/com/visual/open/anpr/core/base/BaseOnnxInfer.java → open-anpr-server/src/main/java/com/visual/open/anpr/server/base/BaseOnnxInfer.java

@ -1,10 +1,10 @@
package com.visual.open.anpr.core.base; package com.visual.open.anpr.server.base;
import ai.onnxruntime.OrtEnvironment; import ai.onnxruntime.OrtEnvironment;
import ai.onnxruntime.OrtLoggingLevel; import ai.onnxruntime.OrtLoggingLevel;
import ai.onnxruntime.OrtSession; import ai.onnxruntime.OrtSession;
public abstract class BaseOnnxInfer extends OpenCVLoader{ public abstract class BaseOnnxInfer extends OpenCVLoader {
private OrtEnvironment env; private OrtEnvironment env;
private String[] inputNames; private String[] inputNames;

2
open-anpr-core/src/main/java/com/visual/open/anpr/core/base/OpenCVLoader.java → open-anpr-server/src/main/java/com/visual/open/anpr/server/base/OpenCVLoader.java

@ -1,4 +1,4 @@
package com.visual.open.anpr.core.base; package com.visual.open.anpr.server.base;
public abstract class OpenCVLoader { public abstract class OpenCVLoader {

6
open-anpr-core/src/main/java/com/visual/open/anpr/core/base/PlateDetection.java → open-anpr-server/src/main/java/com/visual/open/anpr/server/base/PlateDetection.java

@ -1,7 +1,7 @@
package com.visual.open.anpr.core.base; package com.visual.open.anpr.server.base;
import com.visual.open.anpr.core.domain.ImageMat; import com.visual.open.anpr.server.domain.ImageMat;
import com.visual.open.anpr.core.domain.PlateInfo; import com.visual.open.anpr.server.domain.PlateInfo;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;

11
open-anpr-server/src/main/java/com/visual/open/anpr/server/base/PlateRecognition.java

@ -0,0 +1,11 @@
package com.visual.open.anpr.server.base;
import com.visual.open.anpr.server.domain.ImageMat;
import com.visual.open.anpr.server.domain.PlateInfo.ParseInfo;
import java.util.Map;
public interface PlateRecognition {
ParseInfo inference(ImageMat image, Boolean single, Map<String, Object> params);
}

5
open-anpr-server/src/main/java/com/visual/open/anpr/server/bootstrap/OpenAnprApplication.java

@ -2,10 +2,11 @@ package com.visual.open.anpr.server.bootstrap;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; import org.springframework.context.annotation.ComponentScan;
import org.springframework.scheduling.annotation.EnableScheduling;
@SpringBootApplication @SpringBootApplication
@ComponentScan("com.visual.open.anpr.server.extract")
@ComponentScan("com.visual.open.anpr.server.controller")
public class OpenAnprApplication { public class OpenAnprApplication {
public static void main(String[] args) { public static void main(String[] args) {

80
open-anpr-server/src/main/java/com/visual/open/anpr/server/bootstrap/conf/ModelConfig.java

@ -1,16 +1,22 @@
package com.visual.open.anpr.server.bootstrap.conf; package com.visual.open.anpr.server.bootstrap.conf;
import com.visual.open.anpr.core.base.PlateDetection; import com.visual.open.anpr.server.base.PlateDetection;
import com.visual.open.anpr.core.base.PlateRecognition; import com.visual.open.anpr.server.base.PlateRecognition;
import com.visual.open.anpr.core.extract.PlateExtractor; import com.visual.open.anpr.server.controller.server.restful.PlateController;
import com.visual.open.anpr.core.extract.PlateExtractorImpl; import com.visual.open.anpr.server.extract.PlateExtractor;
import com.visual.open.anpr.core.models.TorchPlateDetection; import com.visual.open.anpr.server.extract.PlateExtractorImpl;
import com.visual.open.anpr.core.models.TorchPlateRecognition; import com.visual.open.anpr.server.models.TorchPlateDetection;
import com.visual.open.anpr.server.models.TorchPlateRecognition;
import com.visual.open.anpr.server.utils.FileCopyUtil;
import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import javax.annotation.Resource;
import java.io.*;
@Configuration("visualModelConfig") @Configuration("visualModelConfig")
public class ModelConfig { public class ModelConfig {
@ -33,26 +39,28 @@ public class ModelConfig {
/** /**
* 获取车牌检查模型 * 获取车牌检查模型
*
* @return * @return
*/ */
@Bean(name = "visualPlateDetection") @Bean(name = "visualPlateDetection")
public PlateDetection getPlateDetection(){ public PlateDetection getPlateDetection() {
if(plateDetectionName.equalsIgnoreCase("TorchPlateDetection")){ if (plateDetectionName.equalsIgnoreCase("TorchPlateDetection")) {
return new TorchPlateDetection(getModelPath(plateDetectionName, plateDetectionModel)[0], plateDetectionThread); return new TorchPlateDetection(getModelPath(plateDetectionName, plateDetectionModel)[0], plateDetectionThread);
}else{ } else {
return new TorchPlateDetection(getModelPath(plateDetectionName, plateDetectionModel)[0], plateDetectionThread); return new TorchPlateDetection(getModelPath(plateDetectionName, plateDetectionModel)[0], plateDetectionThread);
} }
} }
/** /**
* 车牌特征提取服务 * 车牌特征提取服务
*
* @return * @return
*/ */
@Bean(name = "visualPlateRecognition") @Bean(name = "visualPlateRecognition")
public PlateRecognition getPlateRecognition(){ public PlateRecognition getPlateRecognition() {
if(plateRecognitionName.equalsIgnoreCase("TorchPlateRecognition")){ if (plateRecognitionName.equalsIgnoreCase("TorchPlateRecognition")) {
return new TorchPlateRecognition(getModelPath(plateRecognitionName, plateRecognitionNameModel)[0], plateRecognitionNameThread); return new TorchPlateRecognition(getModelPath(plateRecognitionName, plateRecognitionNameModel)[0], plateRecognitionNameThread);
}else{ } else {
return new TorchPlateRecognition(getModelPath(plateRecognitionName, plateRecognitionNameModel)[0], plateRecognitionNameThread); return new TorchPlateRecognition(getModelPath(plateRecognitionName, plateRecognitionNameModel)[0], plateRecognitionNameThread);
} }
} }
@ -60,34 +68,60 @@ public class ModelConfig {
/** /**
* 构建特征提取器 * 构建特征提取器
* @param plateDetection 车牌检测模型 *
* @param plateRecognition 车牌识别模型 * @param plateDetection 车牌检测模型
* @param plateRecognition 车牌识别模型
*/ */
@Bean(name = "visualPlateExtractor") @Bean(name = "visualPlateExtractor")
public PlateExtractor getPlateExtractor( public PlateExtractor getPlateExtractor(
@Qualifier("visualPlateDetection")PlateDetection plateDetection, @Qualifier("visualPlateDetection") PlateDetection plateDetection,
@Qualifier("visualPlateRecognition")PlateRecognition plateRecognition @Qualifier("visualPlateRecognition") PlateRecognition plateRecognition
){ ) {
return new PlateExtractorImpl(plateDetection, plateRecognition); return new PlateExtractorImpl(plateDetection, plateRecognition);
}
private static boolean isRunningFromJAR() {
String className = ModelConfig.class.getName().replace('.', '/');
String classJar = ModelConfig.class.getResource("/" + className + ".class").toString();
return classJar.startsWith("jar:");
} }
/** /**
* 获取模型路径 * 获取模型路径
*
* @param modelName 模型名称 * @param modelName 模型名称
* @return * @return
*/ */
private String[] getModelPath(String modelName, String modelPath[]){ private String[] getModelPath(String modelName, String modelPath[]) {
String basePath = "open-anpr-core/src/main/resources/"; boolean runningFromJAR = isRunningFromJAR();
if("docker".equalsIgnoreCase(profile)){ // 在idea 情况下运行项目
String basePath = "open-anpr-server/src/main/resources/";
if (runningFromJAR) {
// 在jar包情况下运行项目
System.out.println("jar包运行");
basePath = System.getProperty("user.dir") + "\\";
String fileName = "plate_detect.onnx";
String fileName2 = "plate_rec_color.onnx";
File file = new File(basePath + "models", fileName);
File file2 = new File(basePath + "models", fileName2);
int a = file.exists() && file2.exists() ? 1 : 2; // 1代表文件都存在,2代表有文件不存在
if (2 == a) {
FileCopyUtil.copyHCNetSdkFromWindows();
}
}
if ("docker".equalsIgnoreCase(profile)) {
basePath = "/app/open-anpr/"; basePath = "/app/open-anpr/";
} }
if((null == modelPath || modelPath.length != 1) && "TorchPlateDetection".equalsIgnoreCase(modelName)){ if ((null == modelPath || modelPath.length != 1) && "TorchPlateDetection".equalsIgnoreCase(modelName)) {
return new String[]{basePath + "models/plate_detect.onnx"}; return new String[]{basePath + "models/plate_detect.onnx"};
} }
if((null == modelPath || modelPath.length != 1) && "TorchPlateRecognition".equalsIgnoreCase(modelName)){ if ((null == modelPath || modelPath.length != 1) && "TorchPlateRecognition".equalsIgnoreCase(modelName)) {
return new String[]{basePath + "models/plate_rec_color.onnx"}; return new String[]{basePath + "models/plate_rec_color.onnx"};
} }

36
open-anpr-server/src/main/java/com/visual/open/anpr/server/controller/server/restful/PlateController.java

@ -4,11 +4,15 @@ import com.visual.open.anpr.server.controller.server.impl.PlateControllerImpl;
import com.visual.open.anpr.server.domain.common.ResponseInfo; import com.visual.open.anpr.server.domain.common.ResponseInfo;
import com.visual.open.anpr.server.domain.request.PlateInfoReqVo; import com.visual.open.anpr.server.domain.request.PlateInfoReqVo;
import com.visual.open.anpr.server.domain.response.PlateInfoRepVo; import com.visual.open.anpr.server.domain.response.PlateInfoRepVo;
import com.visual.open.anpr.server.utils.FfmpegUtil;
import com.visual.open.anpr.server.utils.FileCopyUtil;
import com.visual.open.anpr.server.utils.ImageUtil;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import javax.validation.Valid; import javax.validation.Valid;
import java.io.File;
import java.util.List; import java.util.List;
@Api(tags="01、车牌识别服务") @Api(tags="01、车牌识别服务")
@ -16,6 +20,9 @@ import java.util.List;
@RequestMapping("/visual/plate") @RequestMapping("/visual/plate")
public class PlateController extends PlateControllerImpl { public class PlateController extends PlateControllerImpl {
static String targetPath = "\\images\\";
@ApiOperation(value="1、车牌识别", position = 1) @ApiOperation(value="1、车牌识别", position = 1)
@Override @Override
@ResponseBody @ResponseBody
@ -23,4 +30,33 @@ public class PlateController extends PlateControllerImpl {
public ResponseInfo<List<PlateInfoRepVo>> recognition(@RequestBody @Valid PlateInfoReqVo plateInfoReq) { public ResponseInfo<List<PlateInfoRepVo>> recognition(@RequestBody @Valid PlateInfoReqVo plateInfoReq) {
return super.recognition(plateInfoReq); return super.recognition(plateInfoReq);
} }
@ApiOperation(value = "根据图片名称车牌识别")
@RequestMapping(value = "getByImageName", method = RequestMethod.GET)
public ResponseInfo<List<PlateInfoRepVo>> imagesToBase64(@RequestParam String imageName){
String property = System.getProperty("user.dir") + "\\images\\";
String filePath = property + targetPath + imageName;
String imageBaseCode = ImageUtil.convertImageToBase64Str(filePath);
PlateInfoReqVo plateInfoReq = new PlateInfoReqVo();
plateInfoReq.setImage(imageBaseCode);
return recognition(plateInfoReq);
}
// 抓拍实况中的车牌并识别
/**
* 抓拍实况中的车牌并识别 可同时识别默认最多5张车牌
* @param CameraIP ffmpeg所需的摄像头IP地址
* @return 返回识别结果
*/
@ApiOperation(value = "抓拍实况中的车牌并识别")
@RequestMapping(value = "getByPicture", method = RequestMethod.GET)
public ResponseInfo<List<PlateInfoRepVo>> getByPicture(@RequestParam String CameraIP){
// 获取当前项目路径
String property = System.getProperty("user.dir");
String imageName = FfmpegUtil.getLiveCapture(CameraIP, property + targetPath);
return imagesToBase64(imageName);
}
} }

2
open-anpr-core/src/main/java/com/visual/open/anpr/core/domain/BorderMat.java → open-anpr-server/src/main/java/com/visual/open/anpr/server/domain/BorderMat.java

@ -1,4 +1,4 @@
package com.visual.open.anpr.core.domain; package com.visual.open.anpr.server.domain;
import org.opencv.core.Mat; import org.opencv.core.Mat;

2
open-anpr-test/src/main/java/com/visual/open/anpr/utils/DrawImage.java → open-anpr-server/src/main/java/com/visual/open/anpr/server/domain/DrawImage.java

@ -1,4 +1,4 @@
package com.visual.open.anpr.utils; package com.visual.open.anpr.server.domain;
import org.opencv.core.CvType; import org.opencv.core.CvType;
import org.opencv.core.Mat; import org.opencv.core.Mat;

2
open-anpr-core/src/main/java/com/visual/open/anpr/core/domain/ExtParam.java → open-anpr-server/src/main/java/com/visual/open/anpr/server/domain/ExtParam.java

@ -1,4 +1,4 @@
package com.visual.open.anpr.core.domain; package com.visual.open.anpr.server.domain;
import java.io.Serializable; import java.io.Serializable;

4
open-anpr-core/src/main/java/com/visual/open/anpr/core/domain/ImageMat.java → open-anpr-server/src/main/java/com/visual/open/anpr/server/domain/ImageMat.java

@ -1,8 +1,8 @@
package com.visual.open.anpr.core.domain; package com.visual.open.anpr.server.domain;
import ai.onnxruntime.OnnxTensor; import ai.onnxruntime.OnnxTensor;
import ai.onnxruntime.OrtEnvironment; import ai.onnxruntime.OrtEnvironment;
import com.visual.open.anpr.core.utils.MatUtil; import com.visual.open.anpr.server.utils.MatUtil;
import org.opencv.core.Point; import org.opencv.core.Point;
import org.opencv.core.*; import org.opencv.core.*;
import org.opencv.dnn.Dnn; import org.opencv.dnn.Dnn;

2
open-anpr-core/src/main/java/com/visual/open/anpr/core/domain/PlateImage.java → open-anpr-server/src/main/java/com/visual/open/anpr/server/domain/PlateImage.java

@ -1,4 +1,4 @@
package com.visual.open.anpr.core.domain; package com.visual.open.anpr.server.domain;
import java.io.Serializable; import java.io.Serializable;
import java.util.ArrayList; import java.util.ArrayList;

2
open-anpr-core/src/main/java/com/visual/open/anpr/core/domain/PlateInfo.java → open-anpr-server/src/main/java/com/visual/open/anpr/server/domain/PlateInfo.java

@ -1,4 +1,4 @@
package com.visual.open.anpr.core.domain; package com.visual.open.anpr.server.domain;
import java.io.Serializable; import java.io.Serializable;

9
open-anpr-core/src/main/java/com/visual/open/anpr/core/extract/PlateExtractor.java → open-anpr-server/src/main/java/com/visual/open/anpr/server/extract/PlateExtractor.java

@ -1,9 +1,10 @@
package com.visual.open.anpr.core.extract; package com.visual.open.anpr.server.extract;
import com.visual.open.anpr.server.domain.ExtParam;
import com.visual.open.anpr.server.domain.ImageMat;
import com.visual.open.anpr.server.domain.PlateImage;
import java.util.Map; import java.util.Map;
import com.visual.open.anpr.core.domain.ExtParam;
import com.visual.open.anpr.core.domain.ImageMat;
import com.visual.open.anpr.core.domain.PlateImage;
public interface PlateExtractor { public interface PlateExtractor {

16
open-anpr-core/src/main/java/com/visual/open/anpr/core/extract/PlateExtractorImpl.java → open-anpr-server/src/main/java/com/visual/open/anpr/server/extract/PlateExtractorImpl.java

@ -1,12 +1,12 @@
package com.visual.open.anpr.core.extract; package com.visual.open.anpr.server.extract;
import com.visual.open.anpr.core.base.PlateDetection; import com.visual.open.anpr.server.base.PlateDetection;
import com.visual.open.anpr.core.base.PlateRecognition; import com.visual.open.anpr.server.base.PlateRecognition;
import com.visual.open.anpr.core.domain.ExtParam; import com.visual.open.anpr.server.domain.ExtParam;
import com.visual.open.anpr.core.domain.ImageMat; import com.visual.open.anpr.server.domain.ImageMat;
import com.visual.open.anpr.core.domain.PlateImage; import com.visual.open.anpr.server.domain.PlateImage;
import com.visual.open.anpr.core.domain.PlateInfo; import com.visual.open.anpr.server.domain.PlateInfo;
import com.visual.open.anpr.core.utils.CropUtil; import com.visual.open.anpr.server.utils.CropUtil;
import org.opencv.core.Core; import org.opencv.core.Core;
import org.opencv.core.Mat; import org.opencv.core.Mat;

19
open-anpr-core/src/main/java/com/visual/open/anpr/core/models/TorchPlateDetection.java → open-anpr-server/src/main/java/com/visual/open/anpr/server/models/TorchPlateDetection.java

@ -1,14 +1,17 @@
package com.visual.open.anpr.core.models; package com.visual.open.anpr.server.models;
import ai.onnxruntime.OnnxTensor; import ai.onnxruntime.OnnxTensor;
import ai.onnxruntime.OrtSession; import ai.onnxruntime.OrtSession;
import com.visual.open.anpr.core.base.BaseOnnxInfer; import com.visual.open.anpr.server.base.BaseOnnxInfer;
import com.visual.open.anpr.core.base.PlateDetection; import com.visual.open.anpr.server.base.PlateDetection;
import com.visual.open.anpr.core.domain.ImageMat; import com.visual.open.anpr.server.domain.BorderMat;
import com.visual.open.anpr.core.domain.BorderMat; import com.visual.open.anpr.server.domain.ImageMat;
import com.visual.open.anpr.core.domain.PlateInfo; import com.visual.open.anpr.server.domain.PlateInfo;
import com.visual.open.anpr.core.utils.ReleaseUtil; import com.visual.open.anpr.server.utils.ReleaseUtil;
import org.opencv.core.*; import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.core.Scalar;
import org.opencv.core.Size;
import org.opencv.imgproc.Imgproc; import org.opencv.imgproc.Imgproc;
import java.util.*; import java.util.*;

19
open-anpr-core/src/main/java/com/visual/open/anpr/core/models/TorchPlateRecognition.java → open-anpr-server/src/main/java/com/visual/open/anpr/server/models/TorchPlateRecognition.java

@ -1,20 +1,21 @@
package com.visual.open.anpr.core.models; package com.visual.open.anpr.server.models;
import ai.onnxruntime.OnnxTensor; import ai.onnxruntime.OnnxTensor;
import ai.onnxruntime.OrtSession; import ai.onnxruntime.OrtSession;
import com.visual.open.anpr.core.base.BaseOnnxInfer; import com.visual.open.anpr.server.base.BaseOnnxInfer;
import com.visual.open.anpr.core.base.PlateRecognition; import com.visual.open.anpr.server.base.PlateRecognition;
import com.visual.open.anpr.core.domain.ImageMat; import com.visual.open.anpr.server.domain.ImageMat;
import com.visual.open.anpr.core.domain.PlateInfo.ParseInfo; import com.visual.open.anpr.server.domain.PlateInfo.ParseInfo;
import com.visual.open.anpr.core.utils.ArrayUtil; import com.visual.open.anpr.server.utils.ArrayUtil;
import com.visual.open.anpr.core.utils.MatUtil; import com.visual.open.anpr.server.utils.MatUtil;
import com.visual.open.anpr.core.utils.ReleaseUtil; import com.visual.open.anpr.server.utils.ReleaseUtil;
import com.visual.open.anpr.core.utils.SoftMaxUtil; import com.visual.open.anpr.server.utils.SoftMaxUtil;
import org.opencv.core.Mat; import org.opencv.core.Mat;
import org.opencv.core.Rect; import org.opencv.core.Rect;
import org.opencv.core.Scalar; import org.opencv.core.Scalar;
import org.opencv.core.Size; import org.opencv.core.Size;
import org.opencv.imgproc.Imgproc; import org.opencv.imgproc.Imgproc;
import java.util.Collections; import java.util.Collections;
import java.util.Map; import java.util.Map;

7
open-anpr-server/src/main/java/com/visual/open/anpr/server/service/impl/PlateServiceImpl.java

@ -1,10 +1,7 @@
package com.visual.open.anpr.server.service.impl; package com.visual.open.anpr.server.service.impl;
import com.visual.open.anpr.core.domain.ExtParam; import com.visual.open.anpr.server.extract.PlateExtractor;
import com.visual.open.anpr.core.domain.ImageMat; import com.visual.open.anpr.server.domain.*;
import com.visual.open.anpr.core.domain.PlateImage;
import com.visual.open.anpr.core.domain.PlateInfo;
import com.visual.open.anpr.core.extract.PlateExtractor;
import com.visual.open.anpr.server.domain.extend.*; import com.visual.open.anpr.server.domain.extend.*;
import com.visual.open.anpr.server.domain.request.PlateInfoReqVo; import com.visual.open.anpr.server.domain.request.PlateInfoReqVo;
import com.visual.open.anpr.server.domain.response.PlateInfoRepVo; import com.visual.open.anpr.server.domain.response.PlateInfoRepVo;

2
open-anpr-core/src/main/java/com/visual/open/anpr/core/utils/AlignUtil.java → open-anpr-server/src/main/java/com/visual/open/anpr/server/utils/AlignUtil.java

@ -1,4 +1,4 @@
package com.visual.open.anpr.core.utils; package com.visual.open.anpr.server.utils;
import org.apache.commons.math3.linear.RealMatrix; import org.apache.commons.math3.linear.RealMatrix;
import org.apache.commons.math3.linear.RealVector; import org.apache.commons.math3.linear.RealVector;

2
open-anpr-core/src/main/java/com/visual/open/anpr/core/utils/ArrayUtil.java → open-anpr-server/src/main/java/com/visual/open/anpr/server/utils/ArrayUtil.java

@ -1,4 +1,4 @@
package com.visual.open.anpr.core.utils; package com.visual.open.anpr.server.utils;
public class ArrayUtil { public class ArrayUtil {

4
open-anpr-core/src/main/java/com/visual/open/anpr/core/utils/CropUtil.java → open-anpr-server/src/main/java/com/visual/open/anpr/server/utils/CropUtil.java

@ -1,6 +1,6 @@
package com.visual.open.anpr.core.utils; package com.visual.open.anpr.server.utils;
import com.visual.open.anpr.core.domain.PlateInfo; import com.visual.open.anpr.server.domain.PlateInfo;
import org.opencv.core.CvType; import org.opencv.core.CvType;
import org.opencv.core.Mat; import org.opencv.core.Mat;
import org.opencv.core.Point; import org.opencv.core.Point;

324
open-anpr-server/src/main/java/com/visual/open/anpr/server/utils/FfmpegUtil.java

@ -0,0 +1,324 @@
package com.visual.open.anpr.server.utils;
import ws.schild.jave.Encoder;
import ws.schild.jave.EncoderException;
import ws.schild.jave.MultimediaObject;
import ws.schild.jave.encode.AudioAttributes;
import ws.schild.jave.encode.EncodingAttributes;
import ws.schild.jave.encode.VideoAttributes;
import ws.schild.jave.info.MultimediaInfo;
import ws.schild.jave.process.ProcessWrapper;
import ws.schild.jave.process.ffmpeg.DefaultFFMPEGLocator;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* @author ruibo.duan, <1573434995@qq.com>
* @since 2021/7/22
*/
public class FfmpegUtil {
/**
* 通过本地路径获取多媒体文件信息(时长编码等)
*
* @param localPath 本地路径
* @return MultimediaInfo 对象,包含 (时长编码等)
* @throws EncoderException
*/
public static MultimediaInfo getMultimediaInfo(String localPath) {
MultimediaInfo multimediaInfo = null;
try {
multimediaInfo = new MultimediaObject(new File(localPath)).getInfo();
} catch (EncoderException e) {
System.out.println("获取多媒体文件信息异常");
e.printStackTrace();
}
return multimediaInfo;
}
/**
// * 通过URL获取多媒体文件信息
*
* @param url 网络url
* @return MultimediaInfo 对象,包含 (时长编码等)
* @throws EncoderException
*/
public static MultimediaInfo getMultimediaInfoFromUrl(String url) {
MultimediaInfo multimediaInfo = null;
try {
multimediaInfo = new MultimediaObject(new URL(url)).getInfo();
} catch (Exception e) {
System.out.println("获取多媒体文件信息异常");
e.printStackTrace();
}
return multimediaInfo;
}
private static final int SAMPLING_RATE = 16000;
private static final int SINGLE_CHANNEL = 1;
/**
* 音频格式化为wav,并设置单声道和采样率
*
* @param url 需要转格式的音频
* @param targetPath 格式化后要保存的目标路径
*/
public static boolean formatAudio(String url, String targetPath) {
File target = new File(targetPath);
MultimediaObject multimediaObject;
try {
// 若是本地文件: multimediaObject = new MultimediaObject(new File("你的本地路径"));
multimediaObject = new MultimediaObject(new URL(url));
// 音频参数
// TODO: 2023/1/31 此处按需自定义音频参数
AudioAttributes audio = new AudioAttributes();
// 采样率
audio.setSamplingRate(SAMPLING_RATE);
// 单声道
audio.setChannels(SINGLE_CHANNEL);
Encoder encoder = new Encoder();
EncodingAttributes attrs = new EncodingAttributes();
// 输出格式
attrs.setOutputFormat("wav");
attrs.setAudioAttributes(audio);
encoder.encode(multimediaObject, target, attrs);
return true;
} catch (Exception e) {
System.out.println("格式化音频异常");
return false;
}
}
/**
* 视频格式化为mp4
*
* @param url
* @param targetPath
* @return
*/
public static boolean formatToMp4(String url, String targetPath) {
File target = new File(targetPath);
MultimediaObject multimediaObject;
try {
// 若是本地文件: multimediaObject = new MultimediaObject(new File("你的本地路径"));
multimediaObject = new MultimediaObject(new URL(url));
EncodingAttributes attributes = new EncodingAttributes();
// 设置视频的音频参数
AudioAttributes audioAttributes = new AudioAttributes();
attributes.setAudioAttributes(audioAttributes);
// 设置视频的视频参数
VideoAttributes videoAttributes = new VideoAttributes();
// 设置帧率
videoAttributes.setFrameRate(25);
attributes.setVideoAttributes(videoAttributes);
// 设置输出格式
attributes.setOutputFormat("mp4");
Encoder encoder = new Encoder();
encoder.encode(multimediaObject, target, attributes);
return true;
} catch (Exception e) {
System.out.println("格式化视频异常");
e.printStackTrace();
return false;
}
}
/**
* 获取视频缩略图 获取视频第0秒的第一帧图片
*
* <p>执行的ffmpeg 命令为 ffmpeg -i 你的视频文件路径 -ss 指定的秒数 生成文件的全路径地址
*
* @param localPath 本地路径
* @param targetPath 存放的目标路径
* @return
*/
public static boolean getTargetThumbnail(String localPath, String targetPath) {
// FIXME: 2023/1/31 该方法基本可作为执行ffmpeg命令的模板方法,之后的几个方法与此类似
try {
ProcessWrapper ffmpeg = new DefaultFFMPEGLocator().createExecutor();
ffmpeg.addArgument("-i");
ffmpeg.addArgument(localPath);
ffmpeg.addArgument("-ss");
// 此处可自定义视频的秒数
ffmpeg.addArgument("0");
ffmpeg.addArgument(targetPath);
ffmpeg.execute();
try (BufferedReader br = new BufferedReader(new InputStreamReader(ffmpeg.getErrorStream()))) {
blockFfmpeg(br);
}
} catch (IOException e) {
System.out.println("获取视频缩略图失败");
e.printStackTrace();
return false;
}
return true;
}
/**
* 抓拍实况
* @param localPath 实况地址
* @param targetPath 存放的目标路径
* @return 返回抓拍图片的文件名
*/
// 获取实况抓拍图片
public static String getLiveCapture(String localPath, String targetPath) {
String formattedDate ="";
try {
ProcessWrapper ffmpeg = new DefaultFFMPEGLocator().createExecutor();
ffmpeg.addArgument("-i");
ffmpeg.addArgument(localPath);
ffmpeg.addArgument("-vf");
// 加上 "select=eq(pict_type\,I)" -frames:v 1
ffmpeg.addArgument("select='eq(pict_type,I)'");
ffmpeg.addArgument("-frames:v");
ffmpeg.addArgument("1");
// 生成一个根据时间的文件名
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
// 获取当前时间
Date currentDate = new Date();
// 格式化时间为字符串
formattedDate = sdf.format(currentDate)+ ".jpg";
ffmpeg.addArgument(formattedDate);
ffmpeg.addArgument(targetPath + formattedDate);
ffmpeg.execute();
try (BufferedReader br = new BufferedReader(new InputStreamReader(ffmpeg.getErrorStream()))) {
blockFfmpeg(br);
}
} catch (IOException e) {
formattedDate = "获取实况抓拍图片失败";
System.out.println(formattedDate);
e.printStackTrace();
return formattedDate;
} return formattedDate;
}
/**
* 等待命令执行成功退出
*
* @param br
* @throws IOException
*/
private static void blockFfmpeg(BufferedReader br) throws IOException {
String line;
// 该方法阻塞线程,直至合成成功
while ((line = br.readLine()) != null) {
doNothing(line);
}
}
/**
* 打印日志
*
* @param line
*/
private static void doNothing(String line) {
// FIXME: 2023/1/31 正式使用时注释掉此行,仅用于观察日志
System.out.println(line);
}
/**
* 视频增加字幕
*
* @param originVideoPath 原视频地址
* @param targetVideoPath 目标视频地址
* @param srtPath 固定格式的srt文件地址或存储位置字母文件名 xxx.srt样例看博客
* @return
* @throws Exception
*/
public static boolean addSubtitle(
String originVideoPath, String srtPath, String targetVideoPath) {
try {
ProcessWrapper ffmpeg = new DefaultFFMPEGLocator().createExecutor();
ffmpeg.addArgument("-i");
ffmpeg.addArgument(originVideoPath);
ffmpeg.addArgument("-i");
ffmpeg.addArgument(srtPath);
ffmpeg.addArgument("-c");
ffmpeg.addArgument("copy");
ffmpeg.addArgument(targetVideoPath);
ffmpeg.execute();
try (BufferedReader br = new BufferedReader(new InputStreamReader(ffmpeg.getErrorStream()))) {
blockFfmpeg(br);
}
} catch (IOException e) {
System.out.println("字幕增加失败");
e.printStackTrace();
}
return true;
}
/**
* 常用命令
*
* @return
*/
public static void cmd() {
// FIXME: 2023/1/31 还有很多类似命令 不再一一列举 ,附上命令,具体写法参考 getTargetThumbnail或addSubtitle方法
// FIXME: 2023/1/31 ffmpeg命令网上搜索即可
// 剪切视频
// ffmpeg -ss 00:00:00 -t 00:00:30 -i test.mp4 -vcodec copy -acodec copy output.mp4
// * -ss 指定从什么时间开始
// * -t 指定需要截取多长时间
// * -i 指定输入文件
// ffmpeg -ss 10 -t 15 -accurate_seek -i test.mp4 -codec copy cut.mp4
// ffmpeg -ss 10 -t 15 -accurate_seek -i test.mp4 -codec copy -avoid_negative_ts 1 cut.mp4
// 拼接MP4
// 第一种方法:
// ffmpeg -i "concat:1.mp4|2.mp4|3.mp4" -codec copy out_mp4.mp4
// 1.mp4 第一个视频文件的全路径
// 2.mp4 第二个视频文件的全路径
// 提取视频中的音频
// ffmpeg -i input.mp4 -acodec copy -vn output.mp3
// -vn: 去掉视频;-acodec: 音频选项, 一般后面加copy表示拷贝
// 音视频合成
// ffmpeg -y –i input.mp4 –i input.mp3 –vcodec copy –acodec copy output.mp4
// -y 覆盖输出文件
// 剪切视频
// ffmpeg -ss 0:1:30 -t 0:0:20 -i input.mp4 -vcodec copy -acodec copy output.mp4
// -ss 开始时间; -t 持续时间
// 视频截图
// ffmpeg –i test.mp4 –f image2 -t 0.001 -s 320x240 image-%3d.jpg
// -s 设置分辨率; -f 强迫采用格式fmt;
// 视频分解为图片
// ffmpeg –i test.mp4 –r 1 –f image2 image-%3d.jpg
// -r 指定截屏频率
// 将图片合成视频
// ffmpeg -f image2 -i image%d.jpg output.mp4
// 视频拼接
// ffmpeg -f concat -i filelist.txt -c copy output.mp4
// 将视频转为gif
// ffmpeg -i input.mp4 -ss 0:0:30 -t 10 -s 320x240 -pix_fmt rgb24 output.gif
// -pix_fmt 指定编码
// 视频添加水印
// ffmpeg -i input.mp4 -i logo.jpg
// -filter_complex[0:v][1:v]overlay=main_w-overlay_w-10:main_h-overlay_h-10[out] -map [out] -map
// 0:a -codec:a copy output.mp4
// main_w-overlay_w-10 视频的宽度-水印的宽度-水印边距;
}
}

173
open-anpr-server/src/main/java/com/visual/open/anpr/server/utils/FileCopyUtil.java

@ -0,0 +1,173 @@
package com.visual.open.anpr.server.utils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import java.io.*;
@Slf4j
public class FileCopyUtil {
/**
* 复制path目录下所有文件
* @param path 文件目录 不能以/开头
* @param newpath 新文件目录
*/
public static void BatCopyFileFromJar(String path,String newpath) {
if (!new File(newpath).exists()){
new File(newpath).mkdir();
}
ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
try {
//获取所有匹配的文件
Resource[] resources = resolver.getResources(path+"/*");
//打印有多少文件
for(int i=0;i<resources.length;i++) {
Resource resource=resources[i];
try {
//以jar运行时,resource.getFile().isFile() 无法获取文件类型,会报异常,抓取异常后直接生成新的文件即可;以非jar运行时,需要判断文件类型,避免如果是目录会复制错误,将目录写成文件。
if(resource.getFile().isFile()) {
makeFile(newpath+"/"+resource.getFilename());
InputStream stream = resource.getInputStream();
write2File(stream, newpath+"/"+resource.getFilename());
}
}catch (Exception e) {
makeFile(newpath+"/"+resource.getFilename());
InputStream stream = resource.getInputStream();
write2File(stream, newpath+"/"+resource.getFilename());
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 创建文件
* @param path 全路径 指向文件
* @return
*/
public static boolean makeFile(String path) {
File file = new File(path);
if(file.exists()) {
return false;
}
if (path.endsWith(File.separator)) {
return false;
}
if(!file.getParentFile().exists()) {
if(!file.getParentFile().mkdirs()) {
return false;
}
}
try {
if (file.createNewFile()) {
return true;
} else {
return false;
}
} catch (IOException e) {
e.printStackTrace();
return false;
}
}
/**
* 输入流写入文件
*
* @param is
* 输入流
* @param filePath
* 文件保存目录路径
* @throws IOException
*/
public static void write2File(InputStream is, String filePath) throws IOException {
OutputStream os = new FileOutputStream(filePath);
int len = 8192;
byte[] buffer = new byte[len];
while ((len = is.read(buffer, 0, len)) != -1) {
os.write(buffer, 0, len);
}
os.close();
is.close();
}
/**
*处理异常报错springboot读取classpath里的文件解决打jar包java.io.FileNotFoundException: class path resource cannot be opened
**/
public static File getFileFromClassPath(String path){
File targetFile = new File(path);
if(!targetFile.exists()){
if(targetFile.getParent()!=null){
File parent=new File(targetFile.getParent());
if(!parent.exists()){
parent.mkdirs();
}
}
InputStream initialStream=null;
OutputStream outStream =null;
try {
Resource resource=new ClassPathResource(path);
//注意通过getInputStream,不能用getFile
initialStream=resource.getInputStream();
byte[] buffer = new byte[initialStream.available()];
initialStream.read(buffer);
outStream = new FileOutputStream(targetFile);
outStream.write(buffer);
} catch (IOException e) {
} finally {
if (initialStream != null) {
try {
initialStream.close(); // 关闭流
} catch (IOException e) {
}
}
if (outStream != null) {
try {
outStream.close(); // 关闭流
} catch (IOException e) {
}
}
}
}
return targetFile;
}
private static String userDir = System.getProperty("user.dir");
public static void copyHCNetSDKFromLinux(){
log.info("开始复制文件");
String linuxSOFolder1 = userDir + "/lib/hk/linux/";
String linuxSOFolder2 = userDir + "/lib/hk/linux/HKNetSDKCom/";
File fileFromClassPath1 = FileCopyUtil.getFileFromClassPath("/lib/hk/linux64/");
File fileFromClassPath2 = FileCopyUtil.getFileFromClassPath("/lib/hk/linux64/HCNetSDKCom/");
BatCopyFileFromJar(fileFromClassPath1.toString(),linuxSOFolder1);
BatCopyFileFromJar(fileFromClassPath2.toString(),linuxSOFolder2);
log.info("文件复制结束");
}
public static void copyHCNetSdkFromWindows(){
log.info("开始复制文件");
String WindowsDllFolder1 = userDir + "/models/";
File fileFromClassPath1 = FileCopyUtil.getFileFromClassPath("/models/");
BatCopyFileFromJar(fileFromClassPath1.toString(), WindowsDllFolder1);
log.info("文件复制结束");
}
public static <T> boolean isStartupFromJar() {
String protocol = FileCopyUtil.class.getResource("").getProtocol();
if ("jar".equals(protocol)){
return true;
}else {
return false;
}
}
}

140
open-anpr-server/src/main/java/com/visual/open/anpr/server/utils/FreeMarkerUtil.java

@ -0,0 +1,140 @@
package com.visual.open.anpr.server.utils;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import java.io.*;
/**
* @author:hahaha
* @creattime:2021-12-02 10:33
*/
public class FreeMarkerUtil {
/**
* 复制path目录下所有文件
* @param path 文件目录 不能以/开头
* @param newpath 新文件目录
*/
public static void BatCopyFileFromJar(String path,String newpath) {
if (!new File(newpath).exists()){
new File(newpath).mkdir();
}
ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
try {
//获取所有匹配的文件
Resource[] resources = resolver.getResources(path+"/*");
//打印有多少文件
for(int i=0;i<resources.length;i++) {
Resource resource=resources[i];
try {
//以jar运行时,resource.getFile().isFile() 无法获取文件类型,会报异常,抓取异常后直接生成新的文件即可;以非jar运行时,需要判断文件类型,避免如果是目录会复制错误,将目录写成文件。
if(resource.getFile().isFile()) {
makeFile(newpath+"/"+resource.getFilename());
InputStream stream = resource.getInputStream();
write2File(stream, newpath+"/"+resource.getFilename());
}
}catch (Exception e) {
makeFile(newpath+"/"+resource.getFilename());
InputStream stream = resource.getInputStream();
write2File(stream, newpath+"/"+resource.getFilename());
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 创建文件
* @param path 全路径 指向文件
* @return
*/
public static boolean makeFile(String path) {
File file = new File(path);
if(file.exists()) {
return false;
}
if (path.endsWith(File.separator)) {
return false;
}
if(!file.getParentFile().exists()) {
if(!file.getParentFile().mkdirs()) {
return false;
}
}
try {
if (file.createNewFile()) {
return true;
} else {
return false;
}
} catch (IOException e) {
e.printStackTrace();
return false;
}
}
/**
* 输入流写入文件
*
* @param is
* 输入流
* @param filePath
* 文件保存目录路径
* @throws IOException
*/
public static void write2File(InputStream is, String filePath) throws IOException {
OutputStream os = new FileOutputStream(filePath);
int len = 8192;
byte[] buffer = new byte[len];
while ((len = is.read(buffer, 0, len)) != -1) {
os.write(buffer, 0, len);
}
os.close();
is.close();
}
/**
*处理异常报错springboot读取classpath里的文件解决打jar包java.io.FileNotFoundException: class path resource cannot be opened
**/
public static File getFileFromClassPath(String path){
File targetFile = new File(path);
if(!targetFile.exists()){
if(targetFile.getParent()!=null){
File parent=new File(targetFile.getParent());
if(!parent.exists()){
parent.mkdirs();
}
}
InputStream initialStream=null;
OutputStream outStream =null;
try {
Resource resource=new ClassPathResource(path);
//注意通过getInputStream,不能用getFile
initialStream=resource.getInputStream();
byte[] buffer = new byte[initialStream.available()];
initialStream.read(buffer);
outStream = new FileOutputStream(targetFile);
outStream.write(buffer);
} catch (IOException e) {
} finally {
if (initialStream != null) {
try {
initialStream.close(); // 关闭流
} catch (IOException e) {
}
}
if (outStream != null) {
try {
outStream.close(); // 关闭流
} catch (IOException e) {
}
}
}
}
return targetFile;
}
}

82
open-anpr-server/src/main/java/com/visual/open/anpr/server/utils/ImageUtil.java

@ -0,0 +1,82 @@
package com.visual.open.anpr.server.utils;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.util.Base64;
public class ImageUtil {
/**
* 图片转Base64字符串
* @param imageFileName
* @return
*/
public static String convertImageToBase64Str(String imageFileName) {
ByteArrayOutputStream baos = null;
try {
//获取图片类型
String suffix = imageFileName.substring(imageFileName.lastIndexOf(".") + 1);
//构建文件
File imageFile = new File(imageFileName);
//通过ImageIO把文件读取成BufferedImage对象
BufferedImage bufferedImage = ImageIO.read(imageFile);
//构建字节数组输出流
baos = new ByteArrayOutputStream();
//写入流
ImageIO.write(bufferedImage, suffix, baos);
//通过字节数组流获取字节数组
byte[] bytes = baos.toByteArray();
//获取JDK8里的编码器Base64.Encoder转为base64字符
return Base64.getEncoder().encodeToString(bytes);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (baos != null) {
baos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
/**
* Base64字符串转图片
* @param base64String
* @param imageFileName
*/
public static void convertBase64StrToImage(String base64String, String imageFileName) {
ByteArrayInputStream bais = null;
try {
//获取图片类型
String suffix = imageFileName.substring(imageFileName.lastIndexOf(".") + 1);
//获取JDK8里的解码器Base64.Decoder,将base64字符串转为字节数组
byte[] bytes = Base64.getDecoder().decode(base64String);
//构建字节数组输入流
bais = new ByteArrayInputStream(bytes);
//通过ImageIO把字节数组输入流转为BufferedImage
BufferedImage bufferedImage = ImageIO.read(bais);
//构建文件
File imageFile = new File(imageFileName);
//写入生成文件
ImageIO.write(bufferedImage, suffix, imageFile);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (bais != null) {
bais.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

2
open-anpr-client/src/main/java/com/visual/open/anpr/utils/JsonUtil.java → open-anpr-server/src/main/java/com/visual/open/anpr/server/utils/JsonUtil.java

@ -1,4 +1,4 @@
package com.visual.open.anpr.utils; package com.visual.open.anpr.server.utils;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONArray;

2
open-anpr-core/src/main/java/com/visual/open/anpr/core/utils/MatUtil.java → open-anpr-server/src/main/java/com/visual/open/anpr/server/utils/MatUtil.java

@ -1,4 +1,4 @@
package com.visual.open.anpr.core.utils; package com.visual.open.anpr.server.utils;
import org.opencv.core.Mat; import org.opencv.core.Mat;
import org.opencv.core.Range; import org.opencv.core.Range;

2
open-anpr-core/src/main/java/com/visual/open/anpr/core/utils/MathUtil.java → open-anpr-server/src/main/java/com/visual/open/anpr/server/utils/MathUtil.java

@ -1,4 +1,4 @@
package com.visual.open.anpr.core.utils; package com.visual.open.anpr.server.utils;
import org.apache.commons.math3.linear.Array2DRowRealMatrix; import org.apache.commons.math3.linear.Array2DRowRealMatrix;
import org.apache.commons.math3.linear.ArrayRealVector; import org.apache.commons.math3.linear.ArrayRealVector;

6
open-anpr-core/src/main/java/com/visual/open/anpr/core/utils/ReleaseUtil.java → open-anpr-server/src/main/java/com/visual/open/anpr/server/utils/ReleaseUtil.java

@ -1,9 +1,9 @@
package com.visual.open.anpr.core.utils; package com.visual.open.anpr.server.utils;
import ai.onnxruntime.OnnxTensor; import ai.onnxruntime.OnnxTensor;
import ai.onnxruntime.OrtSession; import ai.onnxruntime.OrtSession;
import com.visual.open.anpr.core.domain.BorderMat; import com.visual.open.anpr.server.domain.BorderMat;
import com.visual.open.anpr.core.domain.ImageMat; import com.visual.open.anpr.server.domain.ImageMat;
import org.opencv.core.Mat; import org.opencv.core.Mat;
public class ReleaseUtil { public class ReleaseUtil {

2
open-anpr-core/src/main/java/com/visual/open/anpr/core/utils/SigmoidUtil.java → open-anpr-server/src/main/java/com/visual/open/anpr/server/utils/SigmoidUtil.java

@ -1,4 +1,4 @@
package com.visual.open.anpr.core.utils; package com.visual.open.anpr.server.utils;
import java.util.function.DoubleUnaryOperator; import java.util.function.DoubleUnaryOperator;

4
open-anpr-core/src/main/java/com/visual/open/anpr/core/utils/Similarity.java → open-anpr-server/src/main/java/com/visual/open/anpr/server/utils/Similarity.java

@ -1,9 +1,7 @@
package com.visual.open.anpr.core.utils; package com.visual.open.anpr.server.utils;
import org.apache.commons.math3.linear.RealMatrix; import org.apache.commons.math3.linear.RealMatrix;
import com.visual.open.anpr.core.utils.ArrayUtil;
public class Similarity { public class Similarity {
/** /**

2
open-anpr-core/src/main/java/com/visual/open/anpr/core/utils/SoftMaxUtil.java → open-anpr-server/src/main/java/com/visual/open/anpr/server/utils/SoftMaxUtil.java

@ -1,4 +1,4 @@
package com.visual.open.anpr.core.utils; package com.visual.open.anpr.server.utils;
import java.util.Arrays; import java.util.Arrays;
import java.util.NoSuchElementException; import java.util.NoSuchElementException;

2
open-anpr-core/src/main/java/com/visual/open/anpr/core/utils/ThreadUtil.java → open-anpr-server/src/main/java/com/visual/open/anpr/server/utils/ThreadUtil.java

@ -1,4 +1,4 @@
package com.visual.open.anpr.core.utils; package com.visual.open.anpr.server.utils;
public class ThreadUtil { public class ThreadUtil {

170
open-anpr-server/src/main/java/com/visual/open/anpr/server/utils/VideoUtil.java

@ -0,0 +1,170 @@
//package com.visual.open.anpr.server.utils;
//
//import org.bytedeco.ffmpeg.avcodec.AVCodecParameters;
//import org.bytedeco.ffmpeg.avformat.AVFormatContext;
//import org.bytedeco.ffmpeg.avformat.AVStream;
//import org.bytedeco.ffmpeg.global.avcodec;
//import org.bytedeco.javacv.*;
//import org.springframework.beans.factory.annotation.Value;
//
//import java.util.logging.Logger;
//
//
//public class VideoUtil {
//
// @Value("3")
// private Integer retryCount;//重试次数,默认值
// @Value("100")
// private Integer sleepTime;//休眠时间,默认值
//
// private static final Logger logger = Logger.getLogger(VideoUtil.class.getName());
// /**
// * 视频转码函数(仅转码)
// *
// * @param inputfile 原始视频文件完整路径
// * @param outputfile 目标视频文件完整保存路径(必须完整文件名,即包含格式后缀,推荐格式后缀为.mp4)
// * @throws Exception 异常
// */
// public static void videoConvert(String inputfile, String outputfile, Integer retryCount, Integer sleepTime) throws Exception {
// if (outputfile.lastIndexOf('.') < 0) {
// throw new Exception("Error! Output file format undetected!");
// }
// String format = outputfile.substring(outputfile.lastIndexOf('.'));
//
// FFmpegLogCallback.set();
// Frame frame;
// FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(inputfile);
// FFmpegFrameRecorder recorder = null;
//
// try {
// long start = System.currentTimeMillis();
// logger.info("视频存储开始:"+ DateUtil.getCurrentDateTime());
// logger.info("开始初始化帧抓取器");
// // 初始化帧抓取器,例如数据结构(时间戳、编码器上下文、帧对象等),
// // 如果入参等于true,还会调用avformat_find_stream_info方法获取流的信息,放入AVFormatContext类型的成员变量oc中
// grabber.start(true);
//
// logger.info("帧抓取器初始化完成");
//
// // grabber.start方法中,初始化的解码器信息存在放在grabber的成员变量oc中
// AVFormatContext avformatcontext = grabber.getFormatContext();
//
// // 文件内有几个媒体流(一般是视频流+音频流)
// int streamNum = avformatcontext.nb_streams();
//
// // 没有媒体流就不用继续了
// if (streamNum < 1)
// {
// logger.info("文件内不存在媒体流");
// throw new Exception("Error! There is no media stream in the file!");
// }
//
// // 取得视频的帧率
// double framerate = grabber.getVideoFrameRate();
//
// System.out.printf("视频帧率[%f],视频时长[%d]秒,媒体流数量[%d]\r\n", framerate, avformatcontext.duration() / 1000000,
// avformatcontext.nb_streams());
//
// // 遍历每一个流,检查其类型
// for (int i = 0; i < streamNum; i++) {
// AVStream avstream = avformatcontext.streams(i);
// AVCodecParameters avcodecparameters = avstream.codecpar();
// System.out.printf("流的索引[%d],编码器类型[%d],编码器ID[%d]\r\n", i, avcodecparameters.codec_type(),
// avcodecparameters.codec_id());
// }
//
// // 视频宽度
// int frameWidth = grabber.getImageWidth();
// // 视频高度
// int frameHeight = grabber.getImageHeight();
// // 音频通道数量
// int audiochannels = grabber.getAudioChannels();
//
// System.out.printf("视频宽度[%d],视频高度[%d],音频通道数[%d]\r\n", frameWidth, frameHeight, audiochannels);
//
// recorder = new FFmpegFrameRecorder(outputfile, frameWidth, frameHeight, audiochannels);
// recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264);
//
// recorder.setFormat(format);
// // 使用原始视频的码率,若需要则自行修改码率
// recorder.setVideoBitrate(grabber.getVideoBitrate());
//
// // 一秒内的帧数,帧率
// recorder.setFrameRate(framerate);
//
// // 两个关键帧之间的帧数
// recorder.setGopSize((int)framerate);
//
// // 设置音频通道数,与视频源的通道数相等
// recorder.setAudioChannels(grabber.getAudioChannels());
//
// recorder.start();
//
// int videoframenum = 0;
// int audioframenum = 0;
// int dataframenum = 0;
//
// logger.info("开始录制\r\n");
//
// // 循环条件
// int count = 0;
//
// // 持续从视频源取帧
// while (true) {
// frame = grabber.grab();
// if (frame != null) {
// // 有图像,就把视频帧加一
// if (null != frame.image) {
// videoframenum++;
// // 取出的每一帧,都保存到视频
// recorder.record(frame);
// }
// // 有声音,就把音频帧加一
// if (null != frame.samples) {
// audioframenum++;
// // 取出的每一帧,都保存到视频
// recorder.record(frame);
// }
// // 有数据,就把数据帧加一
// if (null != frame.data) {
// dataframenum++;
// }
// count = 0;
// }else {
// if (retryCount == null || retryCount == 0) {
// break;
// }
// if (count > retryCount) {
// break;
// }
// if (sleepTime != null && sleepTime > 0) {
// // 休眠一段时间后重试
// Thread.sleep(sleepTime);
// }
// count ++;
// }
// }
// long end = System.currentTimeMillis();
// long second = (end - start) / 1000;
// logger.info("视频存储结束:"+ DateUtil.getCurrentDateTime());
// logger.info("视频存储总耗时(秒):"+ second);
// System.out.printf("转码完成,视频帧[%d],音频帧[%d],数据帧[%d]\r\n", videoframenum, audioframenum, dataframenum);
// logger.info("转码完成,视频帧"+videoframenum+",音频帧" + audioframenum + ",数据帧" + dataframenum);
// } catch (Exception e) {
// e.printStackTrace();
// } finally {
// if (recorder != null) {
// try {
// recorder.close();
// } catch (Exception e) {
// e.printStackTrace();
// }
// }
// try {
// grabber.close();
// } catch (FrameGrabber.Exception e) {
// e.printStackTrace();
// }
// }
// }
//}

2
open-anpr-server/src/main/resources/application-local.yml

@ -1,7 +1,7 @@
# 开发环境配置 # 开发环境配置
server: server:
# 服务器的HTTP端口,默认为80 # 服务器的HTTP端口,默认为80
port: 8080 port: 1115
servlet: servlet:
# 应用的访问路径 # 应用的访问路径
context-path: / context-path: /

0
open-anpr-core/src/main/resources/models/plate_detect.onnx → open-anpr-server/src/main/resources/models/plate_detect.onnx

0
open-anpr-core/src/main/resources/models/plate_rec_color.onnx → open-anpr-server/src/main/resources/models/plate_rec_color.onnx

32
open-anpr-test/pom.xml

@ -1,32 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.visual.open.anpr</groupId>
<artifactId>open-anpr-test</artifactId>
<version>1.1.0</version>
<properties>
<java.version>1.8</java.version>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>com.visual.open.anpr</groupId>
<artifactId>open-anpr-client</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.openpnp</groupId>
<artifactId>opencv</artifactId>
<version>4.6.0-0</version>
</dependency>
</dependencies>
</project>

84
open-anpr-test/src/main/java/com/visual/open/anpr/exps/PlateRecognitionExample.java

@ -1,84 +0,0 @@
package com.visual.open.anpr.exps;
import com.visual.open.anpr.PlateRecognition;
import com.visual.open.anpr.model.*;
import com.visual.open.anpr.utils.Base64Util;
import com.visual.open.anpr.utils.DrawImage;
import org.opencv.highgui.HighGui;
import java.awt.*;
import java.io.File;
import java.util.List;
import java.util.Objects;
public class PlateRecognitionExample {
static{ nu.pattern.OpenCV.loadShared(); }
//本地开发模式
public static String serverHost = "http://127.0.0.1:8080";
//docker部署模式
//public static String serverHost = "http://127.0.0.1:56790";
//远程测试服务
//public static String serverHost = "http://open-anpr.diven.nat300.top";
public static PlateRecognition plateRecognition = PlateRecognition.build(serverHost);
/**搜索*/
public static void recognition() {
String searchPath = "open-anpr-test/src/main/resources/image";
File [] files = Objects.requireNonNull(new File(searchPath).listFiles());
System.out.println(files.length);
for(int i=0; i < files.length; i++){
System.out.println(i);
File imageA = files[i];
String imageBase64 = Base64Util.encode(imageA.getAbsolutePath());
Response<List<RecognitionRep>> response = plateRecognition.detection().recognition(
Recognition.build().setImage(imageBase64).setLimit(5)
);
DrawImage drawImage = DrawImage.build(imageA.getAbsolutePath());
if(response.ok()){
for(RecognitionRep recognitionRep : response.getData()){
//画位置信息
PlateLocation location = recognitionRep.getLocation();
drawImage.drawLine(
new DrawImage.Point(location.getLeftTop().getX(), location.getLeftTop().getY()),
new DrawImage.Point(location.getRightTop().getX(), location.getRightTop().getY()),
2, Color.RED
);
drawImage.drawLine(
new DrawImage.Point(location.getRightTop().getX(), location.getRightTop().getY()),
new DrawImage.Point(location.getRightBottom().getX(), location.getRightBottom().getY()),
2, Color.RED
);
drawImage.drawLine(
new DrawImage.Point(location.getRightBottom().getX(), location.getRightBottom().getY()),
new DrawImage.Point(location.getLeftBottom().getX(), location.getLeftBottom().getY()),
2, Color.RED
);
drawImage.drawLine(
new DrawImage.Point(location.getLeftBottom().getX(), location.getLeftBottom().getY()),
new DrawImage.Point(location.getLeftTop().getX(), location.getLeftTop().getY()),
2, Color.RED
);
//画识别信息
RecognitionInfo recognition = recognitionRep.getRecognition();
int fonSize = Float.valueOf(1.4f * location.width() / recognition.getPlateNo().length()).intValue();
drawImage.drawText(recognition.getPlateNo(),
new DrawImage.Point(location.minX(), location.minY()-(int)(fonSize*2.2)), fonSize, Color.RED);
drawImage.drawText((recognition.getLayout() == PlateLayout.SINGLE ? "单排" : "双排") + ":" + recognition.getPlateColor().getName(),
new DrawImage.Point(location.minX(), location.minY()-(int)(fonSize*1.2)), fonSize, Color.RED);
}
}
HighGui.imshow("image", drawImage.toMat());
HighGui.waitKey();
}
//退出程序
System.exit(1);
}
/**main**/
public static void main(String[] args) {
recognition();
}
}

107
open-anpr-test/src/main/java/com/visual/open/anpr/utils/MatUtil.java

@ -1,107 +0,0 @@
package com.visual.open.anpr.utils;
import org.opencv.core.Mat;
import org.opencv.core.Range;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.util.Base64;
import java.util.Objects;
public class MatUtil {
/**
* 将Mat转换为BufferedImage
* @param mat
* @return BufferedImage
*/
public static BufferedImage matToBufferedImage(Mat mat) {
int dataSize = mat.cols() * mat.rows() * (int) mat.elemSize();
byte[] data = new byte[dataSize];
mat.get(0, 0, data);
int type = mat.channels() == 1 ? BufferedImage.TYPE_BYTE_GRAY : BufferedImage.TYPE_3BYTE_BGR;
if (type == BufferedImage.TYPE_3BYTE_BGR) {
for (int i = 0; i < dataSize; i += 3) {
byte blue = data[i + 0];
data[i + 0] = data[i + 2];
data[i + 2] = blue;
}
}
BufferedImage image = new BufferedImage(mat.cols(), mat.rows(), type);
image.getRaster().setDataElements(0, 0, mat.cols(), mat.rows(), data);
return image;
}
/**
* 将Mat转换为 Base64
* @param mat
* @return Base64
*/
public static String matToBase64(Mat mat) {
ByteArrayOutputStream byteArrayOutputStream = null;
try {
byteArrayOutputStream = new ByteArrayOutputStream();
ImageIO.write(matToBufferedImage(mat), "jpg", byteArrayOutputStream);
byte[] bytes = byteArrayOutputStream.toByteArray();
Base64.Encoder encoder = Base64.getMimeEncoder();
return encoder.encodeToString(Objects.requireNonNull(bytes));
}catch (Exception e){
throw new RuntimeException(e);
}finally {
if(null != byteArrayOutputStream){
try {
byteArrayOutputStream.close();
} catch (Exception e) {}
}
}
}
public static Mat concat(Mat m1, Mat ...m2){
Mat mat = m1;
if(null != m2){
for(Mat m : m2){
mat = concat(mat, m1);
}
}
return mat;
}
/**
* 横向拼接两个图像的数据Mat该两个图像的类型必须是相同的类型均为CvType.CV_8UC3类型
* @author bailichun
* @since 2020.02.20 15:00
* @param m1 要合并的图像1左图
* @param m2 要合并的图像2右图
* @return 拼接好的Mat图像数据集其高度等于两个图像中高度较大者的高度其宽度等于两个图像的宽度之和类型与两个输入图像相同
* @throws Exception 当两个图像数据的类型不同时抛出异常
*/
public static Mat concat(Mat m1, Mat m2){
if(m1.type() != m2.type()){
throw new RuntimeException("concat:两个图像数据的类型不同!");
}
long time = System.currentTimeMillis();
//宽度为两图的宽度之和
double w = m1.size().width + m2.size().width;
//高度取两个矩阵中的较大者的高度
double h = m1.size().height > m2.size().height ? m1.size().height : m2.size().height;
//创建一个大矩阵对象
Mat des = Mat.zeros((int)h, (int)w, m1.type());
//在最终的大图上标记一块区域,用于存放复制图1(左图)的数据,大小为从第0列到m1.cols()列
Mat rectForM1 = des.colRange(new Range(0, m1.cols()));
//标记出位于rectForM1的垂直方向上中间位置的区域,高度为图1的高度,此时该区域的大小已经和图1的大小相同。(用于存放复制图1(左图)的数据)
int rowOffset1 = (int)(rectForM1.size().height-m1.rows())/2;
rectForM1 = rectForM1.rowRange(rowOffset1, rowOffset1 + m1.rows());
//在最终的大图上标记一块区域,用于存放复制图2(右图)的数据
Mat rectForM2 = des.colRange(new Range(m1.cols(), des.cols()));
//标记出位于rectForM2的垂直方向上中间位置的区域,高度为图2的高度,此时该区域的大小已经和图2的大小相同。(用于存放复制图2(右图)的数据)
int rowOffset2 = (int)(rectForM2.size().height-m2.rows())/2;
rectForM2 = rectForM2.rowRange(rowOffset2, rowOffset2 + m2.rows());
//将图1拷贝到des的指定区域 rectForM1
m1.copyTo(rectForM1);
//将图2拷贝到des的指定区域 rectForM2
m2.copyTo(rectForM2);
return des;
}
}

BIN
open-anpr-test/src/main/resources/image/image001.jpg

Binary file not shown.

Before

Width:  |  Height:  |  Size: 107 KiB

BIN
open-anpr-test/src/main/resources/image/image002.jpg

Binary file not shown.

Before

Width:  |  Height:  |  Size: 64 KiB

BIN
open-anpr-test/src/main/resources/image/image003.jpg

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

BIN
open-anpr-test/src/main/resources/image/image004.jpg

Binary file not shown.

Before

Width:  |  Height:  |  Size: 390 KiB

BIN
open-anpr-test/src/main/resources/image/image005.jpg

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

BIN
open-anpr-test/src/main/resources/image/image006.jpg

Binary file not shown.

Before

Width:  |  Height:  |  Size: 64 KiB

BIN
open-anpr-test/src/main/resources/image/image007.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 671 KiB

BIN
open-anpr-test/src/main/resources/image/image008.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 328 KiB

BIN
open-anpr-test/src/main/resources/image/image009.jpg

Binary file not shown.

Before

Width:  |  Height:  |  Size: 382 KiB

BIN
open-anpr-test/src/main/resources/image/image010.jpg

Binary file not shown.

Before

Width:  |  Height:  |  Size: 85 KiB

BIN
open-anpr-test/src/main/resources/image/image011.jpg

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

BIN
open-anpr-test/src/main/resources/image/image012.jpg

Binary file not shown.

Before

Width:  |  Height:  |  Size: 999 KiB

BIN
open-anpr-test/src/main/resources/image/image013.jpg

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

BIN
open-anpr-test/src/main/resources/image/image014.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 400 KiB

BIN
open-anpr-test/src/main/resources/image1/75a6f232_7346047.jpeg

Binary file not shown.

Before

Width:  |  Height:  |  Size: 659 KiB

BIN
open-anpr-test/src/main/resources/image1/c4145e27_7346047.jpeg

Binary file not shown.

Before

Width:  |  Height:  |  Size: 82 KiB

BIN
open-anpr-test/src/main/resources/image1/f7759908_7346047.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 979 KiB

3
pom.xml

@ -17,10 +17,7 @@
<version>1.1.0</version> <version>1.1.0</version>
<modules> <modules>
<module>open-anpr-core</module>
<module>open-anpr-server</module> <module>open-anpr-server</module>
<module>open-anpr-test</module>
<module>open-anpr-client</module>
</modules> </modules>
<properties> <properties>

Loading…
Cancel
Save