之前做过一个项目是关于手写识别的,本篇文章主要分三步介绍:
1.自定义相机拍照显示要识别的图片
2.在图片上面进行手指的触摸操作,模拟选中要操作的区域,选择要选中的文字
3.用ocr技术识别出来选中的文字,后续还有中英文释义派生,这里先忽略了
上图
自定义相机,自动对焦,支持触摸涂抹:
具体步骤:
自动对焦功能,这里是自定义一个focusview,调用camera.autoFocus(this)方法。
/**
* 设置焦点和测光区域
*
* @param event
*/
public void focusOnTouch(MotionEvent event) {
int[] location = new int[2];
RelativeLayout relativeLayout = (RelativeLayout) getParent();
relativeLayout.getLocationOnScreen(location);
Rect focusRect = Utils.calculateTapArea(mFocusView.getWidth(),
mFocusView.getHeight(), 1f, event.getRawX(), event.getRawY(),
location[0], location[0] + relativeLayout.getWidth(), location[1],
location[1] + relativeLayout.getHeight());
Rect meteringRect = Utils.calculateTapArea(mFocusView.getWidth(),
mFocusView.getHeight(), 1.5f, event.getRawX(), event.getRawY(),
location[0], location[0] + relativeLayout.getWidth(), location[1],
location[1] + relativeLayout.getHeight());
Camera.Parameters parameters = camera.getParameters();
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
if (parameters.getMaxNumFocusAreas() > 0) {
List<Camera.Area> focusAreas = new ArrayList<Camera.Area>();
focusAreas.add(new Camera.Area(focusRect, 1000));
parameters.setFocusAreas(focusAreas);
}
if (parameters.getMaxNumMeteringAreas() > 0) {
List<Camera.Area> meteringAreas = new ArrayList<Camera.Area>();
meteringAreas.add(new Camera.Area(meteringRect, 1000));
parameters.setMeteringAreas(meteringAreas);
}
try {
camera.setParameters(parameters);
} catch (Exception e) {
}
camera.autoFocus(this);
}
/**
* 设置聚焦的图片
*
* @param focusView
*/
public void setFocusView(FocusView focusView) {
this.mFocusView = focusView;
}
/**
* 设置自动聚焦,并且聚焦的圈圈显示在屏幕中间位置
*/
public void setFocus() {
if (!mFocusView.isFocusing()) {
try {
camera.autoFocus(this);
mFocusView.setX((Utils.getWidthInPx(getContext()) - mFocusView.getWidth()) / 2);
mFocusView.setY((Utils.getHeightInPx(getContext()) - mFocusView.getHeight()) / 2);
mFocusView.beginFocus();
} catch (Exception e) {
}
}
}
这里手指的滑动涂抹效果,定义一个rubberview,创建一个trackBitmap,一会儿要在此图片上画滑动轨迹,然后通过Xfermode技术同遮罩层图片融合就能实现涂抹的效果:
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
int width = right - left;
int height = bottom - top;
// 初始化轨迹图片,稍后将在此图上绘制触摸轨迹
if (trackBitmap == null) {
trackBitmap = Bitmap.createBitmap(width - getPaddingRight() - getPaddingLeft(), height - getPaddingBottom() - getPaddingTop(), Bitmap.Config.ARGB_8888);
trackBitmapCanvas = new Canvas(trackBitmap);
// 如果已经创建了但是宽高有变化就重新创建
} else if (trackBitmap.getWidth() != width - getPaddingRight() - getPaddingLeft() || trackBitmap.getHeight() != height - getPaddingBottom() - getPaddingTop()) {
trackBitmap.recycle();
trackBitmap = Bitmap.createBitmap(width - getPaddingRight() - getPaddingLeft(), height - getPaddingBottom() - getPaddingTop(), Bitmap.Config.ARGB_8888);
trackBitmapCanvas.setBitmap(trackBitmap);
}
// 初始化遮罩图片
if (maskBitmap == null) {
maskBitmap = Bitmap.createBitmap(width - getPaddingRight() - getPaddingLeft(), height - getPaddingBottom() - getPaddingTop(), Bitmap.Config.ARGB_8888);
// new Canvas(maskBitmap).drawColor(defaultMaskColor);
new Canvas(maskBitmap).drawColor(Color.argb(100, 0, 0, 0));
// new Canvas(maskBitmap).drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);//绘制透明色
}
// 初始化dst位置
if (dstRect == null) {
dstRect = new Rect(getPaddingLeft(), getPaddingTop(), width - getPaddingRight(), height - getPaddingBottom());
} else {
dstRect.set(getPaddingLeft(), getPaddingTop(), width - getPaddingRight(), height - getPaddingBottom());
}
srcRect = computeSrcRect(new Point(maskBitmap.getWidth(), maskBitmap.getHeight()), new Point(dstRect.width(), dstRect.height()), ImageView.ScaleType.CENTER_CROP);
}
主要看看重写onlayout中的方法,初始化遮罩图片,在灰色阴影图上画滑动轨迹,纪录轨迹的多点坐标,算出画出的图片,生成轨迹图片,到这里前面两部分就都完成了,后续会讲述图片的具体生成方法以及ocr的识别。
这里计算图形滑动的区域:
public static Rect computeSrcRect(Point sourceSize, Point targetSize, ImageView.ScaleType scaleType) {
if (scaleType == ImageView.ScaleType.CENTER_INSIDE || scaleType == ImageView.ScaleType.MATRIX || scaleType == ImageView.ScaleType.FIT_XY) {
return new Rect(0, 0, sourceSize.x, sourceSize.y);
} else {
float scale;
if (Math.abs(sourceSize.x - targetSize.x) < Math.abs(sourceSize.y - targetSize.y)) {
scale = (float) sourceSize.x / targetSize.x;
if ((int) (targetSize.y * scale) > sourceSize.y) {
scale = (float) sourceSize.y / targetSize.y;
}
} else {
scale = (float) sourceSize.y / targetSize.y;
if ((int) (targetSize.x * scale) > sourceSize.x) {
scale = (float) sourceSize.x / targetSize.x;
}
}
int srcLeft;
int srcTop;
int srcWidth = (int) (targetSize.x * scale);
int srcHeight = (int) (targetSize.y * scale);
if (scaleType == ImageView.ScaleType.FIT_START) {
srcLeft = 0;
srcTop = 0;
} else if (scaleType == ImageView.ScaleType.FIT_END) {
if (sourceSize.x > sourceSize.y) {
srcLeft = sourceSize.x - srcWidth;
srcTop = 0;
} else {
srcLeft = 0;
srcTop = sourceSize.y - srcHeight;
}
} else {
if (sourceSize.x > sourceSize.y) {
srcLeft = (sourceSize.x - srcWidth) / 2;
srcTop = 0;
} else {
srcLeft = 0;
srcTop = (sourceSize.y - srcHeight) / 2;
}
}
return new Rect(srcLeft, srcTop, srcLeft + srcWidth, srcTop + srcHeight);
}
}
demo正在整理之中。