OCR(Optical Character Recognition,光学字符识别)又称文字识别,文字识别下面又可以分为身份证识别、名片识别、行驶证识别、发票识别等等;车牌识别是OCR中的一种。百度云、华为云、阿里云都有提供这方面的应用。每家的服务都有其自己的特点,这里记录一下是如何调用华为云的车牌识别功能的,从应用的申请,到把代码加入到自己的项目里。
第一步,来到华为云文字识别OCR专栏;
文字识别OCR属于EI企业智能下的子类目,在华为云官网,通过导航 EI企业智能 来到文字识别OCR专栏;
第二步,点击SDK下载,来到下载页面;
我们使用的是Java语言,下载Java语言对应的jar包即可;
第三步,解压下载的架包,导入到开发工具里;
选中其一,导入到自己的开发工具里,这里使用的maven,导入的也是maven版本的。
第四步,用自己拥有的华为云账号,开启车牌识别应用;
在对应的服务里找到车牌识别点击开启;
第五步,查看文档,看看车牌识别服务是如何调用的;
https://support.huaweicloud.com/api-ocr/ocr_03_0040.html
这个页面里面的文档挺多,以下几篇,建议多看一看,以便对对接有个全面的了解;
使用SDK(Java)
调用SDK有两种方式:一种是通过Token,token有效期24小时;另一种是通过AK/SK,只能用于小于12M的请求体;
备注说明:这个很重要,你需要根据自己的应用权衡调用的方式;
第六步,加密参数的获取及线上测试;
怎么获取token:https://support.huaweicloud.com/api-iam/iam_30_0001.html
申请方法:https://support.huaweicloud.com/iam_faq/iam_01_034.html
线上测试的地址,需要在登录的情况下才能访问;
https://apiexplorer.developer.huaweicloud.com/apiexplorer/debug?product=OCR&api=LicensePlate
这里有个地方需要注意:
image的参数,必须填写base64位加过密的才可以测试成功,其他的参数token、AK/SK,系统默认获取已经配置好的。
第七步,通过demo调用api,回到项目里,看看如何调用;
在项目里,有一个OCRdemo类,在这个类里,有两个demo,一个是通过token的方式调用身份证识别接口,另一个通过AK/SK的方式调用身份证识别接口。
没有车牌识别的demo,把身份证识别的改写一下,这里使用AK/SK方式调用;
package com.test.huawei;
import java.io.IOException;
import java.net.URISyntaxException;
import org.apache.commons.io.IOUtils;
import org.apache.http.HttpResponse;
import com.alibaba.fastjson.JSONObject;
import com.test.huawei.ocr.HWOcrClientAKSK;
/**
*
* @author 程就人生
* @date 2020年9月23日
* @Description
*
*/
public class OCRDemo {
public static void main(String[] args) throws URISyntaxException, UnsupportedOperationException, IOException{
//需要识别的图片路径,可以是绝对路径,也可以是相对路径,还可以是url地址
String imgPath = "./data/aaa.jpg";
carAKSKDemo2(imgPath);
}
/**
* 车牌识别demo
* @throws URISyntaxException
* @throws UnsupportedOperationException
* @throws IOException
*/
public static void carAKSKDemo2(String imgPath) throws URISyntaxException, UnsupportedOperationException, IOException{
/*
* AK/SK demo code
* */
String AK="你的AK"; //AK from authentication
String SK="你的SK"; //SK from authentication
String regionName="cn-north-4"; //region name of the service
String httpUri = "/v1.0/ocr/license-plate";
JSONObject params = new JSONObject();
try {
HWOcrClientAKSK ocrClient=new HWOcrClientAKSK(regionName, AK, SK);
HttpResponse response=ocrClient.RequestOcrServiceBase64(httpUri, imgPath, params);
System.out.println(response);
String content = IOUtils.toString(response.getEntity().getContent(), "utf-8");
System.out.println(content);
}
catch (Exception e) {
e.printStackTrace();
}
}
}
在data文件夹里加入含有车牌号的图片;
第八步,抽离代码;
我们要把这个功能加到自己的项目里,先看看这个demo里引入了哪几个文件,
pom.xml文件中需要添加华为的镜像,以便引入华为的架包;
<!-- 华为的镜像 -->
<repositories>
<repository>
<id>huaweicloud</id> <url>https://mirrors.huaweicloud.com/repository/maven/huaweicloudsdk/</url>
</repository>
</repositories>
<!-- 文字识别所需架包 -->
<dependency>
<groupId>com.huawei.hwclouds.ais</groupId>
<artifactId>ais-java-client</artifactId>
<version>2.0.0</version>
</dependency>
工具类需要两个,这里不使用token,就把token的工具类忽略;
package com.test.huawei.ocr;
import com.alibaba.fastjson.JSONObject;
import com.huawei.ais.common.AuthInfo;
import com.huawei.ais.common.ProxyHostInfo;
import com.huawei.ais.sdk.AisAccess;
import com.huawei.ais.sdk.AisAccessWithProxy;
import com.huawei.ais.sdk.util.HttpClientUtils;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.FileUtils;
import org.apache.http.HttpResponse;
import org.apache.http.entity.StringEntity;
import java.io.File;
import java.io.IOException;
public class HWOcrClientAKSK {
private AuthInfo HEC_AUTH; //Authorization Information
private AisAccess HttpService; //access to ocr service on cloud
private ProxyHostInfo PROXYINFO; //proxy host info (optional)
static {
HttpClientUtils.DEFAULT_CONNECTION_TIMEOUT = 15000;
HttpClientUtils.DEFAULT_CONNECTION_REQUEST_TIMEOUT = 15000;
HttpClientUtils.DEFAULT_SOCKET_TIMEOUT = 15000;
}
/**
* Constructor for OcrClientAKSK without proxy
* @param Endpoint HTTPEndPoint for OCR Service
* @param Region The region info for OCR Service
* @param YourAK The Access Key from Authentication
* @param YourSK The Secret Key from Authentication
* */
public HWOcrClientAKSK(String Region,String YourAK,String YourSK) {
if (Region == null| Region == ""| YourAK == null| YourAK == ""| YourSK == null|
YourSK == "")
throw new IllegalArgumentException("the parameter for HWOcrClientAKSK's Constructor cannot be empty");
String endPoint = "https://ocr." + Region + ".myhuaweicloud.com";
HEC_AUTH= new AuthInfo(endPoint,Region,YourAK,YourSK);
HttpService=new AisAccess(HEC_AUTH);
}
/**
* Constructor for OcrClientAKSK with proxy
* @param Endpoint HTTPEndPoint for OCR Service
* @param Region The region info for OCR Service
* @param YourAK The Access Key from Authentication
* @param YourSK The Secret Key from Authentication
* @param ProxyHost The URL for the proxy server
* @param ProxyPort The Port number for the proxy service
* @param ProxyUsrName The Loggin user for the proxy server if authentication is required
* @param ProxyPwd The Loggin pwd for the proxy server if authentication is required
* */
public HWOcrClientAKSK(String Endpoint,String Region,String YourAK,String YourSK,String ProxyHost,int ProxyPort,String ProxyUsrName,String ProxyPwd) {
if (Endpoint== null|Endpoint == ""|Region == null| Region == ""| YourAK == null| YourAK == ""| YourSK == null|
YourSK == ""|ProxyHost == null | ProxyHost == "" | ProxyUsrName == null |ProxyUsrName == ""| ProxyPwd == null | ProxyPwd == "")
throw new IllegalArgumentException("the parameter for HWOcrClientAKSK's Constructor cannot be empty");
HEC_AUTH= new AuthInfo(Endpoint,Region,YourAK,YourSK);
PROXYINFO= new ProxyHostInfo(ProxyHost,ProxyPort,ProxyUsrName,ProxyPwd);
HttpService=new AisAccessWithProxy(HEC_AUTH,PROXYINFO);
}
/*
* Release the access service when the object is collected
* */
protected void finalize(){
HttpService.close();
}
/**
* Call the OCR API with a local picture file
* @param uri the uri for the http request to be called
* @param filepath the path for the picture file to be recognized
* */
public HttpResponse RequestOcrServiceBase64(String uri,String imgPath, JSONObject params) throws IOException {
if(uri == null | uri == "" | imgPath == null | imgPath == "")
throw new IllegalArgumentException("the parameter for requestOcrServiceBase64 cannot be empty");
try {
if (imgPath.indexOf("http://") != -1 || imgPath.indexOf("https://") != -1) {
params.put("url", imgPath);
} else {
byte[] fileData = FileUtils.readFileToByteArray(new File(imgPath));
String fileBase64Str = Base64.encodeBase64String(fileData);
params.put("image", fileBase64Str);
}
// Pass the parameters in JSON objects and invoke the service using POST.
StringEntity stringEntity = new StringEntity(params.toJSONString(), "utf-8");
HttpResponse response = HttpService.post(uri, stringEntity);
return response;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
package com.test.huawei.ocr;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import org.apache.http.HttpResponse;
import com.huawei.ais.sdk.util.HttpClientUtils;
/**
* Tool used to verify the information returned from service access.
*/
public class ResponseProcessUtils {
/**
* Print the HTTP status code after the service access is complete.
*
* @param response Response object
*/
public static void ProcessResponseStatus(HttpResponse response) {
System.out.println(response.getStatusLine().getStatusCode());
}
/**
* Convert the service access result into a character stream, which is used for showing the JSON data.
*
* @param response Response object
* @throws UnsupportedOperationException
* @throws IOException
*/
public static void ProcessResponse(HttpResponse response) throws UnsupportedOperationException, IOException {
System.out.println(HttpClientUtils.convertStreamToString(response.getEntity().getContent()));
}
/**
* Write the byte array to the file to support generation of binary files (for example, images).
* @param fileName File name
* @param data Data
* @throws IOException
*/
public static void WriteBytesToFile(String fileName, byte[] data) throws IOException{
FileChannel fc = null;
try {
ByteBuffer bb = ByteBuffer.wrap(data);
fc = new FileOutputStream(fileName).getChannel();
fc.write(bb);
} catch (Exception e) {
e.printStackTrace();
System.out.println(e.getMessage());
}
finally {
fc.close();
}
}
}
整理过后,才发现使用起来并不难,就是刚开始使用时不知道使用的流程。到此为止,车牌识别的就告一个段落。