最近开发了一个拍车牌识别车牌号的功能,主要调用了腾讯的ocr车牌识别接口,直接上代码:
首先生成签名以及读取配置的工具类:
package com.weaver.formmodel.integration.ocr; import java.util.Random; import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; import weaver.general.Base64; public class SignUtil { /** * 生成 Authorization 签名字段 * * @param appId * @param secretId * @param secretKey * @param bucketName * @param expired * @return 签名字符串 * @throws Exception */ public static String appSign(long appId, String secretId, String secretKey, String bucketName, long expired) throws Exception { long now = System.currentTimeMillis() / 1000; int rdm = Math.abs(new Random().nextInt()); String plainText = String.format("a=%d&b=%s&k=%s&t=%d&e=%d&r=%d", appId, bucketName, secretId, now, now + expired, rdm); byte[] hmacDigest = HmacSha1(plainText, secretKey); byte[] signContent = new byte[hmacDigest.length + plainText.getBytes().length]; System.arraycopy(hmacDigest, 0, signContent, 0, hmacDigest.length); System.arraycopy(plainText.getBytes(), 0, signContent, hmacDigest.length, plainText.getBytes().length); return Base64Encode(signContent); } /** * 生成 base64 编码 * * @param binaryData * @return */ public static String Base64Encode(byte[] binaryData) { String encodedstr = new String(Base64.encode(binaryData)); return encodedstr; } /** * 生成 hmacsha1 签名 * * @param binaryData * @param key * @return * @throws Exception */ public static byte[] HmacSha1(byte[] binaryData, String key) throws Exception { Mac mac = Mac.getInstance("HmacSHA1"); SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(), "HmacSHA1"); mac.init(secretKey); byte[] HmacSha1Digest = mac.doFinal(binaryData); return HmacSha1Digest; } /** * 生成 hmacsha1 签名 * * @param plainText * @param key * @return * @throws Exception */ public static byte[] HmacSha1(String plainText, String key) throws Exception { return HmacSha1(plainText.getBytes(), key); } }
package weaver.general; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.ByteArrayOutputStream; import java.io.CharArrayWriter; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.FileReader; import java.io.FileWriter; import java.io.InputStream; import java.io.OutputStream; import java.io.Reader; import java.io.Writer; /** * Provides encoding of raw bytes to base64-encoded characters, and decoding of * base64 characters to raw bytes. date: 06 August 1998 modified: 14 February * 2000 modified: 22 September 2000 * * @author Kevin Kelley ([email protected]) * @version 1.3 */ public class Base64 { /** * returns an array of base64-encoded characters to represent the passed * data array. * * @param data * the array of bytes to encode * @return base64-coded character array. */ public static char[] encode(byte[] data) { char[] out = new char[((data.length + 2) / 3) * 4]; // // 3 bytes encode to 4 chars. Output is always an even // multiple of 4 characters. // for (int i = 0, index = 0; i < data.length; i += 3, index += 4) { boolean quad = false; boolean trip = false; int val = (0xFF & data[i]); val <<= 8; if ((i + 1) < data.length) { val |= (0xFF & data[i + 1]); trip = true; } val <<= 8; if ((i + 2) < data.length) { val |= (0xFF & data[i + 2]); quad = true; } out[index + 3] = alphabet[(quad ? (val & 0x3F) : 64)]; val >>= 6; out[index + 2] = alphabet[(trip ? (val & 0x3F) : 64)]; val >>= 6; out[index + 1] = alphabet[val & 0x3F]; val >>= 6; out[index + 0] = alphabet[val & 0x3F]; } return out; } /** * Decodes a BASE-64 encoded stream to recover the original data. White * space before and after will be trimmed away, but no other manipulation of * the input will be performed. * * As of version 1.2 this method will properly handle input containing junk * characters (newlines and the like) rather than throwing an error. It does * this by pre-parsing the input and generating from that a count of VALID * input characters. **/ public static byte[] decode(char[] data) { // as our input could contain non-BASE64 data (newlines, // whitespace of any sort, whatever) we must first adjust // our count of USABLE data so that... // (a) we don't misallocate the output array, and // (b) think that we miscalculated our data length // just because of extraneous throw-away junk int tempLen = data.length; for (int ix = 0; ix < data.length; ix++) { if ((data[ix] > 255) || codes[data[ix]] < 0) --tempLen; // ignore non-valid chars and padding } // calculate required length: // -- 3 bytes for every 4 valid base64 chars // -- plus 2 bytes if there are 3 extra base64 chars, // or plus 1 byte if there are 2 extra. int len = (tempLen / 4) * 3; if ((tempLen % 4) == 3) len += 2; if ((tempLen % 4) == 2) len += 1; byte[] out = new byte[len]; int shift = 0; // # of excess bits stored in accum int accum = 0; // excess bits int index = 0; // we now go through the entire array (NOT using the 'tempLen' value) for (int ix = 0; ix < data.length; ix++) { int value = (data[ix] > 255) ? -1 : codes[data[ix]]; if (value >= 0)// skip over non-code { accum <<= 6; // bits shift up by 6 each time thru shift += 6; // loop, with new bits being put in accum |= value; // at the bottom. if (shift >= 8)// whenever there are 8 or more shifted in, { shift -= 8; // write them out (from the top, leaving any out[index++] = // excess at the bottom for next iteration. (byte) ((accum >> shift) & 0xff); } } // we will also have skipped processing a padding null byte ('=') // here; // these are used ONLY for padding to an even length and do not // legally // occur as encoded data. for this reason we can ignore the fact // that // no index++ operation occurs in that special case: the out[] array // is // initialized to all-zero bytes to start with and that works to our // advantage in this combination. } // if there is STILL something wrong we just have to throw up now! if (index != out.length) { throw new Error("Miscalculated data length (wrote " + index + " instead of " + out.length + ")"); } return out; } // // code characters for values 0..63 // private static char[] alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=" .toCharArray(); // // lookup table for converting base64 characters to value in range 0..63 // private static byte[] codes = new byte[256]; static { for (int i = 0; i < 256; i++) codes[i] = -1; for (int i = 'A'; i <= 'Z'; i++) codes[i] = (byte) (i - 'A'); for (int i = 'a'; i <= 'z'; i++) codes[i] = (byte) (26 + i - 'a'); for (int i = '0'; i <= '9'; i++) codes[i] = (byte) (52 + i - '0'); codes['+'] = 62; codes['/'] = 63; } // ///////////////////////////////////////////////// // remainder (main method and helper functions) is // for testing purposes only, feel free to clip it. // ///////////////////////////////////////////////// public static void main(String[] args) { boolean decode = false; if (args.length == 0) { System.out.println("usage: java Base64 [-d[ecode]] filename"); System.exit(0); } for (int i = 0; i < args.length; i++) { if ("-decode".equalsIgnoreCase(args[i])) decode = true; else if ("-d".equalsIgnoreCase(args[i])) decode = true; } String filename = args[args.length - 1]; File file = new File(filename); if (!file.exists()) { System.out .println("Error: file '" + filename + "' doesn't exist!"); System.exit(0); } if (decode) { char[] encoded = readChars(file); byte[] decoded = decode(encoded); writeBytes(file, decoded); } else { byte[] decoded = readBytes(file); char[] encoded = encode(decoded); writeChars(file, encoded); } } private static byte[] readBytes(File file) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); try { InputStream fis = new FileInputStream(file); InputStream is = new BufferedInputStream(fis); int count = 0; byte[] buf = new byte[16384]; while ((count = is.read(buf)) != -1) { if (count > 0) baos.write(buf, 0, count); } is.close(); } catch (Exception e) { e.printStackTrace(); } return baos.toByteArray(); } private static char[] readChars(File file) { CharArrayWriter caw = new CharArrayWriter(); try { Reader fr = new FileReader(file); Reader in = new BufferedReader(fr); int count = 0; char[] buf = new char[16384]; while ((count = in.read(buf)) != -1) { if (count > 0) caw.write(buf, 0, count); } in.close(); } catch (Exception e) { e.printStackTrace(); } return caw.toCharArray(); } private static void writeBytes(File file, byte[] data) { try { OutputStream fos = new FileOutputStream(file); OutputStream os = new BufferedOutputStream(fos); os.write(data); os.close(); } catch (Exception e) { e.printStackTrace(); } } private static void writeChars(File file, char[] data) { try { Writer fos = new FileWriter(file); Writer os = new BufferedWriter(fos); os.write(data); os.close(); } catch (Exception e) { e.printStackTrace(); } } // ///////////////////////////////////////////////// // end of test code. // ///////////////////////////////////////////////// }
package weaver.general; import java.io.File; import java.io.FileInputStream; import java.util.HashMap; import java.util.Map; import java.util.Properties; public class BaseBean { private static MappropertyMap = new HashMap (); public String getPropValue(String cONFIG_FILE, String key) { if (propertyMap.get(cONFIG_FILE) == null) { readPro(cONFIG_FILE); } Properties pro = propertyMap.get(cONFIG_FILE); return pro.getProperty(key); } private void readPro(String cONFIG_FILE) { Properties pro = new Properties(); FileInputStream in; try { String path = Thread.currentThread().getContextClassLoader() .getResource("").toString(); path = path.substring(6, path.indexOf("classes/")); path = path + "prop/" + cONFIG_FILE + ".properties"; path = path.replace("%20", " "); System.out.println(path); File f = new File(path); if (!f.exists()) { throw new RuntimeException("要读取的文件不存在"); } in = new FileInputStream(f); pro.load(in); in.close(); propertyMap.put(cONFIG_FILE, pro); } catch (Exception e) { e.printStackTrace(); } } }
package weaver.general; public class Util { public static int getIntValue(String value) { try { return Integer.parseInt(value); } catch (NumberFormatException e) { e.printStackTrace(); return 0; } } }
然后是接口调配置文件:
正主来了,调用接口部分:
package com.weaver.formmodel.integration.ocr; import java.util.HashMap; import java.util.Map; import net.sf.json.JSONObject; import org.apache.commons.httpclient.HttpStatus; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.StatusLine; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.params.CoreConnectionPNames; import org.apache.http.util.EntityUtils; import weaver.general.BaseBean; import weaver.general.Util; public class OCRClient{ private static String CONFIG_FILE = "OCR_Tencent"; private static String host; private static int appid; private static String secretId; private static String secretKey; private static String targeturl; private static String encoding = "UTF-8"; static { BaseBean bb = new BaseBean(); host = bb.getPropValue(CONFIG_FILE, "host"); appid = Util.getIntValue(bb.getPropValue(CONFIG_FILE, "appid")); secretId = bb.getPropValue(CONFIG_FILE, "secretId"); secretKey = bb.getPropValue(CONFIG_FILE, "secretKey"); targeturl = bb.getPropValue(CONFIG_FILE, "targetUrl"); } /** * 识别图片 * @param imageurl * @param paramsMap 参数map * @return * @throws Exception */ public static MaprecognizeImage(Map paramsMap) throws Exception{ HttpClient httpclient = new DefaultHttpClient(); HttpPost httpPost = new HttpPost(targeturl);// 创建httpPost httpPost.setHeader("host", host); //设置签名 httpPost.setHeader("Authorization", SignUtil.appSign(appid, secretId, secretKey, "", 2592000));//设置请求头, 签名 //设置参数 JSONObject requestParam = new JSONObject(); requestParam.put("appid", String.valueOf(appid)); for(String key :paramsMap.keySet()){//循环加入请求参数 requestParam.put(key, paramsMap.get(key)); } //请求报文 StringEntity entity = new StringEntity(requestParam.toString(), encoding); entity.setContentEncoding(encoding); entity.setContentType("application/json");//发送json数据需要设置contentType httpPost.setEntity(entity); httpPost.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 120000); httpPost.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT, 120000); int state = 0; String result = ""; HttpResponse response = null; try { response = httpclient.execute(httpPost); StatusLine status = response.getStatusLine(); state = status.getStatusCode(); if (state == HttpStatus.SC_OK) { HttpEntity responseEntity = response.getEntity(); result = EntityUtils.toString(responseEntity); }else{ //new BaseBean().writeLog("读取OCR驾驶证或者行驶证接口失败,状态码:"+state); } } finally { httpclient.getConnectionManager().shutdown(); } Map resultMap = new HashMap (); resultMap.put("state", state); resultMap.put("result", result); return resultMap; } //测试 public static void main(String[] args) { String imgurl = "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1532414063478&di=f8709d73023a1a4ef9fe58f23ec95a8e&imgtype=jpg&src=http%3A%2F%2Fimg3.imgtn.bdimg.com%2Fit%2Fu%3D2587099383%2C4041264664%26fm%3D214%26gp%3D0.jpg"; try { //车牌号识别参数设置 Map requestParam = new HashMap (); requestParam.put("url", imgurl); Map res =recognizeImage(requestParam); //解析车牌号返回值 JSONObject resultJson = JSONObject.fromObject(res.get("result")); System.out.println(resultJson.toString()); } catch (Exception e) { e.printStackTrace(); } } }
如需调用其他接口,如身份证识别接口、驾驶证识别接口、等,则只需要修改一下配置文件的targeturl,并且调用时传入相应的参数即可。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。