安卓手机端号码识别

最近在做一个安卓手机端的号码识别项目,号码识别代码是用C开发的,要将其应用于安卓平台,可通过jni来实现,最初的想法是,由于训练文件是一旦确定,便不会再更改,所以希望将训练好的参数文件放只在安卓项目的assets文件夹中,由安卓端传递文件路径给C代码端,由C代码端直接访问解析参数文件,获取所需数据,经多次尝试失败后,发现jni中只能通过AAssetManager读取assets目录中文件内容,并将内容存储到一个char*的buffer中传给C代码。那么问题来了,这个buffer中存储的是文件中的所有内容,如果是knn训练好的xml文件,不仅有C代码端需要的两个Mat数据,还有一些其他杂项,我很难从中将Mat数据提取出来并加以区分,于是想到在训练的时候将训练数据和训练标签两个Mat数据保存在一个txt文件中,人为记住其大小,然后将其放在安卓项目的assets文件夹中,进而在预测的时候将其读入两个Mat中,先用于训练,创建Knn,以便进行预测,最后测试通过。

其中用到的一些函数如下:

1.      同时写两个Mat到txt文件中

intWriteMatToFile(char *fileName, Mat src,Mat src2)

{

FILE*fp;

fp= fopen(fileName, "wb+");//一定要是”wb+”方式,如果为”w+”方式,写出的txt文件中会都一些空格,导致数据不对

if(fp!= NULL)

{

           fwrite(src.data,src.elemSize(), src.rows * src.cols, fp);

           fwrite(src2.data,src2.elemSize(), src2.rows * src2.cols, fp);

           fclose(fp);

}

else

{

           return-1;

}

 

return0;

}

2.      读取txt文件中内容到char*的buffer中

stringstPath;//txt文件路径

FILE *fp;

           fp= fopen(stPath.c_str(), "rb");

           fseek(fp,0,SEEK_END);//定位到文件末

           intnFileLen = ftell(fp); //文件大小

           char*dst = (char*)malloc(nFileLen+1); /* 根据文件大小动态分配内存空间 */

           if(fp != NULL)

           {

                    fseek(fp,0, SEEK_SET);

                    fread(dst,nFileLen, 1, fp);

                    fclose(fp);

           }

3.      将文件路径中的’/’改为’\\’

charstParaName[256] = “E:/android/tt.txt”;

int length = strlen(stParaName);

           intcnt = 0;

           for(inti= 0; i < length ; i++) 

           {

                    if(stParaName[i]=='/')

                    {                          

                             cnt++;

                    }

           }

           intcount = 0;

           stringstPath;

           stPath.resize(length+cnt);      

           for(int i=0; i<length; ++i)

           {

                    if(stParaName[i] == '/')

                    {

                             count++;

                             stPath[i+count-1]= '\\';

                             stPath[i+count]= '\\';

                    }

                    else

                    {

                             stPath[i+count]= stParaName[i];  

                    }

           }

4.      Jni使用AAssetManager读取assets中文件内容

#include <android/asset_manager.h>
#include <android/asset_manager_jni.h>
JNIEXPORTjstring JNICALL Java_pack_idnumocr_IDNumOCR_IDNumOCR
      (JNIEnv *env, jclass, jintArray buf, jint w, jint h,jobject assetManager, jstring fileName, jint normSize, jint K)
   {
      LOGI("ReadAssets");
      AAssetManager* mgr = AAssetManager_fromJava(env, assetManager);
      if(mgr==NULL)
      {
         LOGI(" %s","AAssetManager==NULL");
         return 0;
      }

      jboolean iscopy;
      const char *mfile = env->GetStringUTFChars(fileName, &iscopy);
   //char *mfile = (char*)env->GetStringUTFChars(fileName, &iscopy);
      AAsset* asset = AAssetManager_open(mgr, mfile,AASSET_MODE_UNKNOWN);

      if(asset==NULL)
      {
         LOGI(" %s","asset==NULL");
         return 0;
      }

      off_t bufferSize = AAsset_getLength(asset);
      LOGI("file size : %d\n",bufferSize);
      char *buffer=(char *)malloc(bufferSize+1);
      buffer[bufferSize]=0;
      int numBytesRead = AAsset_read(asset, buffer, bufferSize);
      LOGI(": %s",buffer);

    //将string传给JString的方法
   string output = "abcdefg";
   LOGE("打印日志信息: string output = %d",output.length());
   
   int len = output.length();
    if (len == 0)
   {
      return NULL;//当数据为空,返回NULL
   }
const char* data = output.c_str();//使用NewStringUTF时,形参必须为const char*,若为char*时,会报错误JNI DETECTED ERROR IN APPLICATION: input is not valid Modified UTF-8: illegal start byte 0xff

//释放资源
   free(buffer); //一定要记得释放,否则导致程序闪退
   AAsset_close(asset); //一定要记得释放,否则导致程序闪退
   jstring result = env->NewStringUTF(data);
   env->ReleaseIntArrayElements(buf, cbuf, 0); //一定要记得释放,否则导致程序闪退
   env->ReleaseStringUTFChars(fileName, mfile); //一定要记得释放,否则导致程序闪退
   return result;
}
需要
#include <android/asset_manager.h>
#include <android/asset_manager_jni.h>
并且在Application.mk文件中设置APP_PLATFORM := android-15 #这句是设置最低安卓平台
在Android.mk文件中设置//LOCAL_LDLIBS += -lm -llog
LOCAL_LDLIBS += -L$(SYSROOT)/usr/lib -llog
LOCAL_LDLIBS += -landroid
特别地,native接口函数为public native static String numOCR(int[] buff, int w, int h,AssetManager ass,String trainedFile,int normSize, int K);
Java端对String是否为空的判断是:String a;if(a == null)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值