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

[复制链接]

助理工程师

发表于 2017-3-11 14:17:29   663 查看 2 回复 显示全部楼层 倒序浏览
分享
本帖最后由 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拍摄的一段视频,可以在这里抓取一些车牌图片来识别,可惜这种方法的识别正确率实在不高。
1.PNG 2.PNG 3.PNG 4.PNG 5.PNG
        将这些图片都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)准备测试图片
         无标题.png
apk.jpg
测试视频: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处理实时图像。

标签:Android 人工智能 身份证 开发平台 计算机

技术员

发表于 2017-3-14 15:43:43  

PCB在线计价下单

板子大小:

cm
X
cm

层数:

2

板子数量:

10

厚度:

1.6
很赞  学习学习
回复

点赞

助理工程师

发表于 2017-3-24 16:57:20  
{:4_124:}
回复

高级模式
您需要登录后才可以回帖 登录 | 注册

专家问答 查看更多>>
关闭

站长推荐 上一条 /7 下一条

小黑屋|手机版|Archiver| 电子发烧友 ( 粤ICP备14022951号-2 )     

GMT+8, 2017-5-29 13:55 , Processed in 0.095832 second(s), 16 queries , Memcache On.

微信扫描
快速回复 返回顶部 返回列表
-

推荐专区

技术干货集中营

专家问答

用户帮助┃咨询与建议┃版主议事

我的提问

工程师杂谈

工程师创意

工程师职场

论坛电子赛事

社区活动专版

发烧友活动

-

嵌入式论坛

单片机/MCU论坛

FPGA|CPLD|ASIC论坛

DSP论坛

嵌入式系统论坛

-

电源技术论坛

电源技术论坛

-

硬件设计论坛

电路设计论坛

电子元器件论坛

控制|传感

总线技术|接口技术

-

测试测量论坛

LabVIEW论坛

Matlab论坛

测试测量技术专区

仪器仪表技术专区

-

EDA设计论坛

multisim论坛

PCB设计论坛

proteus论坛|仿真论坛

EasyEDA-中国人自已的EDA工具

-

综合技术与应用

电机控制

智能电网

光电及显示

参考设计中心

汽车电子技术论坛

医疗电子论坛

-

开源硬件

树莓派论坛

智能硬件论坛

开发快智能硬件开发平台

Intel物联网开发者专区

Waveshare

乐美客SBC专区

Arduino论坛

BeagleBone论坛

机器人论坛

创客神器NanoPi

小钢炮CANNON

比派科技banana pi专区

-

无线通信论坛

无线通信技术专区

天线|RF射频|微波|雷达技术

-

IC设计论坛

芯片测试与失效分析

Mixed Signal/SOC[数模混合芯片设计]

Analog/RF IC设计

设计与制造封装测试

-

个人版区

阿东Verilog技术专版

直流马达驱动电路设计

LabVIEW英雄联盟

特权同学FPGA专区

-

厂商专区

灵动微电子 MM32

盈鹏飞嵌入式

TI论坛

TI Deyisupport社区

芯灵思嵌入式论坛

Tisan

米尔科技

庆科社区

WIZnet技术专区

Cypress技术论坛

飞凌嵌入式

Qualcomm技术论坛

英创嵌入式

机智云GoKit论坛

-

检测技术与质量

电磁兼容(EMC)设计与整改

安规知识论坛

检测与认证

-

消费电子论坛

手机技术论坛

平板电脑/mid论坛

音视/视频/机顶盒论坛

-

电子论坛综合区

聚丰众筹官方社区

新人报道区

聚丰供应链

-

论坛服务区

-

供求信息发布

供需广告

招聘┃求职发布区

电子展览展会专区