声明:本文所提到的代码以及库(动态链接库so或者静态库lib)可能来源于第三方成熟产品。
作者仅保留自己所研究部分内容的所有权。
本文中所提到相关工具,仅供学习参考使用,不得作为商业用途。
使用手机(暂限于ANDROID平台手机)相机捕获车牌图像,能够识别车牌号码。识别率达到90%以上。
细化需求:
(1)支持多Android版本(API Level 8~2x),Android 1.5 ~ 4.4.x
(2)要求相机自动聚焦,以保证获取图像质量
(3)图像识别时间不大于6s
(4)图像识别率>90%
2、思路
(1)市场分析,体验现有车牌识别产品,进行研究,拟进行整合
(2)相关方案按照难度的易→难程度,排列如下:
a:基于界面调用,获取返回结果(Activity调用,前提需要安装依赖APP)
b:基于代码反编译,基于接口重用(网络通信接口调用,依赖于对方的调用政策)
c:基于代码反编译,基于动态库重用(JNI应用)
d:基于代码反编译,代码重用(依赖于代码反编译难度,例如:工程有否混淆、反编译工具的选择)
e:基于代码反编译,代码的理解,重构
(1)目标:现有车牌识别APP产品:文通、云脉
(2)工具:反编译工具:dex2jar v2.0、jad 1.5.8g 和AXMLPrinter2.jar (截止2015.6.25日的最新版本)
(3)步骤
a:下载apk文件,并解压
b:使用dex2jar工具,输入classes.dex文件生成classes-dex2jar.jar
c:使用jad工具,输入classes-dex2jar.jar中的class文件生成java源文件
d:使用AXMLPrinter2.jar,输入AndroidManifest.xml生成AndroidManifest.xml.txt
e:开始进行代码分析
(1)无论文通还是云脉的手机app,前者为V1.2.3,后者为V3.0,都使用JNI方式进行API的调用
(2)适用于上述方案C的方式,即基于代码反编译,基于动态链接库重用
(3)云脉使用的动态链接库文件:libimageengine.so、libpnocrengine.so,
对应的接口声明在hotcard.doc.reader.NativeImage和NativeOcrPn中定义
(4)文通使用的动态链接库文件:libTHPlateIDFree.so、libCWImage.so,
对应的接口声明在com.wintone.plateid.PlateIDAPI中定义
(5)相比之下,文通产品的经验和技术底蕴较为深厚,将以文通产品进行研究
PlateIDAPI的定义:
<span style="font-size:12px;">package com.wintone.plateid; import com.wintone.plate.Package; /** * 车牌识别API * @author PAUL * @mail [email protected] * @date 2015-06-01 */ public class PlateIDAPI { public PlateIDAPI() { } //返回车牌识别库版本。 格式: 主版本号 .副版本号 .修订号 .编译号 。 public static native String TH_GetVersion(); /** * 初始化识别库 * @param paramTH_PlateIDCfg * @param paramPackage 车牌识别SDK的配置 * @return */ public static native int TH_InitPlateIDSDK( TH_PlateIDCfg th_plateidcfg, Package package1); public static native int TH_InitPlateIDSDKTF( TH_PlateIDCfg th_plateidcfg); //识别图片 public static native TH_PlateIDResult[] TH_RecogImage( String s, int i, int j, TH_PlateIDResult th_plateidresult, int ai[], int k, int l, int i1, int j1, int ai1[]); //识别图像 public static native TH_PlateIDResult[] TH_RecogImageByte( byte abyte0[], int i, int j, TH_PlateIDResult th_plateidresult, int ai[], int k, int l, int i1, int j1, int ai1[]); public static native int TH_SetAutoSlopeRectifyMode( int i, int j); public static native int TH_SetContrast( int i); //设置夜间模式 public static native int TH_SetDayNightMode( int i); //设置对特殊车牌的识别 public static native int TH_SetEnabledPlateFormat( int i); public static native int TH_SetEnlargeMode( int i); //设置图像格式 public static native int TH_SetImageFormat( int i, int j, int k); //设置默认省份 public static native int TH_SetProvinceOrder( String s); //设置识别阈值 public static native int TH_SetRecogThreshold( int i, int j); public static native int TH_UninitPlateIDSDK(); static { System.loadLibrary("CWImage"); System.loadLibrary("THPlateIDFree"); } };</span>接口调用规则推测
(1)TH_InitPlateIDSDK
(2)TH_Setxxxxx
(3)TH_RecogImage 或 TH_RecogImageByte
(4)TH_UninitPlateIDSDK
(1)初始化SDK;
(2)调用系统相机进行拍照(1280x960像素的分辨率);
(3)调用识别函数进行车牌图片的识别;关键代码如下;
(4)返回调用结果,如果成功,则返回所识别的车牌颜色和号码。
/** * 识别车牌图片文件 * @param filePath2 文件路径 * @return 车牌颜色+车牌号码 */ private String recognizeImageFile(String filePath2) { //Toast.makeText(this, text, Toast.LENGTH_SHORT).show(); TH_PlateIDResult localResult = new TH_PlateIDResult(); int[] array1 = new int[1]; array1[0] = 10; int[] array2 = new int[1]; array2[0] = -1; File file = new File(filePath); if(!file.exists()) { Logger.getLogger(IDef.App_Tag).log(Level.WARNING, "Read image ["+filePath+"] failure"); return (null); } PlateIDAPI.TH_SetImageFormat(1, 0, 1); ConfigArgument configArg = new ConfigArgument(); PlateIDAPI.TH_SetEnabledPlateFormat(configArg.individual); PlateIDAPI.TH_SetEnabledPlateFormat(configArg.tworowyellow); PlateIDAPI.TH_SetEnabledPlateFormat(configArg.armpolice); PlateIDAPI.TH_SetEnabledPlateFormat(configArg.tworowarmy); PlateIDAPI.TH_SetEnabledPlateFormat(configArg.tractor); PlateIDAPI.TH_SetEnabledPlateFormat(configArg.onlytworowyellow); PlateIDAPI.TH_SetEnabledPlateFormat(configArg.embassy); PlateIDAPI.TH_SetEnabledPlateFormat(configArg.onlylocation); PlateIDAPI.TH_SetEnabledPlateFormat(configArg.armpolice2); PlateIDAPI.TH_SetRecogThreshold(7, 5); PlateIDAPI.TH_SetContrast(9); TH_PlateIDResult[] result = PlateIDAPI.TH_RecogImage(file.getAbsolutePath(), CaptureActivity.Desired_Picture_Width, CaptureActivity.Desired_Picture_Height, localResult, array1, 0, 0, 0, 0,array2); if( (result == null) || (result.length== 0) ) { //识别失败 Logger.getLogger(IDef.App_Tag).log(Level.WARNING, "Image recognize failure"); file.delete(); return (null); } StringBuffer sb = new StringBuffer(); sb.append(result[0].toString() ); //更名 File newFile = new File(IDef.App_Dir+File.separatorChar+result[0].getLicense()+".jpg"); file.renameTo(newFile); file.delete(); return (sb.toString() ); }
相关下载
(1)说明文档:http://download.csdn.net/detail/paulorwys/8836519
(2)链接库:http://download.csdn.net/detail/paulorwys/8839447