Android实现扫一扫识别图像数字(使用训练的库拍照查看扫描结果)(下)
Posted Tobey_r1
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android实现扫一扫识别图像数字(使用训练的库拍照查看扫描结果)(下)相关的知识,希望对你有一定的参考价值。
android实现扫一扫识别图像数字(使用训练的库拍照查看扫描结果)(下)
关于
最近在整理电脑上面的项目,想起之前有研究学习图像数字识别功能实现,只记录了上篇,然后下半篇忘记写了,现在在回来看一下,有的地方自己也有些生疏了,总之也是借鉴了网上一部分。本篇代码内容较多,**不想细看的话可以直接跳到末尾,我会将源码放出来。**想知道如何训练数据的可以参考上一篇博文《Android实现扫一扫识别图像数字(镂空图像数字Tesseract训练)(上)》
效果图
也可以下载apk试一下效果:
链接:https://pan.baidu.com/s/1TA2o4ABt3bnqjTAA1gIpjQ
提取码:1234
当然了,识别效果不是每次都正确的,因为训练库里面的数据不够庞大,所以误差率还是不小的,不然如果想要正式使用的话,有大量的训练数据就没关系了
第一步,添加我们的训练库
在res/下新建raw文件夹,将我们上篇训练的num.traineddata拷贝进去:
这里我把我的训练好的数据放到网盘里:
链接:https://pan.baidu.com/s/1ekvpF6nZbPfNOxJGpOTjOg
提取码:1234
编写扫描框控件
public final class ScannerFinderView extends RelativeLayout {
private static final int[] SCANNER_ALPHA = { 0, 64, 128, 192, 255, 192, 128, 64 };
private static final long ANIMATION_DELAY = 100L;
private static final int OPAQUE = 0xFF;
private static final int MIN_FOCUS_BOX_WIDTH = 50;
private static final int MIN_FOCUS_BOX_HEIGHT = 50;
private static final int MIN_FOCUS_BOX_TOP = 200;
private static Point ScrRes;
private int top;
private Paint mPaint;
private int mScannerAlpha;
private int mMaskColor;
private int mFrameColor;
private int mLaserColor;
private int mTextColor;
private int mFocusThick;
private int mAngleThick;
private int mAngleLength;
private Rect mFrameRect; //绘制的Rect
private Rect mRect; //返回的Rect
public ScannerFinderView(Context context) {
this(context, null);
}
public ScannerFinderView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public ScannerFinderView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mPaint = new Paint();
mPaint.setAntiAlias(true);
Resources resources = getResources();
mMaskColor = resources.getColor(R.color.finder_mask);
mFrameColor = resources.getColor(R.color.finder_frame);
mLaserColor = resources.getColor(R.color.finder_laser);
mTextColor = resources.getColor(R.color.white);
mFocusThick = 1;
mAngleThick = 8;
mAngleLength = 40;
mScannerAlpha = 0;
init(context);
this.setOnTouchListener(getTouchListener());
}
private void init(Context context) {
if (isInEditMode()) {
return;
}
// 需要调用下面的方法才会执行onDraw方法
setWillNotDraw(false);
if (mFrameRect == null) {
ScrRes = ScreenUtils.getScreenResolution(context);
int width = ScrRes.x * 3 / 5;
int height = width;
width = width == 0
? MIN_FOCUS_BOX_WIDTH
: width < MIN_FOCUS_BOX_WIDTH ? MIN_FOCUS_BOX_WIDTH : width;
height = height == 0
? MIN_FOCUS_BOX_HEIGHT
: height < MIN_FOCUS_BOX_HEIGHT ? MIN_FOCUS_BOX_HEIGHT : height;
int left = (ScrRes.x - width) / 2;
int top = (ScrRes.y - height) / 5;
this.top = top; //记录初始距离上方距离
mFrameRect = new Rect(left, top, left + width, top + height);
mRect = mFrameRect;
}
}
public Rect getRect() {
return mRect;
}
@Override
public void onDraw(Canvas canvas) {
if (isInEditMode()) {
return;
}
Rect frame = mFrameRect;
if (frame == null) {
return;
}
int width = canvas.getWidth();
int height = canvas.getHeight();
// 绘制焦点框外边的暗色背景
mPaint.setColor(mMaskColor);
canvas.drawRect(0, 0, width, frame.top, mPaint);
canvas.drawRect(0, frame.top, frame.left, frame.bottom + 1, mPaint);
canvas.drawRect(frame.right + 1, frame.top, width, frame.bottom + 1, mPaint);
canvas.drawRect(0, frame.bottom + 1, width, height, mPaint);
drawFocusRect(canvas, frame);
drawAngle(canvas, frame);
drawText(canvas, frame);
drawLaser(canvas, frame);
}
/**
* 画聚焦框,白色的
*
* @param canvas
* @param rect
*/
private void drawFocusRect(Canvas canvas, Rect rect) {
// 绘制焦点框(黑色)
mPaint.setColor(mFrameColor);
// 上
canvas.drawRect(rect.left + mAngleLength, rect.top, rect.right - mAngleLength, rect.top + mFocusThick, mPaint);
// 左
canvas.drawRect(rect.left, rect.top + mAngleLength, rect.left + mFocusThick, rect.bottom - mAngleLength,
mPaint);
// 右
canvas.drawRect(rect.right - mFocusThick, rect.top + mAngleLength, rect.right, rect.bottom - mAngleLength,
mPaint);
// 下
canvas.drawRect(rect.left + mAngleLength, rect.bottom - mFocusThick, rect.right - mAngleLength, rect.bottom,
mPaint);
}
/**
* 画四个角
*
* @param canvas
* @param rect
*/
private void drawAngle(Canvas canvas, Rect rect) {
mPaint.setColor(mLaserColor);
mPaint.setAlpha(OPAQUE);
mPaint.setStyle(Paint.Style.FILL);
mPaint.setStrokeWidth(mAngleThick);
int left = rect.left;
int top = rect.top;
int right = rect.right;
int bottom = rect.bottom;
// 左上角
canvas.drawRect(left, top, left + mAngleLength, top + mAngleThick, mPaint);
canvas.drawRect(left, top, left + mAngleThick, top + mAngleLength, mPaint);
// 右上角
canvas.drawRect(right - mAngleLength, top, right, top + mAngleThick, mPaint);
canvas.drawRect(right - mAngleThick, top, right, top + mAngleLength, mPaint);
// 左下角
canvas.drawRect(left, bottom - mAngleLength, left + mAngleThick, bottom, mPaint);
canvas.drawRect(left, bottom - mAngleThick, left + mAngleLength, bottom, mPaint);
// 右下角
canvas.drawRect(right - mAngleLength, bottom - mAngleThick, right, bottom, mPaint);
canvas.drawRect(right - mAngleThick, bottom - mAngleLength, right, bottom, mPaint);
}
private void drawText(Canvas canvas, Rect rect) {
int margin = 40;
mPaint.setColor(mTextColor);
mPaint.setTextSize(getResources().getDimension(R.dimen.text_size_13sp)); //13dp
String text = getResources().getString(R.string.auto_scan_notification); //<stringname="auto_scan_notification">将扫描内容放入框内,即可自动扫描</string>
Paint.FontMetrics fontMetrics = mPaint.getFontMetrics();
float fontTotalHeight = fontMetrics.bottom - fontMetrics.top;
float offY = fontTotalHeight / 2 - fontMetrics.bottom;
float newY = rect.bottom + margin + offY;
float left = (ScreenUtils.getScreenWidth() - mPaint.getTextSize() * text.length()) / 2;
canvas.drawText(text, left, newY, mPaint);
}
private void drawLaser(Canvas canvas, Rect rect) {
// 绘制焦点框内固定的一条扫描线
mPaint.setColor(mLaserColor);
mPaint.setAlpha(SCANNER_ALPHA[mScannerAlpha]);
mScannerAlpha = (mScannerAlpha + 1) % SCANNER_ALPHA.length;
int middle = rect.height() / 2 + rect.top;
canvas.drawRect(rect.left + 2, middle - 1, rect.right - 1, middle + 2, mPaint);
mHandler.sendEmptyMessageDelayed(1, ANIMATION_DELAY);
}
private Handler mHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
invalidate();
}
};
private OnTouchListener touchListener;
private OnTouchListener getTouchListener() {
if (touchListener == null){
touchListener = new OnTouchListener() {
int lastX = -1;
int lastY = -1;
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
lastX = -1;
lastY = -1;
return true;
case MotionEvent.ACTION_MOVE:
int currentX = (int) event.getX();
int currentY = (int) event.getY();
try {
Rect rect = mFrameRect;
final int BUFFER = 60;
if (lastX >= 0) {
boolean currentXLeft = currentX >= rect.left - BUFFER && currentX <= rect.left + BUFFER;
boolean currentXRight = currentX >= rect.right - BUFFER && currentX <= rect.right + BUFFER;
boolean lastXLeft = lastX >= rect.left - BUFFER && lastX <= rect.left + BUFFER;
boolean lastXRight = lastX >= rect.right - BUFFER && lastX <= rect.right + BUFFER;
boolean currentYTop = currentY <= rect.top + BUFFER && currentY >= rect.top - BUFFER;
boolean currentYBottom = currentY <= rect.bottom + BUFFER && currentY >= rect.bottom - BUFFER;
boolean lastYTop = lastY <= rect.top + BUFFER && lastY >= rect.top - BUFFER;
boolean lastYBottom = lastY <= rect.bottom + BUFFER && lastY >= rect.bottom - BUFFER;
boolean XLeft = currentXLeft || lastXLeft;
boolean XRight = currentXRight || lastXRight;
boolean YTop = currentYTop || lastYTop;
boolean YBottom = currentYBottom || lastYBottom;
boolean YTopBottom = (currentY <= rect.bottom && currentY >= rect.top)
|| (lastY <= rect.bottom && lastY >= rect.top);
boolean XLeftRight = (currentX <= rect.right && currentX >= rect.left)
|| (lastX <= rect.right && lastX >= rect.left);
//右上角
if (XLeft && YTop) {
updateBoxRect(2 * (lastX - currentX), (lastY - currentY), true);
//左上角
} else if (XRight && YTop) {
updateBoxRect(2 * (currentX - lastX), (lastY - currentY), true);
//右下角
} else if (XLeft && YBottom) {
updateBoxRect(2 * (lastX - currentX), (currentY - lastY), false);
//左下角
} else if (XRight && YBottom) {
updateBoxRect(2 * (currentX - lastX), (currentY - lastY), false);
//左侧
} else if (XLeft && YTopBottom) {
updateBoxRect(2 * (lastX - currentX), 0, false);
//右侧
} else if (XRight && YTopBottom) {
updateBoxRect(2 * (currentX - lastX), 0, false);
//上方
} else if (YTop && XLeftRight) {
updateBoxRect(0, (lastY - currentY), true);
//下方
} else if (YBottom && XLeftRight) {
updateBoxRect(0, (currentY - lastY), false);
}
}
} catch (NullPointerException e) {
e.printStackTrace();
}
v.invalidate();
lastX = currentX;
lastY = currentY;
return true;
case MotionEvent.ACTION_UP:
//移除之前的刷新
mHandler.removeMessages(1);
//松手时对外更新
mRect = mFrameRect;
lastX = -1;
lastY = -1;
return true;
default以上是关于Android实现扫一扫识别图像数字(使用训练的库拍照查看扫描结果)(下)的主要内容,如果未能解决你的问题,请参考以下文章