Android平臺車牌識別開發手冊
目錄
1.1 安裝
安裝文通車牌演示程式plate_id_sample_service.apk。
1.2 Android版本
支援Android2.3 – 5.1
1.3 啟用方式介紹
在首次呼叫時提供序列號或啟用檔案進行啟用。
1、 線上序列號啟用方式。
由文通公司提供含有序列號的Excel檔案,使用者在呼叫程式中指定sn引數即用於該裝置的某序列號,首次呼叫識別時裝置須聯網。可指定繫結裝置deviceid或繫結SIM卡序號。預設繫結deviceid。
2、 離線檔案啟用方式。
使用者先提供文通公司含有deviceid
3、 TF卡模式。
需使用文通公司授權的TF卡。
4、 專案授權方式。
專案授權檔案中限制如下內容:開發碼引數、使用者程式包名、識別核心版本號、使用截止時間、使用者程式名稱、使用者公司名稱;
開發碼與呼叫識別時傳遞的devcode引數比對,開發碼由文通公司與專案授權檔案一併提供;
程式包名與AndroidMenifest.xml中package比對;
使用截止時間與當前系統時間比對;
授權檔案中核心版本號與底層核心版本號比對, 預設限制前兩位;
專案名稱與strings.xml中app_name比對;
公司名稱與strings.xml中company_name比對;
專案授權檔案需放入專案assets資料夾中。
注意:如果使用1或2
所列的啟用方式,請選擇指定sn引數或authfile引數 ,不要同時指定sn引數和authfile引數,否則將只按1的方式進行啟用,設定此兩個引數請參見下文程式碼示例。
**採用專案授權無需呼叫驗證授權服務
2 拍攝注意事項
目前支援的JPEG影象的解析度為2048*1536畫素及以下,支援影象中車牌的預設實際寬度為80-400畫素。
2.1 一般要求
影象文字清晰,人眼可辨別;
對比度、亮度適中;
2.2 對拍攝影象的要求
拍攝時做好聚焦,以免影象模糊不清;
拍攝時不要使車牌過度傾斜;
儘量不要使拍攝角度傾斜過大,以免造成影象變形成梯形;
3 介面概述與整合說明
使用者可以呼叫Activity或Service的方式整合識別功能,識別Activity只支援JPG圖片格式,識別Service也支援JPG圖片格式,推薦使用Service方式整合;使用者可以通過呼叫函式的方式設定識別引數,詳情見後面章節。
注意將“plate_id_sdk整合所需檔案”資料夾下的所有內容放到Android專案的根目錄下;注意拷貝assets、lib、libs及res的內容到您的專案中;注意將AndroidManifest.xml裡面的內容和res/values/strings.xml的內容合併到專案相關檔案中;如果採用TF卡授權方式,請將 “TF”資料夾中的相關檔案替換到專案中;如果採用序列號啟用方式繫結裝置,請將“序列號” 資料夾中的相關檔案替換到專案中;
注意當與文通Android證件識別整合到一個專案中時,請刪除lib資料夾下的misc_crypto.jar(如果有的話),否則會引起衝突。
4 呼叫識別Activity(V1.3.0.5不再使用)
4.1 識別引數說明
識別Activity具有如下引數:
型別 |
名稱 |
說明 |
示例 |
String |
cls |
接收識別返回值的包名類名 |
com.wintone.demo.PlateIDRunner |
String |
pic |
圖片路徑 |
|
int |
imageformat |
影象格式 |
1 |
int |
width |
影象寬度 |
420 |
int |
height |
影象高度 |
232 |
int |
bVertFlip |
0 |
|
int |
bDwordAligned |
1 |
|
boolean |
GetVersion |
是否需要獲取開發包的版本資訊 |
true |
String |
sn |
序列號,第一次呼叫時啟用,如不設定此項需通過自動啟用或手動啟用頁面輸入序列號。 |
請輸入大寫序列號 |
String |
authfile |
啟用檔案路徑,啟用檔案中儲存了用於該裝置的序列號和啟用碼,不用時可設定為”” |
|
String |
userdata |
使用者想在識別後和識別結果一起傳回的字串 |
|
String |
returntype |
接收識別結果的方式 |
預設值””,代表用第一種方式接收識別結果;值”withvalue”代表用第二種方式。詳見示例程式章節。 |
4.2 識別返回值說明
識別Activity具有如下返回值:
型別 |
名稱 |
說明 |
備註 |
int |
nRet |
識別結果標誌 |
0成功; 1 FindPlate(沒有找到車牌) 2 車牌評價值(0分) 3 車牌評價值(不及格) 4 車牌識別分數(0分) 5 車牌識別分數(不及格) -1001 讀jpg圖片錯誤,可能是圖片超過2048*1536解析度 -10001 未呼叫初始化函式 -10003 沒有啟用或啟用碼校驗失敗 -10004 指定序列號為null或"" -10005 未連線到伺服器 -10006 獲取啟用碼失敗或未連線到伺服器 -10007 授權伺服器無此序列號 -10008 序列號已使用 -10009 無法建立授權檔案 -10010 校驗啟用碼失敗 -10011 其他錯誤 -10012 未啟用 -10015 啟用檔案校驗失敗 -10401 開發碼錯誤或未找到authmode.lsc檔案 -10402 裝置型號未授權 -10500 未檢測到SIM卡 -1008 未讀到TF卡; -1005 TF卡授權模式下使用了非TF卡授權的動態庫; 20 所插TF中的license\license.dat授權檔案不匹配;或非TF卡授權模式下使用了TF卡模式動態庫; -8:license\license.dat授權檔案未找到 -10600 其他錯誤; -10601 開發碼錯誤; -10602 程式包名錯誤; -10603 截止時間過期; -10604 核心版本號錯誤; -10605 專案名稱錯誤; -10606 公司名稱錯誤。 |
String[] |
GetFieldName |
欄位名 |
"車牌號", "車牌顏色", "車牌顏色程式碼", "車牌型別程式碼", "整牌可信度", "亮度評價","車牌運動方向", "車牌左上點橫座標", "車牌左上點縱座標", "車牌右下點橫座標", "車牌右下點縱座標", "時間","車的亮度", "車的顏色" |
String[] |
GetRecogResult |
欄位值 |
車牌顏色編碼: 0 未知 1 藍 2 黃 3 白 4 黑 5 綠 車牌型別編碼: 0 未知車牌 1 藍牌小汽車 2 黑牌小汽車 3 單排黃牌 4 雙排黃牌(大車尾牌,農用車) 5 警車車牌 6 武警車牌 7 個性化車牌 8 單排軍車 9 雙排軍車 10 使館牌 11 香港牌 12 拖拉機 車輛亮度編碼: 0 深 1 淺 車輛顏色編碼: 0 白 1 灰(銀) 2 黃 3 粉 4 紅 5 綠 6 藍 7 棕 8 黑 運動方向編碼: 1 左 2 右 3 上 4 下 |
String |
ReturnGetVersion |
取版本資訊,如果定義了GetVersion為true才能取版本資訊 |
|
String |
ReturnUserData |
返回使用者自定義資料引數userdata |
|
String |
ReturnLPFileName |
使用者指定的影象路徑 |
5 呼叫識別Service
5.1 呼叫Service方式概述
Service介面包括兩個Service,分別是驗證Service AuthService和識別Service RecogService:
驗證Service所需引數:序列號方式啟用時用sn引數;啟用檔案方式時用authfile引數;不要同時指定sn引數和authfile引數,否則將只按序列號方式進行啟用;如果未設定sn引數和authfile引數,將在根目錄尋找啟用檔案。
TF卡授權方式不用呼叫驗證Service,只調用識別Service即可。
驗證Service呼叫順序:bindService、啟用驗證函式getAuth、unbindService;即每次產生驗證Service新例項完成驗證和啟用的操作。
識別Service呼叫順序:在驗證Service的返回值ReturnAuthority為0時,每次識別時呼叫依次呼叫一次bondService、讀取初始化狀態函式getInitPlateIDSDK、設定識別引數的函式setRecogArgu、識別函式doRecogDetail、unbondService。
注意:Service方式支援JEPG影象檔案識別。
public String[]doRecogDetail(PlateRecognitionParameter prp)//用於識別JEPG圖片。
5.2 示例程式碼
5.2.1 在AndroidManifest.xml中定義Service
<service android:enabled="true" android:name="com.wintone.plateid.AuthService">
<intent-filter >
<action android:name="wintone.plateid.authservice"/>
</intent-filter>
</service>
<service android:enabled="true" android:name="com.wintone.plateid.RecogService">
<intent-filter >
<action android:name="wintone.plateid.recogService"/>
</intent-filter>
</service>
5.2.2 繫結授權驗證服務
//繫結授權驗證服務
Intent authIntent = new Intent(MainActivity.this, AuthService.class);
bindService(authIntent, authConn, Service.BIND_AUTO_CREATE);
5.2.3 授權驗證服務繫結後的操作
//授權驗證服務繫結後的操作
public ServiceConnection authConn = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
authBinder = null;
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.i(TAG, "authConn onServiceConnected");
authBinder = (AuthService.MyBinder) service;
Toast.makeText(getApplicationContext(), "授權驗證服務 繫結成功", Toast.LENGTH_SHORT).show();
try {
// sn:採用序列號方式啟用時設定此引數,否則寫""
// authfile:採用啟用檔案方式啟用時設定此引數,否則寫""
// 以上倆個引數都不為""時按序列號方式啟用;當sn和authfile為""時會在根目錄下找啟用檔案 xxxxxxxxxxxxxxx_cp.txt
ReturnAuthority = authBinder.getAuth(sn, authfile);
if (ReturnAuthority != 0) {
recogButton.setEnabled(false);
String[] str = {"" + ReturnAuthority};
getResult(str);
Toast.makeText(getApplicationContext(), "授權驗證失敗", Toast.LENGTH_SHORT).show();
} else {
//若授權成功,則啟動識別服務
recogIntent = new Intent(MainActivity.this, RecogService.class);
//startService(recogIntent);
Toast.makeText(getApplicationContext(), "授權驗證成功", Toast.LENGTH_SHORT).show();
}
}catch (Exception e) {
e.printStackTrace();
Log.i(TAG, "e=" + e.toString());
}finally{
if (authBinder != null) {
unbindService(authConn);//解綁授權驗證服務
}
}
}
};
5.2.4 繫結識別服務
//繫結識別服務
recogIntent = new Intent(MainActivity.this, RecogService.class);
bindService(recogIntent, recogConn, Service.BIND_AUTO_CREATE);
5.2.5 識別服務繫結後的操作
//識別服務繫結後的操作
public ServiceConnection recogConn = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
recogConn = null;
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
recogBinder = (RecogService.MyBinder) service;
iInitPlateIDSDK = recogBinder.getInitPlateIDSDK();
if (iInitPlateIDSDK != 0) {
nRet = iInitPlateIDSDK;
String[] str = { "" + iInitPlateIDSDK };
getResult(str);
} else {
PlateCfgParameter cfgparameter = new PlateCfgParameter();
cfgparameter.armpolice = 4;
cfgparameter.armpolice2 = 16;
cfgparameter.embassy = 12;
cfgparameter.individual = 0;
cfgparameter.nContrast = 0;
cfgparameter.nOCR_Th = 2;
cfgparameter.nPlateLocate_Th = 5;
cfgparameter.onlylocation = 15;
cfgparameter.tworowyellow = 2;
cfgparameter.tworowarmy = 6;
cfgparameter.szProvince = "";
cfgparameter.onlytworowyellow = 11;
cfgparameter.tractor = 8;
cfgparameter.bIsNight = 0;
recogBinder.setRecogArgu(cfgparameter, imageformat, bVertFlip,
bDwordAligned);
PlateRecognitionParameter prp = new PlateRecognitionParameter();
prp.height = height;
prp.width = width;
prp.pic = recogPicPath;
fieldvalue = recogBinder.doRecogDetail(prp);
nRet = recogBinder.getnRet();
if (nRet != 0) {
String[] str = { "" + nRet };
getResult(str);
} else {
getResult(fieldvalue);
}
}
if (recogBinder != null) {
unbindService(recogConn);
}
}
};
6 呼叫識別引數配置函式
public void setRecogArgu(PlateCfgParameter cfgparameter, int imageformat, int bVertFlip, int bDwordAligned)
說明:本函式存在於識別Service內,引數cfgparameter見下表,其他引數請勿修改。
型別 |
引數名稱 |
取值範圍 |
預設值 |
int |
nPlateLocate_Th |
定位閾值 (取值範圍0-9,7:預設閾值,0:最寬鬆的閾值,9:最嚴格的閾值) |
5 |
int |
nOCR_Th |
識別閾值(取值範圍0-9,5:預設閾值0:最寬鬆的閾值9:最嚴格的閾值) |
2 |
int |
bIsAutoSlope |
是否要傾斜校正 |
1 |
int |
nSlopeDetectRange |
傾斜校正的範圍(取值範圍0-16) |
0 |
String |
szProvince |
省份順序 |
|
int |
nContrast |
清晰度指數(取值範圍0-9,最模糊時設為1;最清晰時設為9) |
0(不校驗) |
int |
bIsNight |
是否夜間模式:1是;0不是 |
0 |
int |
individual |
是否開啟個性化車牌:0是;1不是 |
0 |
int |
tworowyellow |
雙層黃色車牌是否開啟:2是;3不是 |
3 |
int |
armpolice |
單層武警車牌是否開啟:4是;5不是 |
5 |
int |
tworowarmy |
雙層軍隊車牌是否開啟:6是;7不是 |
7 |
int |
tractor |
農用車車牌是否開啟:8是;9不是 |
9 |
int |
onlytworowyellow |
只識別雙層黃牌是否開啟:10是;11不是 |
11 |
int |
embassy |
使館車牌是否開啟:12是;13不是 |
13 |
int |
onlylocation |
只定位車牌是否開啟:14是;15不是 |
15 |
int |
armpolice2 |
雙層武警車牌是否開啟:16是;17不是 |
17 |
public String[] doRecogDetail(PlateRecognitionParameter prp)
說明:本函式存在於識別Service內,引數prp見下表。
識別介面,該函式返回的是識別後的資料。
型別 |
引數名稱 |
預設值 |
|
byte[] |
picByte |
相機獲取的位元組陣列資料 |
|
String |
pic |
拍照識別,圖片的儲存路徑 |
|
int |
width |
影象寬度 |
|
int |
heigth |
影象高度 |
|
String |
userdata |
使用者自定義資料引數userdata |
|
String |
devCode |
開發碼 |
|
String |
dataFile |
時間授權檔案路徑 |
|
String |
versionfile |
版本授權檔案路徑 |
|
boolean |
isCheckDevType |
是否檢查裝置型號 |
false |
int |
plateIDCfg.bRotate |
預覽圖片在進行識別時需要旋轉的角度: 0:不旋轉;1:90度;2:旋轉180;3:旋轉270 |
0 |
int |
plateIDCfg.left |
掃描框在預覽圖片上所對應的左座標點 |
0 |
int |
plateIDCfg.right |
掃描框在預覽圖片上所對應的右座標點 |
0 |
int |
plateIDCfg.top |
掃描框在預覽圖片上所對應的上座標點 |
0 |
int |
plateIDCfg.bottom |
掃描框在預覽圖片上所對應的下座標點 |
0 |
public int getnRet() 獲取識別後的返回值 nRet (詳見4.2返回結果說明)
7序列號線上啟用方式的整合步驟
7.1 資原始檔的拷貝
將assets資料夾、lib資料夾、libs資料夾全部按照下圖的目錄結構複製到整合的專案中:
先選中所有的jar包,然後add Path,右鍵lib資料夾點選Buid Path選項並選擇config buid Path選項,點選Order and Export選項,將android_auth.jar、ksoap2-android-assembly-2.4-jar-with-dependencies.jar、plate_id_sdk.jar、
bcprov-ext-jdk15-146.jar、pki.jar等全部勾選並點選“確定”按鈕,如圖:
將res的內容合併到您的專案中;注意將AndroidManifest.xml裡面的內容和res/values/strings.xml的內容合併到專案相關檔案中
7.2配置AndroidManifest.xml檔案,
開啟要整合的專案的AndroidManifest.xml檔案,將以下許可權、相應的service和activity加入其中:
<!-- 讀取機器各種ID的許可權 -->
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<!-- 在SDCard中建立與刪除檔案許可權 -->
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
<!-- 往SDCard寫入資料許可權 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!-- 關閉該包下的所有應用程式 -->
<uses-permission android:name="android.permission.RESTART_PACKAGES" />
<!-- 訪問internet許可權 -->
<uses-permission android:name="android.permission.INTERNET" />
<!-- 訪問震動許可權 -->
<uses-permission android:name="android.permission.VIBRATE" />
<!--
guangda
<uses-permission android:name="cybertech.pstore.permission.COMPONENT" />
<uses-permission android:name="cybertech.permission.READ_PSTORE_USERINFO" />
<uses-permission android:name="cybertech.permission.READ_PSTORE_LINKINFO" />
-->
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.FLASHLIGHT" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.CHANGE_CONFIGURATION" />
<service
android:name="com.wintone.plateid.AuthService"
android:enabled="true" >
<intent-filter>
<action android:name="wintone.plateid.authservice" />
</intent-filter>
</service>
<service
android:name="com.wintone.plateid.RecogService"
android:enabled="true" >
<intent-filter>
<action android:name="wintone.plateid.recogService" />
</intent-filter>
</service>
<activity
android:name="com.wintone.plateid.MemoryCameraActivity"
android:label="@string/app_name"
android:configChanges="orientation|keyboard|keyboardHidden">
</activity>
<activity
android:name="com.wintone.plateid.MemoryResultActivity">
</activity>
<activity
android:name="com.wintone.plateid.ResultActivity"
android:screenOrientation="portrait" />
<activity android:name="com.wintone.plateid.CameraActivity"
android:configChanges="keyboardHidden|orientation">
<intent-filter>
<action android:name="wintone.camera" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
註冊時請注意更換包名!!
7.3 授權服務的程式碼整合
授權服務的定義:(使用者需將從銷售手中獲得的25位序列號替換sn,
ReturnAuthority變數為授權服務成功與否的標誌,如果為0則證明授權成功)
授權服務的程式碼整合(具體變數的定義請詳見MainActivity.java,該程式碼需在識別之前呼叫)
public ServiceConnection authConn = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
authBinder = null;
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
authBinder = (AuthService.MyBinder) service;
Toast.makeText(getApplicationContext(), R.string.auth_check_service_bind_success, Toast.LENGTH_SHORT).show();
try {
PlateAuthParameter pap = new PlateAuthParameter();
pap.sn = sn;
pap.authFile = authfile;
// sn:採用序列號方式啟用時設定此引數,否則寫""
// authfile:採用啟用檔案方式啟用時設定此引數,否則寫""
// 以上倆個引數都不為""時按序列號方式啟用;當sn和authfile為""時會在根目錄下找啟用檔案xxxxxxxxxxxxxxx_cp.txt
ReturnAuthority = authBinder.getAuth(pap);
if (ReturnAuthority != 0) {
Toast.makeText(getApplicationContext(),getString(R.string.license_verification_failed)+":"+ReturnAuthority,Toast.LENGTH_LONG).show();
}else{
Toast.makeText(getApplicationContext(),R.string.license_verification_success,Toast.LENGTH_LONG).show();
}
}catch (Exception e) {
Toast.makeText(getApplicationContext(), R.string.failed_check_failure, Toast.LENGTH_SHORT).show();
e.printStackTrace();
}finally{
if (authBinder != null) {
unbindService(authConn);
}
}
}
授權服務的呼叫:(在Activity的oncreate()中呼叫,必須在進入拍照介面前進行呼叫)
Intent authIntent = new Intent(MainActivity.this, AuthService.class);
bindService(authIntent,authConn,Service.BIND_AUTO_CREATE);
7.4識別方法選擇:
進入拍照識別介面程式碼:
Intent cameraintent = new Intent(MainActivity.this,MemoryCameraActivity.class);
cameraintent.putExtra("camera", false);
startActivity(cameraintent);
進入視訊識別介面程式碼:
Intent video_intent = new Intent();
video_intent.setClass(getApplicationContext(), MemoryCameraActivity.class);
video_intent.putExtra("camera", true);
startActivity(video_intent);
進入選擇識別介面程式碼:
Intent selectIntent = new Intent(Intent.ACTION_GET_CONTENT);
selectIntent.addCategory(Intent.CATEGORY_OPENABLE);
selectIntent.setType("image/*");
Intent wrapperIntent = Intent.createChooser(selectIntent,"Select Picture");
startActivityForResult(wrapperIntent, SELECT_RESULT_CODE);
7.5識別服務的整合
繫結識別服務
Intent authIntent = new Intent(M