Android名片识别
1.从开源名片识别demo NameCardRec中提取出工具代码并打包成jar包
将开源名片识别的demo NameCardRec中有关于拍照名片识别的代码进行提取,将提取出来的代码打包成为picocr.Jar文件,导入到项目中。
2.导入so包
so包支持多个平台,包括armeabi,armeabi- v7a,arm64-v8a,x86,x86_64,mips和mips64;每个目录下面包含 libnamecardrec.so包。本so包为底层的图片文字识别的引擎,armeabi,armeabi- v7a,arm64-v8a三个包下放有该so文件(),如果有些机型无法名片识别,建议armeabi,armeabi- v7a,arm64-v8a,x86,x86_64,mips和mips64包下都放 libnamecardrec.so文件。
3.新建图片识别工具类StaticRecFromCamera类
package com.fang.home.crm.utils;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import com.fang.home.crm.R;
import com.fang.home.crm.activity.AddContactActivity;
import com.fang.home.crm.net.NetApi;
import com.nostra13.universalimageloader.core.ImageLoader;
import cn.sharp.android.ncr.Constants;
import cn.sharp.android.ncr.MessageId;
import cn.sharp.android.ncr.PrefSettings;
import cn.sharp.android.ncr.ScannerAnimation;
import cn.sharp.android.ncr.image.ImageHelper;
import cn.sharp.android.ncr.ocr.OCRItems;
import cn.sharp.android.ncr.ocr.OCRManager;
import cn.sharp.android.ncr.thread.RecThread;
import cn.sharp.android.ncr.thread.StopWorkThread;
import cn.sharp.android.ncr.view.ScannerView;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.DialogInterface.OnKeyListener;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.PixelFormat;
import android.hardware.Camera;
import android.hardware.Camera.Parameters;
import android.hardware.Camera.Size;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.preference.PreferenceManager;
import android.util.Log;
import android.view.Display;
import android.view.KeyEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.view.SurfaceHolder.Callback;
import android.view.View.OnClickListener;
import android.widget.ImageButton;
import android.widget.Toast;
/**
* 拍照识别
* @author peng qi
*
*/
public class StaticRecFromCamera extends Activity implements Callback,
OnClickListener {
private final static String TAG = "StaticRecFromCamera";
private final static int DIALOG_REC_FAILURE = 0; // 失败
private final static int DIALOG_REC_SUCCESS = 1; // 成功
private final static int DIALOG_REC_PROGRESS = 2;
private final static int DIALOG_INTERRUPT_DECODE_IMAGE_OR_REC = 5;
private final static int DIALOG_STOP_REC_PROGRESS = 7;
private final static int ACTIVITY_REC_NAMECARD = 0;
public final static int REC_PROGRESS_STYLE_NORMAL = 0; //正常
public final static int REC_PROGRESS_STYLE_SCANNER = 1;//扫描
private final static SimpleDateFormat dateFormat = new SimpleDateFormat(
"yyyy-MM-dd_HH_mm_ss"); //日期格式
private Camera mCamera;
private SurfaceView surfaceView;
private ImageButton btnSnap;
private ShutterCallback shutterCallback;
private RawPictureCallback rawCallback;
private JpegPictureCallback jpegCallback;
private AutoFocusCallback autoFocusCallback;
private PreviewCallback previewCallback;
private ScannerView scannerView;
private OCRManager ocrManager;
private AtomicBoolean isCapturePic;
private AtomicBoolean isLive;
private ScannerAnimation recAnimation;
private boolean isRec;
private boolean isInterruptDialogShown;
private boolean isRecProgressDialogShown;
private boolean isStoppingRec;
private StopWorkThread stopRecThread;
private SharedPreferences preference;
private boolean autoFocus, saveRecImage;
private int recStyle;
private String imgPath;
/** 上传成功的本地图片路径 */
private String succeedPic;
private String oldSucceedImgPath = "";
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
Log.e(TAG, "get message, id:" + msg.what);
switch (msg.what) {
//识别成功
case MessageId.NAMECARD_REC_SUCCESS:
isRec = false;
closeCamera();
if (recThread != null) {
recThread = null;
} else {
Log.e(TAG,
"recSuccess msg received, but recThread is null now");
}
//ocrItems中封装识别出来的文字信息
OCRItems ocrItems = (OCRItems) msg.obj;
Log.d(TAG, "start result show activity");
if (saveRecImage && jpegData != null) {
//获取识别出来的文字信息进行相应的处理
}
break;
//识别失败
case MessageId.NAMECARD_REC_FAILURE:
isRec = false;
if (recStyle == REC_PROGRESS_STYLE_NORMAL) {
tryDismissInterruptDialog();
tryDismissRecProgressDialog();
} else if (recStyle == REC_PROGRESS_STYLE_SCANNER) {
scannerView.clearAnimation();
}
if (recThread != null) {
recThread = null;
Log.e(TAG, "rec failure");
showDialog(DIALOG_REC_FAILURE);
} else {
Log.i(TAG,
"recFailure msg received, but recThread is null now");
}
if (isLive.get()) {
rePreview();
Log.d(TAG,
"screen is still alive, camera start preview after previous rec interrupt");
btnSnap.setEnabled(true);
}
break;
//识别终止
case MessageId.REC_THREAD_STOPPED:
Log.d(TAG, "rec thread stop msg received");
stopRecThread = null;
removeDialog(DIALOG_STOP_REC_PROGRESS);
if (isLive.get()) {
rePreview();
Log.d(TAG,
"screen is still alive, camera start preview after previous rec interrupt");
btnSnap.setEnabled(true);
}
isRec = false;
isStoppingRec = false;
break;
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
Window win = getWindow();
//保持界面常亮
win.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
setContentView(R.layout.rec_camera_preview);
surfaceView = (SurfaceView) findViewById(R.id.camera_preview);
scannerView = (ScannerView) findViewById(R.id.rec_progress_scannerview);
btnSnap = (ImageButton) findViewById(R.id.btn_snap);
btnSnap.setOnClickListener(this);
SurfaceHolder surfaceHolder = surfaceView.getHolder();
surfaceHolder.addCallback(this);
surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
shutterCallback = new ShutterCallback();
jpegCallback = new JpegPictureCallback();
autoFocusCallback = new AutoFocusCallback();
previewCallback = new PreviewCallback();
isCapturePic = new AtomicBoolean();
isLive = new AtomicBoolean();
isPreviewing = false;
isRec = false;
isStoppingRec = false;
ocrManager = new OCRManager(handler);
preference = PreferenceManager.getDefaultSharedPreferences(this);
autoFocus = saveRecImage = false;
scannerView.setVisibility(View.GONE); //不显示
recAnimation = new ScannerAnimation();
}
@Override
protected void onResume() {
super.onResume();
isLive.set(true);
if (!isStoppingRec && !isRec) {
isCapturePic.set(false);
startPreview();
isRecProgressDialogShown = isInterruptDialogShown = false;
/**
* 默认设置为自动对焦,将特定配置属性值放在
* layout/pref_settings.xml
*/
autoFocus = preference.getBoolean(PrefSettings.PREF_AUTO_FOCUS,
true);
/**
*默认设置为自动对焦,将特定属性值放在
* layout/pref_settings.xml
*/
saveRecImage = preference.getBoolean(
PrefSettings.PREF_SAVE_REC_IMAGE, true);
}
String recStyleStr = preference.getString(
PrefSettings.PREF_REC_PROGRESS_STYLE, "0");
recStyle = 0;
try {
recStyle = Integer.parseInt(recStyleStr);
} catch (NumberFormatException e) {
}
if (saveRecImage
&& !Environment.getExternalStorageState().equals(
Environment.MEDIA_MOUNTED)) {
Toast.makeText(this, R.string.sdcard_no_write_perm,
Toast.LENGTH_SHORT).show();
Log.e(TAG, "image will not be outputed to sdcard");
}
Log.e(TAG, "onResume结束");
}
@Override
protected void onPause() {
super.onPause();
Log.d(TAG, "on pause");
isLive.set(false);
if (isPreviewing)
stopPreview();
closeCamera();
}
@Override
protected void onDestroy() {
Log.d(TAG, "onDestroy()");
super.onDestroy();
}
@Override
protected Dialog onCreateDialog(int id) {
switch (id) {
case DIALOG_REC_FAILURE:
return new AlertDialog.Builder(this)
.setTitle(R.string.error)
.setMessage(R.string.rec_failure)
.setPositiveButton(R.string.cancel,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog,
int which) {
if (isLive.get()) {
rePreview();
}
}
}).create();
case DIALOG_REC_PROGRESS:
ProgressDialog recProgressDialog = new ProgressDialog(
StaticRecFromCamera.this);
recProgressDialog.setTitle(R.string.waiting);
recProgressDialog.setMessage(getResources().getString(
R.string.rec_in_progress));
recProgressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
recProgressDialog.setCancelable(false);
recProgressDialog
.setOnKeyListener(new DialogInterface.OnKeyListener() {
@Override
public boolean onKey(DialogInterface dialog,
int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
Log.d(TAG, "back key pressed while recognizing");
tryDismissRecProgressDialog();
showDialog(DIALOG_INTERRUPT_DECODE_IMAGE_OR_REC);
isInterruptDialogShown = true;
return true;
}
return false;
}
});
isRecProgressDialogShown = true;
return recProgressDialog;
case DIALOG_INTERRUPT_DECODE_IMAGE_OR_REC:
return new AlertDialog.Builder(this)
.setTitle(R.string.warning)
.setMessage(R.string.interrupt_rec_confirm)
.setPositiveButton(R.string.yes,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog,
int which) {
/**
*
*移除从jpeg中解码bitmap的线程
* dismissDecodeImageProgressDialog();
*/
if (recStyle == REC_PROGRESS_STYLE_NORMAL)
tryDismissRecProgressDialog();
if (isRec) {
if (recThread != null) {
showDialog(DIALOG_STOP_REC_PROGRESS);
recThread.forceStop();
stopRecThread = new StopWorkThread(
recThread,
handler,
MessageId.REC_THREAD_STOPPED);
stopRecThread.start();
recThread = null;
isStoppingRec = true;
Log.i(TAG,
"rec process stopped by user");
} else {
Log.i(TAG, "recThread==null");
}
}
isInterruptDialogShown = false;
Log.d(TAG, "snap button enabled again");
}
})
.setNegativeButton(R.string.no,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog,
int which) {
isInterruptDialogShown = false;
if (isRec) {
switch (recStyle) {
case REC_PROGRESS_STYLE_NORMAL:
showDialog(DIALOG_REC_PROGRESS);
isRecProgressDialogShown = true;
break;
case REC_PROGRESS_STYLE_SCANNER:
scannerView
.startAnimation(recAnimation);
break;
}
}
}
}).setCancelable(false).create();
case DIALOG_STOP_REC_PROGRESS:
return ProgressDialog.show(StaticRecFromCamera.this, "",
getResources().getString(R.string.stopping_rec));
default:
return super.onCreateDialog(id);
}
}
private void tryDismissRecProgressDialog() {
if (isRecProgressDialogShown) {
removeDialog(DIALOG_REC_PROGRESS);
isRecProgressDialogShown = false;
}
}
private void tryDismissInterruptDialog() {
if (isInterruptDialogShown) {
removeDialog(DIALOG_INTERRUPT_DECODE_IMAGE_OR_REC);
isInterruptDialogShown = false;
}
}
public void surfaceCreated(SurfaceHolder holder) {
// The Surface has been created, acquire the camera and tell it
//视图已被创建,获取系统camera并通知它
Log.v(TAG, "surface created");
}
public void surfaceDestroyed(SurfaceHolder holder) {
//释放camera资源
closeCamera();
}
private int previewHeight = 0, previewWidth = 0;
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
Log.e(TAG, "surface changed");
if (holder.isCreating()) {
Log.e(TAG, "is createing surface holder");
if (!ensureCameraDevice())
return;
if (mCamera != null) {
Camera.Parameters parameters = mCamera.getParameters();
WindowManager windowManager = getWindowManager();
Display display = windowManager.getDefaultDisplay();
int screenWidth = screenWidth = display.getWidth();
int screenHeight = screenHeight = display.getHeight();
parameters.setPictureSize(screenWidth,screenHeight);
parameters.setPictureFormat(PixelFormat.JPEG);
parameters.setPreviewFormat(PixelFormat.YCbCr_420_SP);
mCamera.setPreviewCallback(previewCallback);
mCamera.setParameters(parameters);
}
try {
mCamera.setPreviewDisplay(holder);
} catch (IOException e) {
Log.e(TAG, e.getMessage());
closeCamera();
}
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case ACTIVITY_REC_NAMECARD:
Log.e(TAG, "rec-result-display activity finished, result code:"
+ requestCode);
finish();
break;
default:
super.onActivityResult(requestCode, resultCode, data);
}
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
if (isRec && recStyle == REC_PROGRESS_STYLE_SCANNER) {
scannerView.clearAnimation();
showDialog(DIALOG_INTERRUPT_DECODE_IMAGE_OR_REC);
isInterruptDialogShown = true;
}
//可以实现跳转到特定界面
finish();
return true;
}
return super.onKeyDown(keyCode, event);
}
//点击事件
public void onClick(View v) {
if (v == btnSnap) {
// capture image from camera
Log.e(TAG, "take picture button clicked");
if (mCamera != null) {
Log.e(TAG, "start auto focus");
isCapturePic.set(true);
isPreviewing = false;
v.setEnabled(false);
v.setVisibility(View.INVISIBLE);
mCamera.autoFocus(autoFocusCallback);
} else {
Log.e(TAG, "camera==null");
}
}
}
private class ShutterCallback implements Camera.ShutterCallback {
@Override
public void onShutter() {
// TODO Auto-generated method stub
}
}
private class RawPictureCallback implements Camera.PictureCallback {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
if (data == null) {
Log.i(TAG, "======raw picture callback,data==null");
} else {
Log.i(TAG, "======raw picture callback, data length:"
+ data.length);
}
}
}
//拍照
private class JpegPictureCallback implements Camera.PictureCallback {
public void onPictureTaken(byte[] data, Camera camera) {
if (!isLive.get()) {
Log.i(TAG, "JpegCallback, but activity has paused");
return;
}
Log.d(TAG, "onPictureTaken callback");
isCapturePic.set(false);
if (data == null) {
Log.e(TAG, "do not get any data from camera, data==null");
} else {
Log.v(TAG, "data length:" + data.length);
isPreviewing = false;
switch (recStyle) {
case REC_PROGRESS_STYLE_NORMAL:
showDialog(DIALOG_REC_PROGRESS);
isRecProgressDialogShown = true;
break;
case REC_PROGRESS_STYLE_SCANNER:
scannerView.setVisibility(View.VISIBLE);
Bitmap previewImage = ImageHelper.fromYUV420P(previewData,
previewWidth, previewHeight);
if (previewImage != null) {
scannerView.setBitmap(previewImage);
recAnimation.setBitmap(previewImage);
scannerView.invalidate();
scannerView.startAnimation(recAnimation);
Log.d(TAG, "animation started");
}
break;
}
//启动新线程将图片保存到本地
recThread = new RecThread(data, handler, ocrManager);
recThread.start();
isRec = true;
if (saveRecImage) {
jpegData = data;
}
}
}
}
private byte[] jpegData;
//自动聚焦
private class AutoFocusCallback implements Camera.AutoFocusCallback {
public void onAutoFocus(boolean success, Camera camera) {
if (isCapturePic.get() && isLive.get()) {
if (success) {
isCapturePic.set(false);
Log.v(TAG, "camera focus successfully");
mCamera.takePicture(shutterCallback, rawCallback,
jpegCallback);
} else {
mCamera.autoFocus(this);
Log.i(TAG, "camera cannot focus, retry");
}
}
}
}
private RecThread recThread;
/**
* 存储图片
* @author peng qi
*
*/
/** 图片本地保存 */
class upLoadImageAsyncTask extends AsyncTask<Void, Void, String> {
boolean isCancel = false;
String photo_path = "";
private byte[] jpeg;
public upLoadImageAsyncTask(byte[] jpeg) {
this.jpeg = jpeg;
}
@Override
protected void onPreExecute() {
super.onPreExecute();
isCancel = false;
}
@Override
protected String doInBackground(Void... params) {
if (jpeg != null) {
if (Environment.getExternalStorageState().equals(
Environment.MEDIA_MOUNTED)) {
Bitmap bitmap = BitmapFactory.decodeByteArray(jpeg, 0,
jpeg.length);
if (bitmap == null) {
Log.e(TAG, "cannot decode bitmap");
return "本地保存失败";
}
File file=AlbumAndComera.getTempPath();
imgPath=file.getAbsolutePath();
boolean error = false;
try {
file.createNewFile();
} catch (IOException e1) {
error = true;
}
if (!error) {
OutputStream os;
try {
os = new BufferedOutputStream(new FileOutputStream(
file));
bitmap.compress(Bitmap.CompressFormat.JPEG, 80, os);
Log.d(TAG, "bitmap compress successfully");
} catch (FileNotFoundException e) {
}
} else {
Log.e(TAG, "error when creating image file, filename:"
+ imgPath);
}
} else {
Log.e(TAG, "sdcard not ready");
}
}
return "本地图片保存成功";
}
@Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
// 处理相机上传失败
if (result.equals("本地保存失败")) {
Utils.toast(StaticRecFromCamera.this, "图片本地保存失败");
return;
}
if (!isCancel) {
UtilsLog.i(TAG, "最后显示路径:" + imgPath.trim());
String url = imgPath.trim();
oldSucceedImgPath = url;
noticeRefresh(new File(oldSucceedImgPath));
tryDismissInterruptDialog();
tryDismissRecProgressDialog();
//此处可以实现页面跳转
}
}
//通知系统媒体库刷新媒体库数据
private void noticeRefresh(File tempFile) {
Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
Uri uri = Uri.fromFile(tempFile);
intent.setData(uri);
StaticRecFromCamera.this.sendBroadcast(intent);
}
private boolean isPreviewing;
//判断相机资源状态
private boolean ensureCameraDevice() {
if (mCamera == null) {
mCamera = Camera.open();
}
return mCamera != null;
}
//开始相机预览
private void startPreview() {
if (!ensureCameraDevice()) {
Log.e(TAG, "cannot open camera device");
return;
}
if (!isPreviewing) {
mCamera.startPreview();
isPreviewing = true;
Log.e(TAG, "camera started");
} else {
Log.e(TAG, "camera has started previewing");
}
}
//名片识别失败后,重新启动相机预览
private void rePreview() {
if (mCamera != null) {
if (!isPreviewing) {
if (recStyle == REC_PROGRESS_STYLE_SCANNER) {
scannerView.setVisibility(View.GONE);
}
mCamera.startPreview();
isPreviewing = true;
btnSnap.setVisibility(View.VISIBLE);
} else {
Log.i(TAG, "camera has started previewing");
}
} else {
Log.e(TAG, "cannot repreview, mCamera==null");
}
}
//停止相机预览
private void stopPreview() {
if (mCamera != null) {
mCamera.stopPreview();
isPreviewing = false;
Log.e(TAG, "camera stopped");
}
}
//关闭相机
private void closeCamera() {
if (mCamera != null) {
mCamera.release();
isPreviewing = false;
mCamera = null;
Log.e(TAG, "camera released");
}
}
private class PreviewCallback implements Camera.PreviewCallback {
public void onPreviewFrame(byte[] data, Camera camera) {
Log.v(TAG, "preview callback");
if (mCamera != null && isPreviewing) {
previewData = data;
if (autoFocus)
mCamera.autoFocus(autoFocusCallback);
}
}
}
private byte[] previewData;
@Override
public void onLowMemory() {
super.onLowMemory();
Log.i(TAG, "on low memory");
}
}
4.配置AndroidManifest.xml
添加权限:在<manifest>标签下:
<!-- 必选 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
5.将res文件夹下相应文件复制到项目中;
名片识别jar文件和so文件下载地址
Android名片识别相关推荐
- android 名片识别 简书,名片扫描识别API
关键词:名片识别 移动端名片识别 云端名片识别 服务器端名片识别 名片识别SDK 名片识别api 一.名片识别背景 随着计算机技术的迅猛发展,电子化的名片变得越来越流行, 交换变得越来越方便.利用手机 ...
- android 名片识别 简书,nodejs实现名片识别
一.说明: 百度云提供了名片识别的api,每天可以免费调用500次:https://cloud.baidu.com/product/ocr/cards 因此,需要先上百度云注册一个开发者应用 二.名片 ...
- android 名片识别软件,手机名片识别工具Android名片全能王评测
人与人之间的关系是需要交流来建立的,所以难免的在职场上,官场上等各种场上会碰到这样那样的朋友,当然也会结实到新的朋友,当然也会收到很多名片!难道还要手动来一个一个存到手机的通讯录中吗?不.我们不要!接 ...
- android 名片识别 简书,python 腾讯API 名片识别 通用图片转文字
记录名片识别和图片转文字. 腾讯AI开放平台提供的名片OCR很强大, 而且可以免费使用, 所以本文使用的是腾讯AI开放平台. 腾讯AI开放平台API调用需要注意签名方法, 请查看之前文章传送门 名片O ...
- android 名片识别 简书,iOS 自己实现 名片识别 三 图片处理
主题: 图片处理 声明:下面这些图片仅供学习使用 0.png 1.剪切图片 根据矩形特征剪切图片 // @property (nonatomic , strong) CIImage *img; //@ ...
- android 名片识别 简书,iOS 自己实现 名片识别 四 图片转文字以及归类
本页主题: 图片转文字以及归类 先看效果展示 原图: 原图 处理后: result OCR识别效果: 量 U ::; 愧睡酣苒 `:| . - @ 唧涮区 总 代埋 í 倪礼波经理 展厅: 西部家具城 ...
- android 名片识别 简书,简书,也有了我的名片
0.1,0.09,写一篇文章,获赠简书钻数少得可怜,尽管少了点,我是在一丁点.一丁点积累到了现在,写了十四.五万的文字,总数还不足40:不过看着简书钻数值排行榜的名次,上升了不少,这也给了自己创作一点 ...
- Android名片扫描识别系统SDK
Android名片扫描识别系统SDK 一.Android名片扫描识别系统应用背景 这些年,随着移动互联的发展,APP应用成爆发式的增长,在很多APP中都涉及到对名片信息的录入,如移动CRM.移动端OA ...
- Android图像识别扫名片识别技术SDK
Android图像识别扫名片识别技术SDK 一.Android图像识别扫名片识别技术应用背景 这些年,随着移动互联的发展,APP应用成爆发式的增长,在很多APP中都涉及到对名片信息的录入,如移动CRM ...
最新文章
- 31万奖金算法赛事来了!
- GPU — Overview
- 给正在为就业苦恼的应届生
- Service Mesh 是新瓶装旧酒吗?
- CVPR2020 | 参数量减半,北大开源全新高效空域转换模块,还原图像逼真细节
- debian 安装php gd2,如何在Debian Linux中为PHP安装Ioncube
- 作者:潘永花,阿里数据经济研究中心秘书长,阿里研究院高级专家。
- java 从键盘中读取字符流 自定义异常
- 冬季打针后忌用手按摩
- 雨林木风工具箱 3.5
- 视频倒立解决方法/USB 视频设备ID:USB\VID_13D3PID_5130MI_00\621DA5E0900000
- vue下载二进制流图片
- contour 函数详解
- 2021支付宝集五福活动开启啦,集卡攻略来啦
- 企业数据中心“云化”转型解决方案
- 香农编码C程序及演示结果
- ESP8266之AP模式
- atom安装插件被墙问题
- JS常用工具函数-中文按拼音排序
- 计算机网络安全课题研究,网络安全研究的课题题目参考
热门文章
- Opencv中视频播放与进度控制
- XCO-JS 1.0.1使用教程
- 生物冰箱智能锁有哪些功能
- qt 绘制五角星图形
- SHERlocked93 的 2019 年终总结
- 酒桌上应对(from:http://www.haozai.com/bbs/dispbbs.asp?boardID=6ID=106page=1)
- 零基础转行大数据怎么学习?大数据学习路线
- Xshell 6链接Liunx链接不上:
- C语言实现计算数的整数次幂
- 数据集成-5-批数据集成