【MediaTek X20开发板试用体验】小区车牌自动识别系统项目结贴  

分享到:

xble
 xble
Level 1
注册时间:7年 前
帖子数: 15
2017年3月14日 上午9:35  
本帖最后由 xble 于 2017-3-14 09:34 编辑

一)项目概述
  汽车已经成为很多人生活中的必需品,成为人们的代步工具,随之也引发了很多管理问题。车牌作为汽车的唯一身份证,其重要性不言而喻,车牌自动识别需求应运而生,它相对人工管理有很大优点:1.可以不间断的连续工作;2.准确、自动、长时间的保存车牌信息。当然也有很多缺点:1,识别成功率不高;2.位置固定,不如人工灵活。
  希望可以通过这个项目让我学习到一下知识:1)MTK X20开发平台相关知识;2)学习USB Camera模块相关知识;3)学习Opencv的概念和车牌识别的原理,流程。应用到的技术主要有C/C++编程,Android开发,
  Opencv跨平台计算机视觉库,人工智能的相关知识,当然由于水平和时间限制我这里只是简单接触一下,在前人的基础大概了解其大概原理和实现过程。
二)硬件设计
  1.X20开发板
  2.USB Camera
  3.HDMI转接线,DIV显示器,USB鼠标,USB下载线。
三)软件调试
1)USB Camera模块加载和抓取车牌图片
  由于USB Camera模块无法固定,导致抓取图片的质量非常差,所以没有实时解析Camera拍摄图形,而是保存成图片后在进行识别。其实现参考前面的帖子,连接为: http://bbs.elecfans.com/forum.ph ... &tid=1108917&extra=
2)车牌识别原理,过程
        车牌识别原理与我们前面的实现过的简化版字符数字识别全过程原理一致,只是需要添加许多额外的步骤来提高识别准确度。参考连接: http://bbs.elecfans.com/forum.ph ... &tid=1112867&extra=
        我们将车牌识别实现分为两步:1)SVM训练数据准备;2)车牌定位,识别。从一定意义上来说SVM数据训练也是车牌定位识别的过程,只是我们会人工干预,确保这个过程的正确性。
        车牌定位主要处理步骤:1)高斯模糊Sobel算子,闭操作;2)处理图形旋转角度;3)对比SVM数据初步判断图块是否是车牌。
        字符识别主要处理步骤:1)字符分割(阀值操作,取轮廓);2)通过ANN模型进行字符识别。        
        如果想要产品化必须深入了解图形学的相关知识,原理,分析各种图形算法来提高识别准确性,另外准备大量的训练好的SVM和ANN数据也是提高准确性的重要方法。
3)测试车牌图片准备。
        简单方法:从网上搜索一些车牌图片,使用附件里面提供的APK,准确度非常高。
        Camera采集方法:附件里面的video.avi文件是我们使用USB camera拍摄的一段视频,可以在这里抓取一些车牌图片来识别,可惜这种方法的识别正确率实在不高。

 

  
        将这些图片都push到/storage/emulated/0文件夹下。
4)Android+Studio分析上步所得图片,识别,显示结果
        Android界面:edit输入框中的文件名加上前面的文件路径(/storage/emulated/0),显示按钮,识别按钮。代码如下:

  1. package com.example.gzh.myplaterecognizer;
  2. import android.Manifest;
  3. import android.content.DialogInterface;
  4. import android.content.pm.PackageManager;
  5. import android.graphics.Bitmap;
  6. import android.graphics.BitmapFactory;
  7. import android.os.Environment;
  8. import android.support.annotation.NonNull;
  9. import android.support.v4.app.ActivityCompat;
  10. import android.support.v4.content.ContextCompat;
  11. import android.support.v7.app.AlertDialog;
  12. import android.support.v7.app.AppCompatActivity;
  13. import android.os.Bundle;
  14. import android.util.Log;
  15. import android.view.View;
  16. import android.widget.EditText;
  17. import android.widget.ImageView;
  18. import android.widget.TextView;
  19. import android.widget.Toast;
  20. import org.opencv.android.Utils;
  21. import org.opencv.core.Mat;
  22. import java.io.File;
  23. import java.io.FileNotFoundException;
  24. import java.io.IOException;
  25. import static org.opencv.android.OpenCVLoader.initDebug;
  26. import static org.opencv.imgproc.Imgproc.COLOR_RGB2GRAY;
  27. import static org.opencv.imgproc.Imgproc.cvtColor;
  28. public class MainActivity extends AppCompatActivity {
  29.     private static final int MY_PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE = 1;
  30.     private boolean mExternalStorageAvailable = false;
  31.     private boolean mExternalStorageWriteable = false;
  32.     private static final int CAMERA_REQUEST_CODE = 1;
  33.     private boolean mCamera = false;
  34.     static String TAG = "myplaterecognizer";
  35.     ImageView show_image;
  36.     Bitmap srcBitmap;
  37.     Bitmap grayBitmap;
  38.     private long mRecognizerPtr = 0;
  39.     private static boolean flag = true;
  40.     TextView Mytv;
  41.     PlateRecognizer myplaterecognizer;
  42.     EditText MyeditText;
  43.     int nRunningOnce = 0;
  44.     String strMyeditText = "1.PNG";
  45. //    String myPath = "/storage/emulated/0/Documents/PlateRcognizer";
  46.     String myPath = "/storage/emulated/0";
  47.     protected void onCreate(Bundle savedInstanceState) {
  48.         super.onCreate(savedInstanceState);
  49.         setContentView(R.layout.activity_main);
  50.         Log.d(TAG, "call SetExternalStoragepermission_OK");
  51.                                 int nRet = 0;//
  52.         SetExternalStoragepermission_OK();
  53.         nRet = CheckExternalStoragepermission_OK();
  54.         if(nRet == 0)
  55.         {
  56.                 Log.i("Surface:", "nRet ==0");
  57.         }
  58.         else
  59.         {
  60.                 Log.i("Surface:", "nRet !=0");
  61.         Mytv = (TextView) findViewById(R.id.sample_text);
  62.         myplaterecognizer = new PlateRecognizer(this);
  63.         MyeditText = (EditText)findViewById(R.id.editText);
  64.        // str1 = editText1.getText().toString();
  65.         MyeditText.setText(strMyeditText.toCharArray(), 0, strMyeditText.length());
  66.         //initData();
  67.         Mytv.setText(myplaterecognizer.stringFromJNI());
  68.         show_image = (ImageView) findViewById(R.id.imageView);        
  69.         }        // Example of a call to a native method
  70.        // show_image.setImageResource(R.drawable.heidfk640);
  71.         findViewById(R.id.button_show).setOnClickListener(new View.OnClickListener() {
  72.             @Override
  73.             public void onClick(View v) {
  74.                 //myPath
  75.                 String fileName = "";
  76.                 strMyeditText = MyeditText.getText().toString();
  77.                 fileName = String.format("%s/%s", myPath, strMyeditText);
  78.                 String str_test = "";
  79.                 str_test = String.format("=1=fileName=%s", fileName);
  80.                 Log.d(TAG, str_test);
  81.                 Bitmap bm = BitmapFactory.decodeFile(fileName);
  82.                 show_image.setImageBitmap(bm);
  83.             }
  84.         });
  85.         findViewById(R.id.button_PlateRecognizer).setOnClickListener(new View.OnClickListener() {
  86.             @Override
  87.             public void onClick(View v) {
  88.                 String fileName = "";
  89.                 strMyeditText = MyeditText.getText().toString();
  90.                 fileName = String.format("%s/%s", myPath, strMyeditText);
  91.                 String str_test = "";
  92.                 str_test = String.format("=1=fileName=%s/%s", myPath, strMyeditText);
  93.                 Log.d(TAG, str_test);
  94.                 // 进行车牌识别 pr_jingph7n90.jpg
  95.                 //  String plate = myplaterecognizer.recognize("/storage/sdcard/Pictures/PlateRcognizer/heidfk640.jpg");
  96.                 String plate = myplaterecognizer.recognize(fileName);
  97.                 // String plate = myplaterecognizer.recognize(pictureFile.getAbsolutePath());
  98.                 if (null != plate && ! plate.equalsIgnoreCase("0")) {
  99.                     Mytv.setText(plate);
  100.                 } else {
  101.                     Mytv.setText("can not recognize");
  102.                 }
  103.             }
  104.         });
  105.     }
  106.     @Override
  107.     protected void onResume() {
  108.         super.onResume();
  109.         if (initDebug()) {
  110.             Log.i(TAG, "OpenCV initialize success");
  111.         } else {
  112.             Log.i(TAG, "OpenCV initialize failed");
  113.         }
  114.     }
  115.     private int CheckExternalStoragepermission_OK()
  116.     {
  117.         String externalStorageState = Environment.getExternalStorageState();
  118.         if (Environment.MEDIA_MOUNTED.equals(externalStorageState)) {
  119.             mExternalStorageAvailable = true;
  120.             mExternalStorageWriteable = true;
  121.             return 2;      } else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(externalStorageState)) {
  122.             mExternalStorageAvailable = true;
  123.             mExternalStorageWriteable = false;
  124.             return 1;       } else {
  125.             mExternalStorageAvailable = mExternalStorageWriteable = false;
  126.             return 0;
  127.         }
  128.     //    handleExternalStorageState(mExternalStorageAvailable,mExternalStorageWriteable);
  129.     }
  130.     private void SetExternalStoragepermission_OK()
  131.     {
  132.         String externalStorageState = Environment.getExternalStorageState();
  133.         if (Environment.MEDIA_MOUNTED.equals(externalStorageState)) {
  134.             mExternalStorageAvailable = true;
  135.             mExternalStorageWriteable = true;
  136.         } else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(externalStorageState)) {
  137.             mExternalStorageAvailable = true;
  138.             mExternalStorageWriteable = false;
  139.         } else {
  140.             mExternalStorageAvailable = mExternalStorageWriteable = false;
  141.         }
  142.         handleExternalStorageState(mExternalStorageAvailable,mExternalStorageWriteable);
  143.         
  144.                                 requestPermission();
  145.         
  146.     }
  147.     private void requestPermission() {
  148.         if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
  149.                 != PackageManager.PERMISSION_GRANTED) {
  150.             // 第一次请求权限时,用户如果拒绝,下一次请求shouldShowRequestPermissionRationale()返回true
  151.             // 向用户解释为什么需要这个权限
  152.             if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.CAMERA)) {
  153.                 new AlertDialog.Builder(this)
  154.                         .setMessage("申请相机权限")
  155.                         .setPositiveButton("确定", new DialogInterface.OnClickListener() {
  156.                             @Override
  157.                             public void onClick(DialogInterface dialog, int which) {
  158.                                 //申请相机权限
  159.                                 ActivityCompat.requestPermissions(MainActivity.this,
  160.                                         new String[]{Manifest.permission.CAMERA}, CAMERA_REQUEST_CODE);
  161.                             }
  162.                         })
  163.                         .show();
  164.             } else {
  165.                 //申请相机权限
  166.                 ActivityCompat.requestPermissions(this,
  167.                         new String[]{Manifest.permission.CAMERA}, CAMERA_REQUEST_CODE);
  168.             }
  169.         } else {
  170.           //  Tv.setTextColor(Color.GREEN);
  171.           //  Tv.setText("相机权限已申请");
  172.         }
  173.     }
  174.     private void handleCameraState(boolean mCamera ) {
  175.                 }
  176.     private void handleExternalStorageState(boolean mExternalStorageAvailable,boolean mExternalStorageWriteable ) {
  177.         if(mExternalStorageAvailable && mExternalStorageWriteable){
  178.             //STORAGE is dangerous so check
  179.             // checkSelfPermission()
  180.             int permissionCheck = ContextCompat.checkSelfPermission(this,
  181.                     Manifest.permission.WRITE_EXTERNAL_STORAGE);
  182.             Log.d("permission", "permissionCheck=="+permissionCheck);
  183.             if (permissionCheck != PackageManager.PERMISSION_GRANTED) {
  184.                 //has not granted request permission
  185.                 // Should we show an explanation?
  186.                 if (ActivityCompat.shouldShowRequestPermissionRationale(this,
  187.                         Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
  188.                     // Show an expanation to the user *asynchronously* -- don't block
  189.                     // this thread waiting for the user's response! After the user
  190.                     // sees the explanation, try again to request the permission.
  191.                     //  Toast.makeText(MainActivity.this, "Permission++++", Toast.LENGTH_SHORT).show();
  192. //                    ActivityCompat.requestPermissions(this,
  193. //                            new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
  194. //                            MY_PERMISSIONS_REQUEST_READ_CONTACTS);
  195.                     new AlertDialog.Builder(this)
  196.                             .setMessage("您拒绝过授予访问外部存储设备的权限,但是只有申请该权限,才能往外部存储设备写入数据,你确定要重新申请获取权限吗?")
  197.                             .setPositiveButton("ok", new DialogInterface.OnClickListener() {
  198.                                 @Override
  199.                                 public void onClick(DialogInterface dialog, int which) {
  200.                                     dialog.dismiss();
  201.                                     //again request permission
  202.                                     ActivityCompat.requestPermissions(MainActivity.this,
  203.                                             new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
  204.                                             MY_PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE);
  205.                                 }
  206.                             })
  207.                             .setNegativeButton("no", new DialogInterface.OnClickListener() {
  208.                                 @Override
  209.                                 public void onClick(DialogInterface dialog, int which) {
  210.                                     dialog.dismiss();
  211.                                 }
  212.                             })
  213.                             .create()
  214.                             .show();
  215.                 } else {
  216.                     // No explanation needed, we can request the permission.
  217.                     ActivityCompat.requestPermissions(this,
  218.                             new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
  219.                             MY_PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE);
  220.                     // MY_PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE is an
  221.                     // app-defined int constant. The callback method gets the
  222.                     // result of the request.
  223.                 }
  224.             }else{
  225.                 //had granted
  226.                 Toast.makeText(MainActivity.this, "run writeDatasToExternalStorage() method", Toast.LENGTH_SHORT).show();
  227.                 // writeDatasToExternalStorage();
  228.             }
  229.         }else{
  230.             Log.d("permission", "ExternalStorage can not be write  or unAvailable");
  231.         }
  232.     }
  233.     /**          */
  234.     private void writeDatasToExternalStorage(){
  235.         File directory = Environment.getExternalStorageDirectory();// 6.0 /storage/emulated/0    5.0 /storage/sdcard
  236.             /*
  237.              Environment.getDataDirectory();//  /data
  238.              Environment.getRootDirectory();// /system
  239.              Environment.getDownloadCacheDirectory();//  /cache
  240.              Environment.getExternalStoragePublicDirectory(
  241.                     Environment.DIRECTORY_PICTURES);// 6.0 /storage/emulated/0/Pictures   5.0/storage/sdcard/Pictures
  242.            */
  243.         File file = new File(directory, "permisson");
  244.         if(!file.exists()){
  245.             try {
  246.                 file.createNewFile();
  247.             } catch (IOException e) {
  248.                 e.printStackTrace();
  249.             }
  250.         }
  251.     }
  252.     /**
  253.      *
  254.      * @param requestCode
  255.      * @param permissions
  256.      * @param grantResults
  257.      */
  258.     @Override
  259.     public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
  260.         Log.d("permission", "onRequestPermissionsResult  requestCode" + requestCode);
  261.         if (requestCode == MY_PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE) {
  262.                 // If request is cancelled, the result arrays are empty.
  263.                 if (grantResults.length > 0
  264.                         && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
  265.                     // permission was granted, yay! Do the
  266.                     // contacts-related task you need to do.
  267.                     Toast.makeText(MainActivity.this, "run writeDatasToExternalStorage() method", Toast.LENGTH_SHORT).show();
  268.                     //   writeDatasToExternalStorage();
  269.                 } else {
  270.                     // Permission Denied
  271.                     Toast.makeText(MainActivity.this, "Permission Denied", Toast.LENGTH_SHORT).show();
  272.                     // permission denied, boo! Disable the
  273.                     // functionality that depends on this permission.
  274.                 }
  275.                 return;
  276.             }
  277.         if (requestCode == CAMERA_REQUEST_CODE) {
  278.                     if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
  279.                    // Tv.setTextColor(Color.GREEN);
  280.                   //  Tv.setText("相机权限已申请");
  281.             } else {
  282.                 //用户勾选了不再询问
  283.                 //提示用户手动打开权限
  284.                 if (!ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.CAMERA)) {
  285.                     Toast.makeText(this, "相机权限已被禁止", Toast.LENGTH_SHORT).show();
  286.                 }
  287.             }
  288.             }
  289.             // other 'case' lines to check for other
  290.             // permissions this app might request
  291.         super.onRequestPermissionsResult(requestCode, permissions, grantResults);
  292.     }
  293. }

复制代码

        NDK算法实现;

  1. #include "EasyPR.h"
  2. #include "easyPR/include/core/plate_locate.h"
  3. #include "easyPR/include/core/plate_judge.h"
  4. #include "easyPR/include/core/chars_segment.h"
  5. #include "easyPR/include/core/chars_identify.h"
  6. #include "easyPR/include/core/plate_detect.h"
  7. #include "easyPR/include/core/chars_recognise.h"
  8. #include "easyPR/include/core/plate_recognize.h"
  9. using namespace easypr;
  10. #include <android/log.h>
  11. #define LOG_TAG "System.out"
  12. #define  LOGI(...)  __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
  13. #define  LOGD(...)  __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__)
  14. #define  LOGE(...)  __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
  15. extern "C"
  16. JNIEXPORT jstring JNICALL Java_com_example_gzh_myplaterecognizer_PlateRecognizer_stringFromJNI(
  17.                 JNIEnv *env,
  18.                 jobject /* this */
  19.         ) {
  20.     return env->NewStringUTF("myplaterecognizer JNI!");
  21. }
  22. char* jstring2str(JNIEnv* env, jstring jstr) {
  23.         char* rtn = NULL;
  24.         jclass clsstring = env->FindClass("java/lang/String");
  25.         jstring strencode = env->NewStringUTF("utf-8"); // "GB2312"
  26.         jmethodID mid = env->GetMethodID(clsstring, "getBytes", "(Ljava/lang/String;)[B");
  27.         jbyteArray barr = (jbyteArray) env->CallObjectMethod(jstr, mid, strencode);
  28.         jsize alen = env->GetArrayLength(barr);
  29.         jbyte* ba = env->GetByteArrayElements(barr, JNI_FALSE);
  30.         if (alen > 0) {
  31.                 rtn = (char *)malloc(alen + 1);
  32.                 memcpy(rtn, ba, alen);
  33.                 rtn[alen] = 0;
  34.         }
  35.         env->ReleaseByteArrayElements(barr, ba, 0);
  36.         return rtn;
  37. }
  38. extern "C"
  39. JNIEXPORT jlong JNICALL Java_com_example_gzh_myplaterecognizer_PlateRecognizer_initPR(
  40.                 JNIEnv *env,
  41.                 jobject /* this */,
  42.                 jstring svmpath,
  43.                 jstring annpath)
  44. {
  45. //        const string *svm = (*env)->GetStringUTFChars(env, svmpath, 0);
  46. //        const string *ann = (*env)->GetStringUTFChars(env, annpath, 0);
  47.         char* svm = jstring2str(env, svmpath);
  48.         char* ann = jstring2str(env, annpath);
  49.         LOGE("Java_com_example_gzh_myplaterecognizer_PlateRecognizer_initPR svm=%s, ann=%s", svm, ann);
  50.         CPlateRecognize *pr = new CPlateRecognize();
  51.         pr->setDebug(false);
  52.         pr->setLifemode(true);
  53.     pr->setMaxPlates(4);
  54.     pr->loadSVM(svm);
  55.     pr->loadANN(ann);
  56.     return (jlong)pr;
  57. }
  58. extern "C"
  59. JNIEXPORT jlong JNICALL Java_com_example_gzh_myplaterecognizer_PlateRecognizer_uninitPR(
  60.                 JNIEnv *env, jobject, jlong recognizerPtr) {
  61.     CPlateRecognize *pr = (CPlateRecognize *)recognizerPtr;
  62.         LOGE("Java_com_example_gzh_myplaterecognizer_PlateRecognizer_uninitPR");
  63.     delete pr;
  64.     return 0;
  65. }
  66. extern "C"
  67. JNIEXPORT jbyteArray JNICALL Java_com_example_gzh_myplaterecognizer_PlateRecognizer_plateRecognize(
  68.                 JNIEnv *env, jobject, jlong recognizerPtr, jstring imgpath) {
  69.     CPlateRecognize *pr = (CPlateRecognize *)recognizerPtr;
  70.     //        const string *img = (*env)->GetStringUTFChars(env, imgpath, 0);
  71.     char* img = jstring2str(env, imgpath);
  72.         Mat src = imread(img);
  73.         std::vector<std::string> plateVec;
  74.         int count = pr->plateRecognize(src, plateVec);
  75.         std::string str = "0";
  76.         if(! plateVec.empty() && count == 0) {
  77.                 str = plateVec[0];
  78.         }
  79.         char *result = new char[str.length() + 1];
  80.         strcpy(result, str.c_str());
  81.         jbyte *by = (jbyte*) result;
  82.         jbyteArray jarray = env->NewByteArray(strlen(result));
  83.         env->SetByteArrayRegion(jarray, 0, strlen(result), by);
  84.         return jarray;
  85. }
  86. extern "C"
  87. JNIEXPORT jbyteArray JNICALL Java_com_example_gzh_myplaterecognizer_PlateRecognizer_plateRecognize1(
  88.                 JNIEnv *env, jobject, jlong recognizerPtr, jlong imgMat) {
  89.         CPlateRecognize *pr = (CPlateRecognize *)recognizerPtr;
  90.         //        const string *img = (*env)->GetStringUTFChars(env, imgpath, 0);
  91.         //char* img = jstring2str(env, imgpath);
  92.         Mat& src = *(Mat*)imgMat;// = imread(img);
  93.         std::vector<std::string> plateVec;
  94.         int count = pr->plateRecognize(src, plateVec);
  95.         std::string str = "0";
  96.         if(! plateVec.empty() && count == 0) {
  97.                 str = plateVec[0];
  98.         }
  99.         char *result = new char[str.length() + 1];
  100.         strcpy(result, str.c_str());
  101.         jbyte *by = (jbyte*) result;
  102.         jbyteArray jarray = env->NewByteArray(strlen(result));
  103.         env->SetByteArrayRegion(jarray, 0, strlen(result), by);
  104.         return jarray;
  105. }

复制代码

  1. #include "../../include/core/plate_recognize.h"
  2. #include "../../include/config.h"
  3. namespace easypr {
  4. CPlateRecognize::CPlateRecognize() { }
  5. // !车牌识别模块
  6. int CPlateRecognize::plateRecognize(Mat src, std::vector<std::string> &licenseVec) {
  7.   // 车牌方块集合
  8.   std::vector<CPlate> plateVec;
  9.   // 进行深度定位,使用颜色信息与二次Sobel
  10.   int resultPD = plateDetect(src, plateVec, kDebug, 0);
  11.   if (resultPD == 0) {
  12.     size_t num = plateVec.size();
  13.     int index = 0;
  14.     //依次识别每个车牌内的符号
  15.     for (size_t j = 0; j < num; j++) {
  16.       CPlate item = plateVec[j];
  17.       Mat plate = item.getPlateMat();
  18.       //获取车牌颜色
  19.       std::string plateType = getPlateColor(plate);
  20.       //获取车牌号
  21.       std::string plateIdentify = "";
  22.       int resultCR = charsRecognise(plate, plateIdentify);
  23.       if (resultCR == 0) {
  24.         std::string license = plateType + ":" + plateIdentify;
  25.         licenseVec.push_back(license);
  26.       }
  27.     }
  28.     //完整识别过程到此结束
  29.     //如果是Debug模式,则还需要将定位的图片显示在原图左上角
  30.     if (getPDDebug()) {
  31.       Mat result;
  32.       src.copyTo(result);
  33.       for (size_t j = 0; j < num; j++) {
  34.         CPlate item = plateVec[j];
  35.         Mat plate = item.getPlateMat();
  36.         int height = 36;
  37.         int width = 136;
  38.         if (height * index + height < result.rows) {
  39.           Mat imageRoi = result(Rect(0, 0 + height * index, width, height));
  40.           addWeighted(imageRoi, 0, plate, 1, 0, imageRoi);
  41.         }
  42.         index++;
  43.         RotatedRect minRect = item.getPlatePos();
  44.         Point2f rect_points[4];
  45.         minRect.points(rect_points);
  46.         Scalar lineColor = Scalar(255, 255, 255);
  47.         if (item.getPlateLocateType() == SOBEL) lineColor = Scalar(255, 0, 0);
  48.         if (item.getPlateLocateType() == COLOR) lineColor = Scalar(0, 255, 0);
  49.         for (int j = 0; j < 4; j++)
  50.           line(result, rect_points[j], rect_points[(j + 1) % 4], lineColor, 2,
  51.                8);
  52.       }
  53.       //显示定位框的图片
  54.       showResult(result);
  55.     }
  56.   }
  57.   return resultPD;
  58. }
  59. }

复制代码

四)测试过程和视频
   测试过程:1)安装APK;2)准备测试图片
          
 
测试视频: http://v.youku.com/v_show/id_XMjYyODcwNzkzNg==.html。
抓取测试图片视频地址: https://pan.baidu.com/s/1pLvxVbd
apk共享地址; https://pan.baidu.com/s/1o84Ttvc
五)总结
        改进方案:
        1)Android界面上应该使用通过按钮选择车牌图片来识别,或者通过Listbox显示多个图片,或者通过Combox选择框来显示多个图片;
        2)对plateRecognize类众多函数没有详细解读;
        3)固定Camera处理实时图像。


DragonCat liked
回复引用
DragonCat
Level 2Admin
注册时间:7年 前
帖子数: 42
2017年3月20日 上午10:42  

牛,希望大家去结合更多的应用场景使用MediaTek X20 board,然后发出来共享讨论,哈哈,让我们的论坛飞起来呀。


回复引用
  
Working

登陆 或者 注册