
@ -0,0 +1,30 @@ |
|||
<?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.0.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> |
@ -0,0 +1,47 @@ |
|||
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); |
|||
} |
|||
|
|||
|
|||
} |
@ -0,0 +1,12 @@ |
|||
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; |
|||
} |
|||
|
|||
} |
@ -0,0 +1,63 @@ |
|||
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>>>() {}); |
|||
} |
|||
|
|||
} |
@ -0,0 +1,207 @@ |
|||
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); |
|||
} |
|||
} |
|||
|
|||
} |
@ -0,0 +1,4 @@ |
|||
package com.visual.open.anpr.http; |
|||
|
|||
public class HttpClientResult { |
|||
} |
@ -0,0 +1,455 @@ |
|||
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(); |
|||
} |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,17 @@ |
|||
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; |
|||
} |
|||
|
|||
} |
@ -0,0 +1,31 @@ |
|||
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; |
|||
} |
|||
|
|||
} |
@ -0,0 +1,8 @@ |
|||
package com.visual.open.anpr.model; |
|||
|
|||
public enum PlateLayout { |
|||
|
|||
SINGLE, //单排
|
|||
DOUBLE, //双排
|
|||
UNKNOWN; //未知
|
|||
} |
@ -0,0 +1,66 @@ |
|||
package com.visual.open.anpr.model; |
|||
|
|||
import java.io.Serializable; |
|||
|
|||
public class PlateLocation implements Serializable { |
|||
/**左上角x坐标**/ |
|||
private int x; |
|||
/**左上角y坐标**/ |
|||
private int y; |
|||
/**宽度**/ |
|||
private int w; |
|||
/**高度**/ |
|||
private int h; |
|||
|
|||
/** |
|||
* 构建坐标 |
|||
* @param x |
|||
* @param y |
|||
* @param w |
|||
* @param h |
|||
* @return |
|||
*/ |
|||
public static PlateLocation build(int x, int y, int w, int h){ |
|||
return new PlateLocation().setX(x).setY(y).setW(w).setH(h); |
|||
} |
|||
|
|||
public static PlateLocation build(float x, float y, float w, float h){ |
|||
return new PlateLocation().setX((int) x).setY((int) y).setW((int) w).setH((int) h); |
|||
} |
|||
|
|||
public int getX() { |
|||
return x; |
|||
} |
|||
|
|||
public PlateLocation setX(int x) { |
|||
this.x = x; |
|||
return this; |
|||
} |
|||
|
|||
public int getY() { |
|||
return y; |
|||
} |
|||
|
|||
public PlateLocation setY(int y) { |
|||
this.y = y; |
|||
return this; |
|||
} |
|||
|
|||
public int getW() { |
|||
return w; |
|||
} |
|||
|
|||
public PlateLocation setW(int w) { |
|||
this.w = w; |
|||
return this; |
|||
} |
|||
|
|||
public int getH() { |
|||
return h; |
|||
} |
|||
|
|||
public PlateLocation setH(int h) { |
|||
this.h = h; |
|||
return this; |
|||
} |
|||
} |
@ -0,0 +1,40 @@ |
|||
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; |
|||
} |
|||
|
|||
} |
@ -0,0 +1,36 @@ |
|||
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; |
|||
} |
|||
} |
@ -0,0 +1,40 @@ |
|||
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; |
|||
} |
|||
|
|||
} |
@ -0,0 +1,13 @@ |
|||
package com.visual.open.anpr.model; |
|||
|
|||
public class RecognitionReq extends Recognition<RecognitionReq>{ |
|||
|
|||
/** |
|||
* 构建比对对象 |
|||
* @return |
|||
*/ |
|||
public static RecognitionReq build(){ |
|||
return new RecognitionReq(); |
|||
} |
|||
|
|||
} |
@ -0,0 +1,62 @@ |
|||
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 + '}'; |
|||
} |
|||
} |
@ -0,0 +1,48 @@ |
|||
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); |
|||
} |
|||
} |
|||
|
|||
} |
@ -0,0 +1,128 @@ |
|||
package com.visual.open.anpr.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); |
|||
} |
|||
|
|||
} |
|||
|
@ -0,0 +1,38 @@ |
|||
package com.visual.open.anpr.server.domain.extend; |
|||
|
|||
import io.swagger.annotations.ApiModelProperty; |
|||
|
|||
import java.io.Serializable; |
|||
|
|||
public class LocationPoint implements Serializable { |
|||
|
|||
/**坐标X的值**/ |
|||
@ApiModelProperty(value="坐标X的值", position = 1, required = true) |
|||
private int x; |
|||
/**坐标Y的值**/ |
|||
@ApiModelProperty(value="坐标Y的值", position = 2, required = true) |
|||
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; |
|||
} |
|||
} |
@ -0,0 +1,32 @@ |
|||
<?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.0.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> |
@ -0,0 +1,65 @@ |
|||
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()); |
|||
for(int i=0; i< files.length-1; 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.drawRect( |
|||
new DrawImage.Rect(location.getX(), location.getY(), location.getW(), location.getH()), 2, Color.RED); |
|||
|
|||
|
|||
RecognitionInfo recognition = recognitionRep.getRecognition(); |
|||
int fonSize = Float.valueOf(1.4f * location.getW() / recognition.getPlateNo().length()).intValue(); |
|||
drawImage.drawText(recognition.getPlateNo(), |
|||
new DrawImage.Point(location.getX(), location.getY()-(int)(fonSize*2.2)), fonSize, Color.RED); |
|||
drawImage.drawText((recognition.getLayout() == PlateLayout.SINGLE ? "单排" : "双排") + ":" + recognition.getPlateColor().getName(), |
|||
new DrawImage.Point(location.getX(), location.getY()-(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(); |
|||
} |
|||
|
|||
} |
@ -0,0 +1,124 @@ |
|||
package com.visual.open.anpr.utils; |
|||
|
|||
|
|||
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 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; |
|||
} |
|||
} |
|||
|
|||
} |
@ -0,0 +1,107 @@ |
|||
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; |
|||
} |
|||
|
|||
} |
After Width: | Height: | Size: 107 KiB |
After Width: | Height: | Size: 64 KiB |
After Width: | Height: | Size: 40 KiB |
After Width: | Height: | Size: 390 KiB |
After Width: | Height: | Size: 47 KiB |
After Width: | Height: | Size: 64 KiB |
After Width: | Height: | Size: 671 KiB |
After Width: | Height: | Size: 328 KiB |
After Width: | Height: | Size: 382 KiB |
After Width: | Height: | Size: 85 KiB |
After Width: | Height: | Size: 29 KiB |
After Width: | Height: | Size: 999 KiB |
After Width: | Height: | Size: 34 KiB |
After Width: | Height: | Size: 400 KiB |