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 方法
修改为以下:
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
图片角度转换:
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
Android OpenCV集成摄像头图片动态识别车牌号的更多相关文章
- 利用face_recognition,dlib与OpenCV调用摄像头进行人脸识别
用已经搭建好 face_recognition,dlib 环境来进行人脸识别 未搭建好环境请参考:https://www.cnblogs.com/guihua-pingting/p/12201077. ...
- 手机摄像头扫描识别车牌号,移动端车牌识别sdk
一.移动端车牌识别应用背景 (技术交流:18701686857 QQ:283870550) 随着经济水平的不断提高,汽车数量的不断激增为汽车管理带来了不小的难度.路边违章停车的现象越来越频繁.现在, ...
- 基于TensorFlow的车牌号识别系统
简介 过去几周我一直在涉足深度学习领域,尤其是卷积神经网络模型.最近,谷歌围绕街景多位数字识别技术发布了一篇不错的paper.该文章描述了一个用于提取街景门牌号的单个端到端神经网络系统.然后,作者阐述 ...
- Android实现OCR扫描识别数字图片之图片扫描识别
[Android实例] Android实现OCR扫描识别数字图片之图片扫描识别 Android可以识别和扫描二维码,但是识别字符串呢? google提供了以下解决方案用的是原来HP的相关资料. 可以吧 ...
- 【OpenCV for Android】Android Studio集成OpenCV
准备工作 1.下载安装Android Studio(过程略). 2.下载Android OpenCV:https://opencv.org/releases.html,找到Android pack点击 ...
- WINDOWS系统Eclipse+NDK+Android + OpenCv
WINDOWS系统Eclipse+NDK+Android + OpenCv 参考文档博客 1 NDK环境搭建 http://jingyan.baidu.com/article/5d6edee22d90 ...
- Android原理揭秘系列之一动态墙纸
Livewallpaper,即动态墙纸,是Android的一大3D特色功能,用户可以在桌面选择加载动态墙纸,让自己的手机桌面背景旋动起来. 相对于静态桌面壁纸,动态墙纸可以展示各种动态变化的背景,而与 ...
- 基于QT和OpenCV的人脸检測识别系统(2)
紧接着上一篇博客的讲 第二步是识别部分 人脸识别 把上一阶段检測处理得到的人脸图像与数据库中的已知 人脸进行比对,判定人脸相应的人是谁(此处以白色文本显示). 人脸预处理 如今你已经得到一张人脸,你能 ...
- android opencv
最近工作需求:用opencv来先做一个demo.扫描照片进行边缘检测和透视矫正. 之后会加入照片降噪等处理. 请教了一下搞图像的同事.他的提议: 1.绿盟的“黄色照片检测” 用的是动态的opencv库 ...
随机推荐
- Kubernetes用户指南(四)--应用检查和调试
一.调试 当你的应用开始运行,那么DEBUG是不可避免的问题. 早些时候,我们在描述的是如何通过kubectl get pods来获得Pod的简单状态信息. 但是现在,这里有更多的方式来获得关于你的应 ...
- 转: Android微信智能心跳方案
http://mp.weixin.qq.com/s?__biz=MzAwNDY1ODY2OQ==&mid=207243549&idx=1&sn=4ebe4beb8123f1b5 ...
- Android自己定义(三)实现圆盘的百分比设置
近期一直在学习自己定义控件,昨天看到群里有人问怎样怎样实现圆盘样式的显示,学有所用,于是乎就有了这篇博客 先上图,一目了然 这里的显示颜色以及颜色块的大小你都能够自己设置 这里设置了三种颜色,相应三种 ...
- rpm安装找不到.so库文件(linux动态库连接的相关知识)(转)
1.找不到库文件的原因 库文件不存在 这种情况一般是因为所需要的包没装,只要安装相应的包就可以解决 存在而系统不知道 这种情况一般出现在自己编译软件时候 确保库文件所在的路径已加入系统,在/etc/l ...
- 【Python】self的用法扫盲
在Python中,我们有两个重要的概念:类与实例 例如:我们在现实生活中人就是一个类,实例就是具体到某一个男人(张三.李四等) 1.类:定义人这个类 class People(object): pas ...
- LRU的C++实现引申出的迭代器问题
leetcode上刷题.碰到一题实现LRU算法的题目. LRU,Least recently used.是一种常见的cache和页面替换算法.算法和原理可以参阅相关wiki. leetcode上的这一 ...
- Spring 配置dataSource和sessionFactory
记得导入dbcp和pool的jar包. <?xml version="1.0" encoding="UTF-8"?> <beans xml ...
- 网络方面的常用命令 & 常用端口介绍
在网络方面我们常常会用到如下命令: (1)ping命令:我们常常用来判断2台或2台以上的机器间是否网络连通. ping 192.168.1.88 -t 如果想看任何命令的参数是什么意思,我们只需要:命 ...
- net.reflector8.5.0.179过了试用期,要求输入序列号怎么办 注册机 破解
去网上搜索“reflector keygen注册机下载”,随便找一个版本下载(如果你之前下载的软件自带有“Keygen.exe”注册机的话,直接用自带的注册机就可以了)1.断开网络2.下载安装原程序, ...
- Angular2升级到Angular4
angular4终于在两天前发布了正式版本,那么怎么升级呢?其实angular2和angular4之间属于平滑过渡,并不像1和2之间颠覆性的重写代码. npm uninstall -g @angula ...