1. 程式人生 > >Android平臺車牌識別開發手冊

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

androididExcel檔案(第一列為deviceid,第二列為androidid),然後文通公司提供對應裝置的啟用檔案壓縮包,壓縮包中啟用檔案的數目與裝置數目一致,以[deviceid]_cp.txt命名,使用者在呼叫程式中指定authfile引數即啟用檔案的路徑和名稱,首次呼叫時裝置無需聯網。如authfile引數為null或等於””時,預設啟用檔案路徑為根目錄下的[deviceid]_cp.txt,當啟用檔案存在時做此啟用操作。

3、 TF卡模式。

需使用文通公司授權的TF卡。

4、  專案授權方式。

專案授權檔案中限制如下內容:開發碼引數、使用者程式包名、識別核心版本號、使用截止時間、使用者程式名稱、使用者公司名稱;

開發碼與呼叫識別時傳遞的devcode引數比對,開發碼由文通公司與專案授權檔案一併提供;

程式包名與AndroidMenifest.xmlpackage比對;

使用截止時間與當前系統時間比對;

授權檔案中核心版本號與底層核心版本號比對, 預設限制前兩位;

專案名稱與strings.xmlapp_name比對;

公司名稱與strings.xmlcompany_name比對;

專案授權檔案需放入專案assets資料夾中。

注意:如果使用12 所列的啟用方式,請選擇指定sn引數或authfile引數 ,不要同時指定sn引數和authfile引數,否則將只按1的方式進行啟用,設定此兩個引數請參見下文程式碼示例。

**採用專案授權無需呼叫驗證授權服務

2 拍攝注意事項

目前支援的JPEG影象的解析度為2048*1536畫素及以下,支援影象中車牌的預設實際寬度為80-400畫素。

2.1 一般要求

影象文字清晰,人眼可辨別;

對比度、亮度適中;

2.2 對拍攝影象的要求

拍攝時做好聚焦,以免影象模糊不清;

拍攝時不要使車牌過度傾斜;

儘量不要使拍攝角度傾斜過大,以免造成影象變形成梯形;

3 介面概述與整合說明

使用者可以呼叫ActivityService的方式整合識別功能,識別Activity只支援JPG圖片格式,識別Service也支援JPG圖片格式,推薦使用Service方式整合;使用者可以通過呼叫函式的方式設定識別引數,詳情見後面章節。

注意將“plate_id_sdk整合所需檔案”資料夾下的所有內容放到Android專案的根目錄下;注意拷貝assetsliblibsres的內容到您的專案中;注意將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

取版本資訊,如果定義了GetVersiontrue才能取版本資訊

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、啟用驗證函式getAuthunbindService;即每次產生驗證Service新例項完成驗證和啟用的操作。

識別Service呼叫順序:在驗證Service的返回值ReturnAuthority0時,每次識別時呼叫依次呼叫一次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:採用啟用檔案方式啟用時設定此引數,否則寫""

             // 以上倆個引數都不為""時按序列號方式啟用;當snauthfile""時會在根目錄下找啟用檔案 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:不旋轉;190度;2:旋轉1803:旋轉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.jarksoap2-android-assembly-2.4-jar-with-dependencies.jarplate_id_sdk.jar

bcprov-ext-jdk15-146.jarpki.jar等全部勾選並點選“確定”按鈕,如圖:

res的內容合併到您的專案中;注意將AndroidManifest.xml裡面的內容和res/values/strings.xml的內容合併到專案相關檔案中

7.2配置AndroidManifest.xml檔案,

開啟要整合的專案的AndroidManifest.xml檔案,將以下許可權、相應的serviceactivity加入其中:

<!-- 讀取機器各種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:採用啟用檔案方式啟用時設定此引數,否則寫""

// 以上倆個引數都不為""時按序列號方式啟用;當snauthfile""時會在根目錄下找啟用檔案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);

                }

            }

        }

授權服務的呼叫:(在Activityoncreate()中呼叫,必須在進入拍照介面前進行呼叫)

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