Android OpenCV集成摄像头图片动态识别车牌号

  最近两天开发一个使用OpenCV集成的一个识别车牌号的项目,困难重重,总结一下相关经验,以及开发注意事项;

一、开发环境:

     Android Studio 个人版本 3.1.4

     NDK下载:14b

     CMake:Android Studio SDK Tools中下载

     参考资料:https://github.com/zeusees/HyperLPR   集成有冲突未解决;

 

                    很实用的一个Dmeo以这个为例

                    https://blog.csdn.net/u011686167/article/details/79029765   

 

                    楼主人很好,给我解答疑问;附上博主Demo下载地址:

                    https://download.csdn.net/download/u011686167/10899892

     集成中遇到的问题:

     一、环境配置的问题:

           NDK:尝试使用最新版本,但是一直有冲突,出现问题,14b使用兼容性比较好

           CMake:

           OpenCV类库: openCVLibrary330

     二、项目集成问题:

         (1)下载模型文件替换和倒入assets/pr下面的文件,报错如下:

            "/storage/emulated/0/pr/HorizonalFinemapping.prototxt") in bool cv::dnn::ReadProtoFromTextFile(

             const char*,google::protobuf::Message*), file /build/master_pack-android/opencv/modules/dnn/src

            /caffe/caffe_io.cpp, line 1113

           (2)添加摄像头权限

           (3)问题:只能横向识别车牌号,纵向不能识别,并且相机方向不对:

             解决相机显示正常:

             参考资料   https://blog.csdn.net/u010112268/article/details/80420454               

             将下图文件中的  deliverAndDrawFrame 方法

              

              修改为以下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
protected void deliverAndDrawFrame(CvCameraViewFrame frame){
    Mat modified;
 
    if (mListener != null) {
        modified = mListener.onCameraFrame(frame);
    } else {
        modified = frame.rgba();
    }
 
    boolean bmpValid = true;
    if (modified!= null) {
        try {
            Utils.matToBitmap(modified,mCacheBitmap);
        } catch(Exceptione) {
            Log.e(TAG, "Mattype: " + modified);
            Log.e(TAG, "Bitmaptype: " + mCacheBitmap.getWidth() + "*" + mCacheBitmap.getHeight());
            Log.e(TAG, "Utils.matToBitmap()throws an exception: " +e.getMessage());
            bmpValid = false;
        }
    }
 
    if (bmpValid&& mCacheBitmap != null) {
        Canvas canvas =getHolder().lockCanvas();
        if (canvas!= null) {
            canvas.drawColor(0,android.graphics.PorterDuff.Mode.CLEAR);
            /*if (BuildConfig.DEBUG)
                Log.d(TAG, "mStretchvalue: " + mScale);
 
            if (mScale != 0) {
               canvas.drawBitmap(mCacheBitmap, new Rect(0,0,mCacheBitmap.getWidth(),mCacheBitmap.getHeight()),
                     newRect((int)((canvas.getWidth() - mScale*mCacheBitmap.getWidth()) / 2),
                    (int)((canvas.getHeight() - mScale*mCacheBitmap.getHeight()) / 2),
                     (int)((canvas.getWidth() -mScale*mCacheBitmap.getWidth()) / 2 + mScale*mCacheBitmap.getWidth()),
                    (int)((canvas.getHeight() - mScale*mCacheBitmap.getHeight()) / 2 +mScale*mCacheBitmap.getHeight())), null);
            } else {
                canvas.drawBitmap(mCacheBitmap, new Rect(0,0,mCacheBitmap.getWidth(),mCacheBitmap.getHeight()),
                     newRect((canvas.getWidth() - mCacheBitmap.getWidth()) / 2,
                     (canvas.getHeight()- mCacheBitmap.getHeight()) / 2,
                     (canvas.getWidth() -mCacheBitmap.getWidth()) / 2 + mCacheBitmap.getWidth(),
                     (canvas.getHeight()- mCacheBitmap.getHeight()) / 2 + mCacheBitmap.getHeight()), null);
            }*/
 
            /*----------------------------修改预览旋转90度问题--------------------------------*/
            canvas.rotate(90,0,0);
            float scale= canvas.getWidth() / (float)mCacheBitmap.getHeight();
            float scale2= canvas.getHeight() / (float)mCacheBitmap.getWidth();
            if(scale2> scale){
                scale = scale2;
            }
            if (scale!= 0) {
                canvas.scale(scale,scale,0,0);
            }
            canvas.drawBitmap(mCacheBitmap, 0, -mCacheBitmap.getHeight(), null);
            /*----------------------------修改预览旋转90度问题--------------------------------*/
 
            if (mFpsMeter != null) {
                mFpsMeter.measure();
                mFpsMeter.draw(canvas, 20, 30);
            }
            getHolder().unlockCanvasAndPost(canvas);
        }
    }
 
}

     

 

         解决图片不能纵向识别方法:参考资料 https://blog.csdn.net/hujiameihuxu/article/details/78810100

          图片角度转换:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
Mat matRotateClockWise90(Mat src)
{
    if (src.empty())
    {
        qDebug()<<"RorateMat src is empty!";
    }
    // 矩阵转置
    transpose(src, src);
    //0: 沿X轴翻转; >0: 沿Y轴翻转; <0: 沿X轴和Y轴翻转
    flip(src, src, 1);// 翻转模式,flipCode == 0垂直翻转(沿X轴翻转),flipCode>0水平翻转(沿Y轴翻转),flipCode<0水平垂直翻转(先沿X轴翻转,再沿Y轴翻转,等价于旋转180°)
    return src;
}
  
Mat matRotateClockWise180(Mat src)//顺时针180
{
    if (src.empty())
    {
        qDebug() << "RorateMat src is empty!";
    }
     
    //0: 沿X轴翻转; >0: 沿Y轴翻转; <0: 沿X轴和Y轴翻转
    flip(src, src, 0);// 翻转模式,flipCode == 0垂直翻转(沿X轴翻转),flipCode>0水平翻转(沿Y轴翻转),flipCode<0水平垂直翻转(先沿X轴翻转,再沿Y轴翻转,等价于旋转180°)
    flip(src, src, 1);
    return src;
    //transpose(src, src);// 矩阵转置
}
  
Mat matRotateClockWise270(Mat src)//顺时针270
{
    if (src.empty())
    {
        qDebug() << "RorateMat src is empty!";
    }
    // 矩阵转置
    //transpose(src, src);
    //0: 沿X轴翻转; >0: 沿Y轴翻转; <0: 沿X轴和Y轴翻转
    transpose(src, src);// 翻转模式,flipCode == 0垂直翻转(沿X轴翻转),flipCode>0水平翻转(沿Y轴翻转),flipCode<0水平垂直翻转(先沿X轴翻转,再沿Y轴翻转,等价于旋转180°)
    flip(src, src, 0);
    return src;
}
  
Mat myRotateAntiClockWise90(Mat src)//逆时针90°
{
    if (src.empty())
    {
      qDebug()<<"mat is empty!";
    }
    transpose(src, src);
    flip(src, src, 0);

  进行转化:

    

 

  本人Demo代码地址以及模型地址:https://gitee.com/anan9303/PrjAndroid.git

 

 

 

 

 

           

 

posted @   张亚楠  阅读(4354)  评论(2编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 通过 API 将Deepseek响应流式内容输出到前端
· 因为Apifox不支持离线,我果断选择了Apipost!
点击右上角即可分享
微信分享提示