首先吐槽,搞了1天半,终于弄好了。自己android开发是小白,之前一门心思想在jni目录下读取xml文件,事实证明无论如何都不行的。好吧,后来发现资源文件应该都放在assets目录下,可是文件会被压缩,必须用什么assetmanager访问。opencv之前训练的两个svm.xml和ocr.xml文件,和一般的xml文件不同的,自己解析xml存到opencv的mat中太麻烦了。后来想了又想,还是放到sdcard中比较好,我是通过DDMS导入的,反正这次只是长姿势
声明:
1.本次导入的汽车图片还是包含西班牙的车牌的汽车,它与中国车牌最大的不同是不包含中文,西班牙车牌含有0-9数字及20个英文字符
2.在模拟机上运行速度貌似和vs2008一样慢,而且有识别错的可能,我碰到过
3.原理什么的见我前面的文章,我这次直接使用训练好的svm.xml和ocr.xml,并给出完整的识别流程。整个工程文件,待会上传csdn下载频道
环境需求:
eclipse juno
ndk(r9)
android sdk 4.4 api 19
opencv 2.4.7 android版本
cygwin
准备工作:
1.将E:\OpenCV-2.4.7.1-android-sdk\sdk中的java项目导入工作空间,日后凡事java端调用opencv的函数都要用到这个类库
2.安装opencv manager.apk,目前在android上所有的opencv程序都必须依附于android manger。在DOS窗口口中执行:
- adb install <OpenCV4Android SDKpath>/apk/OpenCV_2.4.7_Manager_2.14_armv7a-neon.apk
开始项目:
1.新建android application工程,取名CarPlate,右击项目属性,勾选opencv类库
2.将汽车照片复制到drwabale随便哪个目录下,然后编写布局文件activity_main.xml:
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical"
- tools:context=".MainActivity" >
-
- <TextView
- android:id="@+id/myshow"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="检测结果...." />
- <Button
- android:id="@+id/btn_plate"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:text="车牌检测"
- android:onClick="click"
- />
- <ImageView
- android:id="@+id/image_view"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:contentDescription="@string/str_proc"/>
- </LinearLayout>
3.新建CarPlateDetection类,编写本地化方法,作为调用c语言代码的入口:
- package com.example.carplate;
-
-
- public class CarPlateDetection {
- public static native String ImageProc(int[] pixels, int w, int h,String path);
- }
4.在dos窗口中,使用javah工具,自动生成c语言的头文件,具体方法就是在DOS窗口中跑到CarPlate项目的bin\classes目录下,输入:
- javah com.example.carplate.CarPlateDetection
之后,在classes目录下将会有com_example_carplate_CarPlateDetection.h文件
5.新建一个jni文件夹,把刚才的那个com_example_carplate_CarPlateDetection.h文件拷贝过来。然后编写Android.mk:
- LOCAL_PATH := $(call my-dir)
- include $(CLEAR_VARS)
- include E:/OpenCV-2.4.7.1-android-sdk/sdk/native/jni/OpenCV.mk
- LOCAL_SRC_FILES := ImageProc.cpp
- LOCAL_SRC_FILES += Plate_Recognition.cpp
- LOCAL_SRC_FILES += Plate_Segment.cpp
- LOCAL_SRC_FILES += Plate.cpp
- LOCAL_C_INCLUDES += $(LOCAL_PATH)
- LOCAL_MODULE := imageproc
- LOCAL_LDLIBS += -llog
- include $(BUILD_SHARED_LIBRARY)
6.修改AndroidManifest.xml,增加sdcard权限【就算是读取,也要加上!】:
- <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
- <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
7.回到MainActivity中,编写java端主要的代码:
- package com.example.carplate;
-
- import java.io.File;
-
- import org.opencv.android.BaseLoaderCallback;
- import org.opencv.android.LoaderCallbackInterface;
- import org.opencv.android.OpenCVLoader;
- import org.opencv.core.*;
-
- import android.os.Bundle;
- import android.os.Environment;
- import android.app.Activity;
- import android.graphics.Bitmap;
- import android.graphics.BitmapFactory;
- import android.view.Menu;
- import android.view.View;
- import android.widget.ImageView;
- import android.widget.TextView;
-
- public class MainActivity extends Activity {
- private ImageView imageView = null;
- private Bitmap bmp = null;
- private TextView m_text = null;
- private String path = null;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- imageView = (ImageView) findViewById(R.id.image_view);
- m_text = (TextView) findViewById(R.id.myshow);
-
- bmp = BitmapFactory.decodeResource(getResources(), R.drawable.test2);
- imageView.setImageBitmap(bmp);
- path = Environment.getExternalStorageDirectory().getAbsolutePath();
- System.out.println(path);
- }
-
-
- private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {
- @Override
- public void onManagerConnected(int status) {
- switch (status) {
- case LoaderCallbackInterface.SUCCESS:{
- System.loadLibrary("imageproc");
- } break;
- default:{
- super.onManagerConnected(status);
- } break;
- }
- }
- };
-
- public void click(View view){
- System.out.println("entering the jni");
- int w = bmp.getWidth();
- int h = bmp.getHeight();
- int[] pixels = new int[w * h];
- String result=null;
- bmp.getPixels(pixels, 0, w, 0, 0, w, h);
-
- result=CarPlateDetection.ImageProc(pixels, w, h,path);
- System.out.println(result);
- m_text.setText(result);
- }
-
- @Override
- protected void onResume() {
-
- super.onResume();
-
-
- OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_3, this, mLoaderCallback);
- }
- }
8.好了,现在开始主要的C语言部分。对应头文件和源文件内容分别是(这些文件也放在jni目录下):
Plate.h:【车牌类,包含车牌数据结构及对识别的车牌字符顺序调整函数】
- #ifndef Plate_h
- #define Plate_h
-
- #include <string.h>
- #include <vector>
-
- #include <cv.h>
- #include <highgui.h>
- #include <cvaux.h>
-
- using namespace std;
- using namespace cv;
-
- class Plate{
- public:
- Plate();
- Plate(Mat img, Rect pos);
- string str();
- Rect position;
- Mat plateImg;
- vector<char> chars;
- vector<Rect> charsPos;
- };
-
- #endif
Plate.cpp:
- #include "Plate.h"
-
- Plate::Plate(){
- }
-
- Plate::Plate(Mat img, Rect pos){
- plateImg=img;
- position=pos;
- }
-
- string Plate::str(){
- string result="";
-
- vector<int> orderIndex;
- vector<int> xpositions;
- for(int i=0; i< charsPos.size(); i++){
- orderIndex.push_back(i);
- xpositions.push_back(charsPos[i].x);
- }
- float min=xpositions[0];
- int minIdx=0;
- for(int i=0; i< xpositions.size(); i++){
- min=xpositions[i];
- minIdx=i;
- for(int j=i; j<xpositions.size(); j++){
- if(xpositions[j]<min){
- min=xpositions[j];
- minIdx=j;
- }
- }
- int aux_i=orderIndex[i];
- int aux_min=orderIndex[minIdx];
- orderIndex[i]=aux_min;
- orderIndex[minIdx]=aux_i;
-
- float aux_xi=xpositions[i];
- float aux_xmin=xpositions[minIdx];
- xpositions[i]=aux_xmin;
- xpositions[minIdx]=aux_xi;
- }
- for(int i=0; i<orderIndex.size(); i++){
- result=result+chars[orderIndex[i]];
- }
- return result;
- }
PlateSegment.h:【功能:从一张汽车图片中分割得到一张车牌】
- #ifndef seg_h
- #define seg_h
-
- #include<iostream>
- #include <cv.h>
- #include <highgui.h>
- #include <cvaux.h>
- #include "Plate.h"
-
- using namespace std;
- using namespace cv;
-
- bool verifySizes(RotatedRect mr);
- Mat histeq(Mat in);
- vector<Plate> segment(Mat input);
-
- #endif
PlateSegment.cpp:
- #include "Plate_Segment.h"
-
-
- bool verifySizes(RotatedRect mr)
- {
- float error=0.4;
-
- float aspect=4.7272;
-
- int min= 15*aspect*15;
- int max= 125*aspect*125;
-
- float rmin= aspect-aspect*error;
- float rmax= aspect+aspect*error;
-
- int area= mr.size.height * mr.size.width;
- float r= (float)mr.size.width / (float)mr.size.height;
- if(r<1)
- r= (float)mr.size.height / (float)mr.size.width;
-
- if(( area < min || area > max ) || ( r < rmin || r > rmax )){
- return false;
- }else{
- return true;
- }
- }
-
- Mat histeq(Mat in)
- {
- Mat out(in.size(), in.type());
- if(in.channels()==3){
- Mat hsv;
- vector<Mat> hsvSplit;
- cvtColor(in, hsv, CV_BGR2HSV);
- split(hsv, hsvSplit);
- equalizeHist(hsvSplit[2], hsvSplit[2]);
- merge(hsvSplit, hsv);
- cvtColor(hsv, out, CV_HSV2BGR);
- }else if(in.channels()==1){
- equalizeHist(in, out);
- }
-
- return out;
- }
-
- vector<Plate> segment(Mat input){
- vector<Plate> output;
-
-
- Mat img_gray;
- cvtColor(input, img_gray, CV_BGR2GRAY);
- blur(img_gray, img_gray, Size(5,5));
-
-
- Mat img_sobel;
- Sobel(img_gray, img_sobel, CV_8U, 1, 0, 3, 1, 0, BORDER_DEFAULT);
-
-
- Mat img_threshold;
- threshold(img_sobel, img_threshold, 0, 255, CV_THRESH_OTSU+CV_THRESH_BINARY);
-
-
- Mat element = getStructuringElement(MORPH_RECT, Size(17, 3) );
- morphologyEx(img_threshold, img_threshold, CV_MOP_CLOSE, element);
-
-
- vector< vector< Point> > contours;
- findContours(img_threshold,
- contours,
- CV_RETR_EXTERNAL,
- CV_CHAIN_APPROX_NONE);
-
-
- vector<vector<Point> >::iterator itc= contours.begin();
- vector<RotatedRect> rects;
-
-
- while (itc!=contours.end()) {
-
- RotatedRect mr= minAreaRect(Mat(*itc));
- if( !verifySizes(mr)){
- itc= contours.erase(itc);
- }else{
- ++itc;
- rects.push_back(mr);
- }
- }
-
- cv::Mat result;
- input.copyTo(result);
-
- for(int i=0; i< rects.size(); i++)
- {
-
- float minSize=(rects[i].size.width < rects[i].size.height)?rects[i].size.width:rects[i].size.height;
- minSize=minSize-minSize*0.5;
-
- srand ( time(NULL) );
-
- Mat mask;
- mask.create(input.rows + 2, input.cols + 2, CV_8UC1);
- mask= Scalar::all(0);
- int loDiff = 30;
- int upDiff = 30;
- int connectivity = 4;
- int newMaskVal = 255;
- int NumSeeds = 10;
- Rect ccomp;
- int flags = connectivity + (newMaskVal << 8 ) + CV_FLOODFILL_FIXED_RANGE + CV_FLOODFILL_MASK_ONLY;
- for(int j=0; j<NumSeeds; j++){
- Point seed;
- seed.x=rects[i].center.x+rand()%(int)minSize-(minSize/2);
- seed.y=rects[i].center.y+rand()%(int)minSize-(minSize/2);
- int area = floodFill(input, mask, seed, Scalar(255,0,0), &ccomp, Scalar(loDiff, loDiff, loDiff), Scalar(upDiff, upDiff, upDiff), flags);
- }
-
-
-
- vector<Point> pointsInterest;
- Mat_<uchar>::iterator itMask= mask.begin<uchar>();
- Mat_<uchar>::iterator end= mask.end<uchar>();
- for( ; itMask!=end; ++itMask)
- if(*itMask==255)
- pointsInterest.push_back(itMask.pos());
-
- RotatedRect minRect = minAreaRect(pointsInterest);
-
- if(verifySizes(minRect)){
-
- Point2f rect_points[4]; minRect.points( rect_points );
-
-
- float r= (float)minRect.size.width / (float)minRect.size.height;
- float angle=minRect.angle;
- if(r<1)
- angle=90+angle;
- Mat rotmat= getRotationMatrix2D(minRect.center, angle,1);
-
-
- Mat img_rotated;
- warpAffine(input, img_rotated, rotmat, input.size(), CV_INTER_CUBIC);
-
-
- Size rect_size=minRect.size;
- if(r < 1)
- swap(rect_size.width, rect_size.height);
- Mat img_crop;
- getRectSubPix(img_rotated, rect_size, minRect.center, img_crop);
-
- Mat resultResized;
- resultResized.create(33,144, CV_8UC3);
- resize(img_crop, resultResized, resultResized.size(), 0, 0, INTER_CUBIC);
-
- Mat grayResult;
- cvtColor(resultResized, grayResult, CV_BGR2GRAY);
- blur(grayResult, grayResult, Size(3,3));
- grayResult=histeq(grayResult);
- output.push_back(Plate(grayResult,minRect.boundingRect()));
- }
- }
- return output;
- }
PlateRecogntion.h:【从车牌图片上识别各个字符】
- #ifndef rec_h
- #define rec_h
- #include <cv.h>
- #include <highgui.h>
- #include <cvaux.h>
- #include <ml.h>
-
- #include <iostream>
- #include <vector>
- #define HORIZONTAL 1
- #define VERTICAL 0
-
- using namespace std;
- using namespace cv;
-
- bool verifySizes(Mat r);
- Mat preprocessChar(Mat in);
- Mat ProjectedHistogram(Mat img, int t);
- Mat features(Mat in, int sizeData);
- int classify(Mat f,CvANN_MLP *ann);
- void train(Mat TrainData, Mat classes,CvANN_MLP *ann,int nlayers);
- #endif
PlateRecognition.cpp:
- #include "Plate_Recognition.h"
-
- const int numCharacters=30;
-
- bool verifySizes(Mat r){
-
- float aspect=45.0f/77.0f;
- float charAspect= (float)r.cols/(float)r.rows;
- float error=0.35;
- float minHeight=15;
- float maxHeight=28;
-
- float minAspect=0.2;
- float maxAspect=aspect+aspect*error;
-
- float area=countNonZero(r);
-
- float bbArea=r.cols*r.rows;
-
- float percPixels=area/bbArea;
-
- if(percPixels < 0.8 && charAspect > minAspect && charAspect < maxAspect && r.rows >= minHeight && r.rows < maxHeight)
- return true;
- else
- return false;
-
- }
-
- Mat preprocessChar(Mat in){
-
- int h=in.rows;
- int w=in.cols;
- int charSize=20;
- Mat transformMat=Mat::eye(2,3,CV_32F);
- int m=max(w,h);
- transformMat.at<float>(0,2)=m/2 - w/2;
- transformMat.at<float>(1,2)=m/2 - h/2;
-
- Mat warpImage(m,m, in.type());
- warpAffine(in, warpImage, transformMat, warpImage.size(), INTER_LINEAR, BORDER_CONSTANT, Scalar(0) );
-
- Mat out;
- resize(warpImage, out, Size(charSize, charSize) );
-
- return out;
- }
-
-
- Mat ProjectedHistogram(Mat img, int t)
- {
- int sz=(t)?img.rows:img.cols;
- Mat mhist=Mat::zeros(1,sz,CV_32F);
-
- for(int j=0; j<sz; j++){
- Mat data=(t)?img.row(j):img.col(j);
- mhist.at<float>(j)=countNonZero(data);
- }
-
-
- double min, max;
- minMaxLoc(mhist, &min, &max);
-
- if(max>0)
- mhist.convertTo(mhist,-1 , 1.0f/max, 0);
-
- return mhist;
- }
-
- Mat features(Mat in, int sizeData){
-
- Mat vhist=ProjectedHistogram(in,VERTICAL);
- Mat hhist=ProjectedHistogram(in,HORIZONTAL);
-
-
- Mat lowData;
- resize(in, lowData, Size(sizeData, sizeData) );
-
-
- int numCols=vhist.cols+hhist.cols+lowData.cols*lowData.cols;
-
- Mat out=Mat::zeros(1,numCols,CV_32F);
-
- int j=0;
- for(int i=0; i<vhist.cols; i++)
- {
- out.at<float>(j)=vhist.at<float>(i);
- j++;
- }
- for(int i=0; i<hhist.cols; i++)
- {
- out.at<float>(j)=hhist.at<float>(i);
- j++;
- }
- for(int x=0; x<lowData.cols; x++)
- {
- for(int y=0; y<lowData.rows; y++){
- out.at<float>(j)=(float)lowData.at<unsigned char>(x,y);
- j++;
- }
- }
-
- return out;
- }
-
-
- int classify(Mat f,CvANN_MLP *ann){
- int result=-1;
- Mat output(1, 30, CV_32FC1);
- (*ann).predict(f, output);
- Point maxLoc;
- double maxVal;
- minMaxLoc(output, 0, &maxVal, 0, &maxLoc);
- return maxLoc.x;
- }
-
- void train(Mat TrainData, Mat classes,CvANN_MLP *ann,int nlayers){
- Mat layers(1,3,CV_32SC1);
- layers.at<int>(0)= TrainData.cols;
- layers.at<int>(1)= nlayers;
- layers.at<int>(2)= 30;
- (*ann).create(layers, CvANN_MLP::SIGMOID_SYM, 1, 1);
-
-
-
- Mat trainClasses;
- trainClasses.create( TrainData.rows, 30, CV_32FC1 );
- for( int i = 0; i < trainClasses.rows; i++ )
- {
- for( int k = 0; k < trainClasses.cols; k++ )
- {
-
- if( k == classes.at<int>(i) )
- trainClasses.at<float>(i,k) = 1;
- else
- trainClasses.at<float>(i,k) = 0;
- }
- }
- Mat weights( 1, TrainData.rows, CV_32FC1, Scalar::all(1) );
-
-
- (*ann).train( TrainData, trainClasses, weights );
- }
然后,编写我们的ImageProc.cpp:【这边我把sdcard的路径都写死了,大家自己调整下】
- #include<com_example_carplate_CarPlateDetection.h>
- #include "Plate.h"
- #include "Plate_Segment.h"
- #include "Plate_Recognition.h"
- #include <android/log.h>
- #define LOG_TAG "System.out"
- #define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
- #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__)
- #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- JNIEXPORT jstring JNICALL Java_com_example_carplate_CarPlateDetection_ImageProc
- (JNIEnv *env, jclass obj, jintArray buf, jint w, jint h,jstring dir){
- jint *cbuf;
- cbuf = env->GetIntArrayElements(buf, false);
-
-
- Size size;
- size.width = w;
- size.height = h;
-
- Mat imageData,input;
- imageData = Mat(size, CV_8UC4, (unsigned char*)cbuf);
- input = Mat(size, CV_8UC3);
- cvtColor(imageData,input,CV_BGRA2BGR);
-
- vector<Plate> posible_regions = segment(input);
-
- const char strCharacters[] = {'0','1','2','3','4','5','6','7','8','9','B', 'C', 'D', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'R', 'S', 'T', 'V', 'W', 'X', 'Y', 'Z'};
- CvANN_MLP ann;
-
- FileStorage fs;
-
- fs.open("/storage/sdcard/SVM.xml", FileStorage::READ);
- Mat SVM_TrainingData;
- Mat SVM_Classes;
- fs["TrainingData"] >> SVM_TrainingData;
- fs["classes"] >> SVM_Classes;
- if(fs.isOpened())
- LOGD("read success!");
-
-
- LOGD("size:%d",SVM_TrainingData.rows);
- SVM_TrainingData.convertTo(SVM_TrainingData, CV_32FC1);
- SVM_Classes.convertTo(SVM_Classes, CV_32FC1);
- CvSVMParams SVM_params;
- SVM_params.svm_type = CvSVM::C_SVC;
- SVM_params.kernel_type = CvSVM::LINEAR;
- SVM_params.degree = 0;
- SVM_params.gamma = 1;
- SVM_params.coef0 = 0;
- SVM_params.C = 1;
- SVM_params.nu = 0;
- SVM_params.p = 0;
- SVM_params.term_crit = cvTermCriteria(CV_TERMCRIT_ITER, 1000, 0.01);
- LOGD("Everything is ready");
-
- LOGD("START TO ENTER SVM PREDICT");
- CvSVM svmClassifier(SVM_TrainingData, SVM_Classes, Mat(), Mat(), SVM_params);
-
- vector<Plate> plates;
- for(int i=0; i< posible_regions.size(); i++)
- {
- Mat img=posible_regions[i].plateImg;
- Mat p= img.reshape(1, 1);
- p.convertTo(p, CV_32FC1);
-
- int response = (int)svmClassifier.predict( p );
- if(response==1)
- plates.push_back(posible_regions[i]);
- }
- LOGD("SVM PREDICT FINISH");
- fs.release();
-
- FileStorage fs2;
- fs2.open("/storage/sdcard/OCR.xml", FileStorage::READ);
- Mat TrainingData;
- Mat Classes;
- fs2["TrainingDataF15"] >> TrainingData;
- fs2["classes"] >> Classes;
- LOGD("size:%d",TrainingData.rows);
- LOGD("START TO TRAIN MLP");
-
- train(TrainingData, Classes,&ann,10);
- LOGD("FINISH TRAIN MLP");
- Mat inputs=plates[0].plateImg;
- Plate mplate;
-
-
- Mat img_threshold;
- threshold(inputs, img_threshold, 60, 255, CV_THRESH_BINARY_INV);
-
- Mat img_contours;
- img_threshold.copyTo(img_contours);
-
- vector< vector< Point> > contours;
- findContours(img_contours,
- contours,
- CV_RETR_EXTERNAL,
- CV_CHAIN_APPROX_NONE);
-
- vector<vector<Point> >::iterator itc= contours.begin();
- LOGD("Before extracting hist and low-resolution image");
-
- while (itc!=contours.end()) {
-
-
- Rect mr= boundingRect(Mat(*itc));
-
- Mat auxRoi(img_threshold, mr);
- if(verifySizes(auxRoi)){
- auxRoi=preprocessChar(auxRoi);
- LOGD("FINISH extracting features");
-
- Mat f=features(auxRoi,15);
-
- LOGD("START TO CLASSIFY IN MLP");
- int character=classify(f,&ann);
- mplate.chars.push_back(strCharacters[character]);
- LOGD("FINISH CLASSIFY");
- mplate.charsPos.push_back(mr);
-
- }
- ++itc;
- }
- fs2.release();
- string licensePlate=mplate.str();
-
-
- env->ReleaseIntArrayElements(buf, cbuf, 0);
-
- return env->NewStringUTF(licensePlate.c_str());
- }
9.最后用cygwin进行交叉编译:
打开cygwin,输入
cd /cygdrive/e/worksapce/CarPlate
ndk-build
记得按F5,并clean一下工程,这是在libs目录下有个libimage_proc.so文件,
10.通过DDMS向sdcard中添加文件:
打开虚拟机,点击DDMS:
如果能进入如下界面的话:【否则点击左半边的小倒三角,选择reset adb】
点击右半边右上角第二个按钮:
跑到如storage/sdcard目录下,将之前训练好的SVM.XML和OCR.XML都加入进去。
如果cygwin没有报错的话,然后运行我们的android applicatoin
效果图:
注意:
1.如果想玩国内车牌的话,可以用我之前 2篇文章的方法,自己人工分类图片【不用你裁剪,只要挑选就行】,并运行程序得到相应的xml文件
2.这边我的路径和资源摆放都很不够理想,暂时也想不出更好的了
完整的程序下载地址:http://download.csdn.net/detail/jinshengtao/6828651
里面的assets文件夹下有训练好的svm.xml和ocr.xml,把他放到sdcard中吧
OpenCV Error: One of arguments' values is out of range (there should be at least one input and one output and every hidden layer must have more than 1 neuron) in CvANN_MLP::create, file /home/reports/ci/slave_desktop/50-SDK/opencv/modules/ml/src/ann_mlp.cpp, line 244
错误提示:
Fatal signal 11 (SIGSEGV) at 0x00000010 (code=1), thread 22543 (xample.carplate)
网上有人说这是jin的问题或者是线程问题,说和4.0以上系统有关系,请问大家有遇到过这个问题么?该怎么解决呢?
1. E/OpenCV_for_Tegra(1970): Tegra Version detected: 0
2. E/cv::error()(1970): OpenCV Error: Bad argument (train data must be floating-point matrix) in cvCheckTrainData, file /home/reports/ci/slave_desktop/50-SDK/opencv/modules/ml/src/inner_functions.cpp, line 857
3. Fatal signal 11 (SIGSEGV) at 0xdeadbaad (code=1)
比如我使用nexus 7,把xml文件放在根目录新建的文件夹detect文件夹里面。
路径写成/storage/sdcard0/detect/OCR.xml
2.确保你的图片在ndk那边能否正确读入
3.建议在vs2008端把代码能运行起来了,再搞mac上
4.我也是学习<matering opencv....>的笔记,有想不通的,你可以看原书