基于百度云AI开发车型识别车牌识别案例详解
關鍵字: 車牌識別 車型識別 百度AI SpringBoot Vue Java SDK
文章目錄
- 1.創建百度AI應用
- 2.通過Access_token密碼調用百度AI接口(車型識別)
- 3.Java客戶端AipImageClassifyClient調用AI接口
- 4.車型識別接口說明
- 5.Java后端Controller層接收圖片
- 6.Java后端Service層訪問AI接口
- 7.基于VUE的前端開發車牌識別和車型識別
- 8.總結與展望
1.創建百度AI應用
進入百度AI官網https://ai.baidu.com/,點擊右上角控制臺,用百度賬號登錄。如果沒有百度賬號,需要首先創建一個百度賬號。
在控制臺可以看到各種百度提供的AI應用接口。找到需要的應用接口,點進去可以創建一個相應的應用。
圖像識別提供一個組合API接口,支持多種垂類識別服務的靈活組合調用。
然后會提供給該應用一個API Key 和Secret Key,它是我們調用接口必須的兩個參數。
以下是本次開發中用到的車型識別的應用。百度AI的車牌識別需要另外申請一個應用。需要注意的是不同的應用有不同的AppID等參數。
2.通過Access_token密碼調用百度AI接口(車型識別)
車型識別功能檢測圖片中的車輛,識別具體車型,包括車輛品牌體型號、顏色、年份、位置信息。
車輛識別為例。它的請求url為: https://aip.baidubce.com/rest/2.0/image-classify/v1/car
調用方式一定為POST。同時我們要在后面添加以下參數:
access_token:即前面獲取的密碼
在請求頭中設置Content-Type參數
Content-Type:設置為application/x-www-form-urlencoded
在請求體Body中設置image圖片的信息參數
1.image:圖片信息參數,它是通過圖片路徑找到圖片轉為字節,然后經過Base64編碼最后形成的字符串。如下代碼
//獲取圖片的路徑
String filePath = Path;
//將圖片轉為字節數組
byte[] imgData = FileUtil.readFileByBytes(filePath);
//將圖片字節數組轉為Base64編碼的字符串換
String imgStr = Base64Util.encode(imgData);
//將經過Base64編碼的圖片字符串轉為UTF-8編碼的字符串。可以直接傳給image參數
String imgParam = URLEncoder.encode(imgStr, “UTF-8”);
2.top_num:設置返回的信息的數量,默認5,因為車輛識別會得出多個結果,按幾率得到,我們可以獲取前n個的數據
3.baike_num:設置返回的百科的信息數,默認不返回
3.Java客戶端AipImageClassifyClient調用AI接口
以上方法是采用接口直接調用,下面的方法是使用JAVA客戶端進行訪問。首先需要安裝ImageClassify Java SDK,可以在官方網站下載Java SDK壓縮工具包。
然后,新建AipImageClassifyClient,AipImageClassifyClient是圖像識別的Java客戶端,為使用圖像識別的開發人員提供了一系列的交互方法。
用戶可以參考如下代碼新建一個AipImageClassifyClient,初始化完成后建議單例使用,避免重復獲取access_token:
public class Sample {//設置APPID/AK/SKpublic static final String APP_ID = "你的 App ID";public static final String API_KEY = "你的 Api Key";public static final String SECRET_KEY = "你的 Secret Key";public static void main(String[] args) {// 初始化一個AipImageClassifyClientAipImageClassifyClient client = new AipImageClassifyClient(APP_ID, API_KEY, SECRET_KEY);// 可選:設置網絡連接參數client.setConnectionTimeoutInMillis(2000);client.setSocketTimeoutInMillis(60000);// 可選:設置代理服務器地址, http和socket二選一,或者均不設置client.setHttpProxy("proxy_host", proxy_port); // 設置http代理client.setSocketProxy("proxy_host", proxy_port); // 設置socket代理// 調用接口String path = "test.jpg";JSONObject res = client.objectDetect(path, new HashMap<String, String>());System.out.println(res.toString(2));} }在上面代碼中,常量APP_ID在百度智能云控制臺中創建,常量API_KEY與SECRET_KEY是在創建完畢應用后,系統分配給用戶的,均為字符串,用于標識用戶,為訪問做簽名驗證,可在AI服務控制臺中的應用列表中查看。
4.車型識別接口說明
識別圖片中車輛的具體車型,可識別常見的3000+款車型(小汽車為主),輸出車輛的品牌型號、顏色、年份、位置信息;支持返回對應識別結果的百度百科詞條信息,包含詞條名稱、百科頁面鏈接、百科圖片鏈接、百科內容簡介。
當前只支持單主體識別,若圖片中有多個車輛,則識別目標最大的車輛。
百度官方文檔提供了調用的示例,提交參數的方式有本地路徑和二進制數組。
public void sample(AipImageClassify client) {// 傳入可選參數調用接口HashMap<String, String> options = new HashMap<String, String>();options.put("top_num", "3");options.put("baike_num", "5");// 參數為本地路徑String image = "test.jpg";JSONObject res = client.carDetect(image, options);System.out.println(res.toString(2));// 參數為二進制數組byte[] file = readFile("test.jpg");res = client.carDetect(file, options);System.out.println(res.toString(2)); }車型識別 請求參數詳情
| image | 是 | mixed | - | 本地圖片路徑或者圖片二進制數據 |
| top_num | 否 | String | 5 | 返回預測得分top結果數,默認為5 |
| baike_num | 否 | String | 0 | 返回百科信息的結果數,默認不返回 |
車型識別 返回數據參數詳情
| log_id | 是 | uint64 | 唯一的log id,用于問題定位 |
| color_result | 是 | string | 車身顏色 |
| result | 是 | car-result() | 車型識別結果數組 |
| +name | 是 | string | 車型名稱,示例:寶馬x6 |
| +score | 是 | double | 置信度,取值范圍0-1,示例:0.5321 |
| +year | 是 | string | 年份 |
| +baike_info | 否 | object | 對應識別結果的百科詞條名稱 |
| ++baike_url | 否 | string | 對應識別結果百度百科頁面鏈接 |
| ++image_url | 否 | string | 對應識別結果百科圖片鏈接 |
| ++description | 否 | string | 對應識別結果百科內容描述 |
| location_result | 是 | string | 車輛在圖片中的位置信息 |
| +width | 是 | float | 車輛區域的寬度 |
| +height | 是 | float | 車輛區域的高度 |
| +left | 是 | float | 車輛區域離左邊界的距離 |
| +top | 是 | float | 車輛區域離上邊界的距離 |
車型識別 返回示例
{"log_id": 4086212218842203806,"location_result": {"width": 447,"top": 226,"height": 209,"left": 188},"result": [{"baike_info": {"baike_url": "http://baike.baidu.com/item/%E5%B8%83%E5%8A%A0%E8%BF%AAChiron/20419512","description": "布加迪Chiron是法國跑車品牌布加迪出品的豪華超跑車。配置四渦輪增壓發動機,420 公里每小時,有23種顏色的選擇,售價高達260萬美元。"},"score": 0.98793351650238,"name": "布加迪Chiron","year": "無年份信息"},{"score": 0.0021970034576952,"name": "奧迪RS5","year": "2011-2017"},{"score": 0.0021096928976476,"name": "奧迪RS4","year": "無年份信息"},{"score": 0.0015581247862428,"name": "奧迪RS7","year": "2014-2016"},{"score": 0.00082337751518935,"name": "布加迪威航","year": "2004-2015"}],"color_result": "顏色無法識別" }車型識別的錯誤碼可見:https://ai.baidu.com/ai-doc/VEHICLE/Gk3hb3ifo
? 車牌識別的調用方式和以上車型識別的方式大同小異,這里略過。
5.Java后端Controller層接收圖片
本次開發的后端應用基于SpringBoot v2.4.1,Controller層的開發內容如下所示。
/*** @Author Jarrett Luo* @Date 2021/1/28 18:26* @Version 1.0*/ @RestController @RequestMapping(value = "/recognition") public class RecognitionController {@ResourceRecognitionService recognitionService;@CrossOrigin@PostMappingpublic ApiResult save(@RequestParam(value="file", required=false) MultipartFile multipartFile)throws IOException {byte[] imgBytes = multipartFile.getBytes();if(imgBytes!=null){return recognitionService.find(imgBytes);}else {return ApiResult.error(201,"數據為空!");}} }byte[] imgBytes = multipartFile.getBytes();將前端傳遞的數據轉換為二進制數組,以便于后面進行調用。
必須進行非空判斷后才能進入下一步,否則會出現沒有返回值的錯誤。ApiResult是自己寫的一個工具,用于返回結果,如果傳入的空數據,則返回201的錯誤碼。
6.Java后端Service層訪問AI接口
根據百度AI控制頁創建的應用,設置每個應用的APP_ID, API_KEY, SECRET_KEY。這里需要注意的是百度AI提交的不同接口需要創建不同的應用。
我們對文件的大小進行了限制,這里僅處理10MB以下的圖片。
public ApiResult find(byte[] image) {if(image.length>10048575) {return ApiResult.error(201, "文件過大!");}// 初始化一個AipOcrAipOcr client = new AipOcr(APP_ID, API_KEY, SECRET_KEY);HashMap<String, String> options = new HashMap<String, String>();JSONObject res = client.plateLicense(image, options);String number;if(res.has("words_result")) {JSONObject jsonData = res.getJSONObject("words_result");number = jsonData.getString("number");}else {number = null;}// 初始化一個AipImageClassifyAipImageClassify client1 = new AipImageClassify(APP_ID_1, API_KEY_1, SECRET_KEY_1);// 傳入可選參數調用接口HashMap<String, String> options1 = new HashMap<String, String>();options.put("top_num", "1");// 參數為本地路徑JSONObject res1 = client1.carDetect(image, options1);String color;String name;String year;if(res1.has("result")) {JSONArray jsonData = res1.getJSONArray("result");JSONObject vehicle = jsonData.getJSONObject(0);//獲取數組第一個元素year = vehicle.getString("year");name = vehicle.getString("name");color = res1.getString("color_result");if(year.equals("無年份信息")){year = null;}if(name.equals("非車類")) {name = null;}if(color.equals("無車輛顏色信息")) {color = null;}}else {year = null;name = null;color = null;}RecognitionDTO recognitionDTO = new RecognitionDTO(number,name,year,color);return ApiResult.success(recognitionDTO);}注意以上代碼的ApiResult是自己寫的一個結果轉換的工具類。關于ApiResult的詳細內容可以查看作者github的詳細介紹。
7.基于VUE的前端開發車牌識別和車型識別
根據開發需求,在頁面中增加一個拍照自動識別按鈕,用戶點擊按鈕后可以選擇拍照或者相冊中的照片。相應的HTML代碼如下所示。
/*** 圖片拍照識別上傳* @author: 羅佳瑞*/uploadFile() {var that = this;var inputDOM = that.$refs.imageInput;var file = inputDOM.files;var formData = new FormData();formData.append('file', file[0]);this.uploadImage(formData)Indicator.open({text: '識別中...',spinnerType: 'fading-circle'});setTimeout(()=>{Indicator.close();},15000)},以下是采用異步方式提交數據到后臺服務器,提交數據的函數時recorgnizeRequest。如果成功返回數據該函數將回調uploadImageResult,關于該回調函數下文將會介紹。
/** * 異步提交數據到后臺 * @author: 羅佳瑞 */ async uploadImage(formData) {await vehiclePageRequest.recorgnizeRequest(formData).then(res => {this.uploadImageResult(res)}).catch(err => {Toast("" + err)}) },采用axios提交數據到相應的URL。VUE中采用Promise提交數據,采用這種方式提交更好的看到提交成功和識別的結果。特別要注意,為了避免axios對formdata進行轉換,因此最好加上tansformRequest。
function recorgnizeRequest(FormData) {return new Promise((resolve, reject) => {axios({url: RECORGNIZE_URL,method: 'POST',headers: {'Content-Type': "multipart/form-data",// token: sessionStorage.getItem('token')},//這部分非常重要,否則formdata會被轉格式transformRequest: [function(){return FormData;}],params: {},data: FormData,}).then((res) => {// 成功resolve(res.data)}).catch((res) => {// 失敗reject(res)})}) }后端返回的數據采用如下代碼映射到表單中。由于返回的結果中可能沒有識別到車輛,或者圖片中沒有車輛信息,因此在這一步進行非空判斷。
Indicator是前端框架的指示器,用于告知用戶當前識別進度以及識別結果。
uploadImageResult(res) {if(res.code==200) {var recorgnizeResult = res.datavar rln = recorgnizeResult.licenseNumbervar rvb = recorgnizeResult.namevar rvc = recorgnizeResult.color;var rvy = recorgnizeResult.year;var resultStr = "";if(rln!=null){this.vehicleInfo.vehiclePlate = rln;resultStr = resultStr + "車牌可能是:" + rln + ";\n"}if(rvb!=null) {this.vehicleInfo.vehicleBrand = rvb;resultStr = resultStr + "品牌可能是:" + rvb + ";\n"}if(rvc!=null) {this.vehicleInfo.vehicleColor = rvc;resultStr = resultStr + "顏色可能是:" + rvc + ";\n"}if(rvy!=null) {var rvyFormat = rvy.substr(0,4)resultStr = resultStr + "年代可能是:" + rvyFormat + "年;\n"}Indicator.close();Indicator.open({text: "識別成功\n" + resultStr,spinnerType: 'fading-circle'});setTimeout(()=>{Indicator.close();},7500)}else{Toast({message: "連接超時!"})} }前端頁面開發結果如下。用戶點擊拍照自動識別后,選擇拍照或者相冊,提交照片等待返回結果。
服務器返回的結果會自動輸入到下圖中的車牌號,汽車品牌,車身顏色。
8.總結與展望
-
本文從訪問百度AI接口出發,詳細闡述了后端如何調用百度接口,實現一次圖片上傳得到車牌識別和車型識別的結果。
-
本文的前端開發作為示例,提供了一種思路,更多的如客戶端,安卓,IOS應用等等都可以采用如此方法開發。
-
采用百度AI提供的接口,可以拓展更多豐富的應用;多種接口的疊加讓用戶一次上傳便得到多種結果。
-
通過成熟的AI算法,識別的準確度和速度都比較令人滿意。
-
以上過程中存在的不足是,由于用戶拍照后直接上傳的圖片是比較大的,導致在傳輸過程中比較慢,甚至會出現超時的情況,用戶體驗不夠好。改進的方法是前端頁面首先對大文件進行壓縮后再上傳。
-
百度AI提供了組合調用AI的方式,前端可以采用該種方式發起請求。在此應用中需要保存用戶的圖片,因此沒有采用該方式。
如果您覺得上面的內容對您有幫助歡迎點贊、評論、轉發!
更多內容請查閱作者博客:https://jiaruiblog.com
或者star作者github: https://github.com/Jarrettluo?tab=repositories
總結
以上是生活随笔為你收集整理的基于百度云AI开发车型识别车牌识别案例详解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 微信小程序安装moment报错VM182
- 下一篇: eeupdate使用说明_UNRAID中