Android图片识别应用详解

Android图片识别应用详解,第1张

概述最近由于参加一个小小的创意比赛,用安卓做了一个小小的图片识别应用,主要是通过拍照识别图片中的菜品,还有对象位置查找的东西。之前没有做过安卓,都是拼拼凑凑多篇博客完成的,我也把这个项目的一些过程分享一下

最近由于参加一个小小的创意比赛,用安卓做了一个小小的图片识别应用,主要是通过拍照识别图片中的菜品,还有对象位置查找的东西。之前没有做过安卓,都是拼拼凑凑多篇博客完成的,我也把这个项目的一些过程分享一下。先把功能贴一下,其实就是点击拍照,将照片保存在本地,然后识别出图中的菜品,然后用红色方框圈出来,并显示菜品种类。采用最新的Camera2的API,的确是比Camera好用。

1、界面

我采用了一个SurfaceVIEw用来显示摄像头的预览画面,重写了一个SurfaceVIEw来进行红色方框还有菜品名字的绘制。图片是一个ImageVIEw,相当于拍照按钮的功能。

 <?xml version="1.0" enCoding="utf-8"?><relativeLayout  xmlns:androID="http://schemas.androID.com/apk/res/androID"  xmlns:tools="http://schemas.androID.com/tools"  androID:layout_wIDth="match_parent"  androID:layout_height="match_parent"  tools:context="com.hd.hd.MainActivity">  <SurfaceVIEw    androID:layout_wIDth="match_parent"    androID:layout_height="match_parent"    androID:ID="@+ID/surfaceVIEw"    androID:layout_centerHorizontal="true"    androID:layout_centerVertical="true"/>  <com.hd.hd.SVDraw    androID:layout_wIDth="match_parent"    androID:layout_height="match_parent"    androID:ID="@+ID/mySurfaceVIEw"    androID:layout_centerHorizontal="true"    androID:layout_centerVertical="true"/>  <linearLayout    androID:layout_wIDth="wrap_content"    androID:layout_height="wrap_content"    androID:orIEntation="horizontal"    androID:layout_alignParentBottom="true"    >  <ImageVIEw    androID:ID="@+ID/btngal"    androID:layout_wIDth="wrap_content"    androID:layout_height="wrap_content"    androID:gravity="center_horizontal"    androID:layout_alignParentBottom="true"    androID:src="@drawable/s_8"    androID:layout_alignParentleft="true"     />  <TextVIEw    androID:ID="@+ID/textvIEw"    androID:layout_wIDth="wrap_content"    androID:layout_height="wrap_content"    androID:layout_gravity="center"    androID:textcolor="@color/white"    androID:textSize="20dp"    androID:layout_toRightOf="@ID/btngal"    androID:layout_alignParenttop="true"    />  </linearLayout></relativeLayout>

SVDraw,,继承SurfaceVIEw,用于绘制红色方框

package com.hd.hd;import androID.content.Context;import androID.graphics.Canvas;import androID.graphics.color;import androID.graphics.Paint;import androID.graphics.PixelFormat;import androID.graphics.PorterDuff;import androID.util.AttributeSet;import androID.vIEw.SurfaceHolder;import androID.vIEw.SurfaceVIEw;import java.util.List;/*定义一个画矩形框的类*/public class SVDraw extends SurfaceVIEw implements SurfaceHolder.Callback{  protected SurfaceHolder sh;  private int mWIDth;  private int mHeight;  public SVDraw(Context context,AttributeSet attrs) {    super(context,attrs);    // Todo auto-generated constructor stub     sh = getHolder();    sh.addCallback(this);    sh.setFormat(PixelFormat.transparent);    setZOrderOntop(true);  }  public voID surfaceChanged(SurfaceHolder arg0,int arg1,int w,int h) {    // Todo auto-generated method stub   }  public voID surfaceCreated(SurfaceHolder sh) {    // Todo auto-generated method stub    mWIDth = this.getWIDth();    mHeight = this.getHeight();  }  public voID surfaceDestroyed(SurfaceHolder arg0) {    // Todo auto-generated method stub   }  voID clearDraw()  {    Canvas canvas = sh.lockCanvas();    canvas.drawcolor(color.transparent,PorterDuff.Mode.CLEAR);    sh.unlockCanvasAndPost(canvas);  }  public voID drawline(List<String> keys,List<String> values)  {    Canvas canvas = sh.lockCanvas();    canvas.drawcolor(color.transparent);    Paint p = new Paint();    p.setAntiAlias(true);    p.setcolor(color.RED);    p.setstrokeWIDth(6);    p.setStyle(Paint.Style.stroke);//设置空心    p.setTextSize(160);    Paint p1 = new Paint();    p1.setcolor(color.WHITE);    p1.setTextSize(80);    for(int i = 0;i < keys.size();i++){      String v = values.get(i);      v = v.replace("[","");      v = v.replace("]","");      String[] value = v.split(",");      canvas.drawRect(mWIDth - Integer.parseInt(value[3]),Integer.parseInt(value[0]),mHeight - Integer.parseInt(value[1]),Integer.parseInt(value[2]),p);// 正方形      canvas.drawText(keys.get(i),mWIDth - Integer.parseInt(value[3]),Integer.parseInt(value[0])-5,p1);    }    sh.unlockCanvasAndPost(canvas);  }}

2、上传图片到服务器,我没有采用Json的格式,而是直接将图片文件转化为字节数组,发送给服务器。使用一个异步任务,完成后,直接在onPostExcute()方法里绘制。

package com.hd.hd;import androID.os.AsyncTask;import androID.util.Log;import androID.Widget.TextVIEw;import org.Json.JsONException;import org.Json.JsONObject;import java.io.DataOutputStream;import java.io.file;import java.io.fileinputStream;import java.io.IOException;import java.io.inputStream;import java.net.httpURLConnection;import java.net.MalformedURLException;import java.net.URL;import java.util.ArrayList;import java.util.Iterator;import java.util.List;import java.util.UUID;/** * Created by asus on 2017/8/13. */public class MyTask extends AsyncTask<String,Integer,String> {  private static String TAG = "MainActivity";  private file file; //需要发送的图片  private String result_content; //服务器返回的结果  private SVDraw surfaceVIEw;   //需要绘制的surfacevIEw  private TextVIEw tv;    //显示文字  private static final int TIME_OUT = 10 * 1000; // 超时时间  private static final String CHARSET = "utf-8"; // 设置编码  public MyTask(file f,SVDraw s,TextVIEw tv){    this.file = f;    this.surfaceVIEw = s;    this.tv = tv;  }  @OverrIDe  protected voID onPreExecute() {  }  //doInBackground方法内部执行后台任务,不可在此方法内修改UI  @OverrIDe  protected String doInBackground(String... params) {    //调用文件上传方法    result_content = uploadfile(file,"http://13.76.211.62/");    return null;  }  //onProgressUpdate方法用于更新进度信息  @OverrIDe  protected voID onProgressUpdate(Integer... progresses) {  }  //onPostExecute方法用于在执行完后台任务后更新UI,显示结果  @OverrIDe  protected voID onPostExecute(String result) {    //由于返回的是一个python的字典形式的字符串,用Json来解析    JsONObject obj = null;    List<String> keys = new ArrayList<String>();    List<String> values = new ArrayList<String>();    try {      obj = new JsONObject(result_content);      //Json对象的Key的迭代器,用来遍历Json      Iterator it = obj.keys();      while (it.hasNext()) {        String key = (String) it.next();        String value = obj.getString(key);        keys.add(key);        values.add(value);      }    } catch (JsONException e) {      e.printstacktrace();    }    //绘制图形    surfaceVIEw.clearDraw();    surfaceVIEw.drawline(keys,values);    tv.setText("搭配很赞哦");  }  //onCancelled方法用于在取消执行中的任务时更改UI  @OverrIDe  protected voID onCancelled() {  }  /**   * 上传图片文件到服务器   * @param file   * @param RequestURL   * @return   */  public static String uploadfile(file file,String RequestURL) {    String result = null;    String BOUNDARY = UUID.randomUUID().toString(); // 边界标识 随机生成    String PREFIX = "--",liNE_END = "\r\n";    String CONTENT_TYPE = "multipart/form-data"; // 内容类型    try {      //创建URL连接,指明连接地址      URL url = new URL(RequestURL);      httpURLConnection conn = (httpURLConnection) url.openConnection();      //设置http请求的属性为POST      conn.setReadTimeout(TIME_OUT);      conn.setConnectTimeout(TIME_OUT);      conn.setDoinput(true); // 允许输入流      conn.setDoOutput(true); // 允许输出流      conn.setUseCaches(false); // 不允许使用缓存      conn.setRequestMethod("POST"); // 请求方式      conn.setRequestProperty("Charset",CHARSET); // 设置编码      conn.setRequestProperty("connection","keep-alive");      conn.setRequestProperty("Content-Type",CONTENT_TYPE + ";boundary=" + BOUNDARY);      if (file != null) {        /**         * 当文件不为空,把文件包装并且上传         */        Log.i(TAG,"upload");        DataOutputStream dos = new DataOutputStream(conn.getoutputStream());        Log.e(TAG,"not null");        /**         * 这里重点注意: name里面的值为服务端需要key 只有这个key 才可以得到对应的文件         * filename是文件的名字,包含后缀名的 比如:abc.png         */        inputStream is = new fileinputStream(file);        byte[] bytes = new byte[1024];        int len;        while ((len = is.read(bytes)) != -1) {          dos.write(bytes,len);        }        is.close();        dos.flush();        Log.e(TAG,"sent");        /**         * 获取响应码 200=成功 当响应成功,获取响应的流         */        int res = conn.getResponseCode();        Log.e(TAG,"response code:" + res);        Log.e(TAG,"request success");        inputStream input = conn.getinputStream();        StringBuffer sb1 = new StringBuffer();        int ss;        while ((ss = input.read()) != -1) {          sb1.append((char) ss);        }        result = sb1.toString();        Log.e(TAG,"result : " + result);      }    } catch (MalformedURLException e) {      e.printstacktrace();    } catch (IOException e) {      e.printstacktrace();    }    return result;  }}

3、初始化界面、照相机,使得照相机能够实时预览,并实现拍照功能

 package com.hd.hd;import androID.Manifest;import androID.content.Context;import androID.content.pm.PackageManager;import androID.graphics.Bitmap;import androID.graphics.BitmapFactory;import androID.graphics.ImageFormat;import androID.harDWare.camera2.CameraAccessException;import androID.harDWare.camera2.CameraCaptureSession;import androID.harDWare.camera2.Cameracharacteristics;import androID.harDWare.camera2.CameraDevice;import androID.harDWare.camera2.CameraManager;import androID.harDWare.camera2.CaptureRequest;import androID.harDWare.camera2.CaptureResult;import androID.harDWare.camera2.TotalCaptureResult;import androID.media.Image;import androID.media.ImageReader;import androID.os.Build;import androID.os.Bundle;import androID.os.Environment;import androID.os.Handler;import androID.os.HandlerThread;import androID.support.annotation.NonNull;import androID.support.annotation.RequiresAPI;import androID.support.v4.app.ActivityCompat;import androID.support.v7.app.AppCompatActivity;import androID.util.Log;import androID.util.SparseIntArray;import androID.vIEw.Surface;import androID.vIEw.SurfaceHolder;import androID.vIEw.SurfaceVIEw;import androID.vIEw.VIEw;import androID.Widget.ImageVIEw;import androID.Widget.TextVIEw;import androID.Widget.Toast;import java.io.file;import java.io.fileNotFoundException;import java.io.fileOutputStream;import java.io.IOException;import java.nio.ByteBuffer;import java.util.Arrays;public class MainActivity extends AppCompatActivity{  private static final SparseIntArray ORIENTATIONS = new SparseIntArray();  private String TAG = "MainActivity";  ///为了使照片竖直显示  static {    ORIENTATIONS.append(Surface.ROTATION_0,90);    ORIENTATIONS.append(Surface.ROTATION_90,0);    ORIENTATIONS.append(Surface.ROTATION_180,270);    ORIENTATIONS.append(Surface.ROTATION_270,180);  }  private SurfaceVIEw mSurfaceVIEw;  private SurfaceHolder mSurfaceHolder;  private CameraManager mCameraManager;//摄像头管理器  private Handler childHandler,mainHandler;  private String mCameraID;//摄像头ID 0 为后 1 为前  private ImageReader mImageReader;  private CameraCaptureSession mCameraCaptureSession;  private CameraDevice mCameraDevice;  private SVDraw hSurfaceVIEw;  private MyTask myTask;  private CaptureRequest.Builder captureRequestBuilder;  private TextVIEw tv;  private final int DRAW_ORDER = 10;  private Handler myHandler;  private ImageVIEw imageVIEw;  private String dir = Environment.getExternalStorageDirectory().getabsolutePath() + "/Healthy_d/";  @OverrIDe  protected voID onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    setContentVIEw(R.layout.activity_main);    //此步骤非常重要,安卓不用自动帮你创建文件夹来保存拍照的照片    file dirFirstFolder = new file(dir);//方法二:通过变量文件来获取需要创建的文件夹名字    if(!dirFirstFolder.exists())    { //如果该文件夹不存在,则进行创建      dirFirstFolder.mkdirs();//创建文件夹    }    //AndroID 6后有些敏感的权限不能随意分配,必须向用户发送请求赋予    //这里请求用户赋予拍照,读写内存卡,连接网络的权限,其实只有拍照权限需要向用户请求,但是有备无患吧    if (ActivityCompat.checkSelfPermission(MainActivity.this,Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {      Log.e(TAG,ActivityCompat.checkSelfPermission(MainActivity.this,Manifest.permission.WRITE_EXTERNAL_STORAGE)+"");      ActivityCompat.requestPermissions(MainActivity.this,new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},43);    }    if (ActivityCompat.checkSelfPermission(MainActivity.this,Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {      ActivityCompat.requestPermissions(MainActivity.this,new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},44);    }    if (ActivityCompat.checkSelfPermission(MainActivity.this,Manifest.permission.INTERNET) != PackageManager.PERMISSION_GRANTED) {      ActivityCompat.requestPermissions(MainActivity.this,new String[]{Manifest.permission.INTERNET},45);    }    initVIEw();  }  /**   * 初始化视图   */  private voID initVIEw() {    HandlerThread handlerThread = new HandlerThread("Camera2");    handlerThread.start();    childHandler = new Handler(handlerThread.getLooper());    //mSurfaceVIEw    mSurfaceVIEw = (SurfaceVIEw) findVIEwByID(R.ID.surfaceVIEw);    hSurfaceVIEw = (SVDraw) findVIEwByID(R.ID.mySurfaceVIEw);    imageVIEw = (ImageVIEw) findVIEwByID(R.ID.btngal);    tv = (TextVIEw)findVIEwByID(R.ID.textvIEw);    //设置ImageVIEw监听器,点击图片,拍照    imageVIEw.setonClickListener(new VIEw.OnClickListener() {      @OverrIDe      public voID onClick(VIEw v) {        Toast.makeText(MainActivity.this,"正在识别,请稍等",Toast.LENGTH_LONG).show();        if (mCameraDevice == null) return;        // 创建拍照需要的CaptureRequest.Builder        try {          captureRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);          // 将imageReader的surface作为CaptureRequest.Builder的目标          captureRequestBuilder.addTarget(mImageReader.getSurface());          // 自动对焦          captureRequestBuilder.set(CaptureRequest.CONTRol_AF_MODE,CaptureRequest.CONTRol_AF_MODE_CONTINUOUS_PICTURE);          // 自动曝光          captureRequestBuilder.set(CaptureRequest.CONTRol_AE_MODE,CaptureRequest.CONTRol_AE_MODE_ON_auto_FLASH);          // 获取手机方向          int rotation = getwindowManager().getDefaultdisplay().getRotation();          // 根据设备方向计算设置照片的方向          captureRequestBuilder.set(CaptureRequest.JPEG_ORIENTATION,ORIENTATIONS.get(rotation));          //拍照          CaptureRequest mCaptureRequest = captureRequestBuilder.build();          mCameraCaptureSession.capture(mCaptureRequest,mSessionCaptureCallback,childHandler);        } catch (CameraAccessException e) {          e.printstacktrace();        }      }    });    mSurfaceHolder = mSurfaceVIEw.getHolder();    mSurfaceHolder.setKeepScreenOn(true);    // mSurfaceVIEw添加回调    mSurfaceHolder.addCallback(new SurfaceHolder.Callback() {      @OverrIDe      public voID surfaceCreated(SurfaceHolder holder) { //SurfaceVIEw创建        // 初始化Camera        initCamera2();      }      @OverrIDe      public voID surfaceChanged(SurfaceHolder holder,int format,int wIDth,int height) {      }      @OverrIDe      public voID surfaceDestroyed(SurfaceHolder holder) { //SurfaceVIEw销毁        // 释放Camera资源        if (null != mCameraDevice) {          mCameraDevice.close();          mCameraDevice = null;        }      }    });  }  //拍照时,可以对照片进行 *** 作,这里可以不写,因为我没对其进行 *** 作  private CameraCaptureSession.CaptureCallback mSessionCaptureCallback =      new CameraCaptureSession.CaptureCallback() {        @OverrIDe        public voID onCaptureCompleted(CameraCaptureSession session,CaptureRequest request,TotalCaptureResult result) {}        @OverrIDe        public voID onCaptureProgressed(CameraCaptureSession session,CaptureResult partialResult){}};  /**   * 初始化Camera2   */  @RequiresAPI(API = Build.VERSION_CODES.LolliPOP)  private voID initCamera2() {    HandlerThread handlerThread = new HandlerThread("Camera2");    handlerThread.start();    childHandler = new Handler(handlerThread.getLooper());    mainHandler = new Handler(getMainLooper());    mCameraID = "" + Cameracharacteristics.LENS_FACING_FRONT;//后摄像头    mImageReader = ImageReader.newInstance(mSurfaceVIEw.getWIDth(),mSurfaceVIEw.getHeight(),ImageFormat.JPEG,1);    mImageReader.setonImageAvailableListener(new ImageReader.OnImageAvailableListener() { //可以在这里处理拍照得到的临时照片 例如,写入本地      @OverrIDe      public voID onImageAvailable(ImageReader reader) {        Image image = reader.acquireNextimage();        ByteBuffer buffer = image.getPlanes()[0].getBuffer();        byte[] bytes = new byte[buffer.remaining()];        buffer.get(bytes);//由缓冲区存入字节数组        Bitmap bitmap = BitmapFactory.decodeByteArray(bytes,bytes.length);        String filename = "test";        file file = new file(dir + filename + ".jpg");        String state = Environment.getExternalStorageState();        //如果状态不是mounted,无法读写        if (!state.equals(Environment.MEDIA_MOUNTED)) {          return;        }        fileOutputStream out = null;        try {          out = new fileOutputStream(file);          bitmap.compress(Bitmap.CompressFormat.JPEG,100,out);//转化为jpeg图片          out.flush();          out.close();          image.close();//一定要记得关,否则会出现程序崩溃        } catch (fileNotFoundException e) {          e.printstacktrace();        } catch (IOException e) {          e.printstacktrace();        }        new MyTask(file,hSurfaceVIEw,tv).execute();      }    },mainHandler);    //获取摄像头管理    mCameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);    try {      if (ActivityCompat.checkSelfPermission(this,Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {        ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.CAMERA},42);      }      //打开摄像头      mCameraManager.openCamera(mCameraID,stateCallback,mainHandler);    } catch (CameraAccessException e) {      e.printstacktrace();    }  }  /**   * 当发送权限请求用户响应时,回调该函数   * @param requestCode   * @param permissions   * @param grantResults   */  @OverrIDe  public voID onRequestPermissionsResult(int requestCode,@NonNull String[] permissions,@NonNull int[] grantResults) {    if (requestCode == 42) {      Toast.makeText(this,"CAMERA PERMISSION GRANTED",Toast.LENGTH_SHORT).show();      if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {        //申请成功,可以拍照        Log.i(TAG,"apply camera success");        CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);        try {          if (ActivityCompat.checkSelfPermission(this,Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {            Toast.makeText(this,"CAMERA PERMISSION DENIED",Toast.LENGTH_SHORT).show();          }          mCameraManager.openCamera(mCameraID,mainHandler);        } catch (CameraAccessException e) {          e.printstacktrace();        }      } else {        Toast.makeText(this,Toast.LENGTH_SHORT).show();      }      return;    }    super.onRequestPermissionsResult(requestCode,permissions,grantResults);  }  /**   * 摄像头创建监听   */  private CameraDevice.StateCallback stateCallback = new CameraDevice.StateCallback() {    @OverrIDe    public voID onopened(CameraDevice camera) {//打开摄像头      mCameraDevice = camera;      //开启预览      takePrevIEw();    }    @OverrIDe    public voID ondisconnected(CameraDevice camera) {//关闭摄像头      if (null != mCameraDevice) {        mCameraDevice.close();        mCameraDevice = null;      }    }    @OverrIDe    public voID onError(CameraDevice camera,int error) {//发生错误      Toast.makeText(MainActivity.this,"摄像头开启失败",Toast.LENGTH_SHORT).show();    }  };  /**   * 开始预览   */  private voID takePrevIEw() {    try {      // 创建预览需要的CaptureRequest.Builder      final CaptureRequest.Builder prevIEwRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);      // 将SurfaceVIEw的surface作为CaptureRequest.Builder的目标      prevIEwRequestBuilder.addTarget(mSurfaceHolder.getSurface());//      prevIEwRequestBuilder.addTarget(mImageReader.getSurface());      // 创建CameraCaptureSession,该对象负责管理处理预览请求和拍照请求      mCameraDevice.createCaptureSession(Arrays.asList(mSurfaceHolder.getSurface(),mImageReader.getSurface()),new CameraCaptureSession.StateCallback() // ③      {        @OverrIDe        public voID onConfigured(CameraCaptureSession cameraCaptureSession) {          if (null == mCameraDevice) return;          // 当摄像头已经准备好时,开始显示预览          mCameraCaptureSession = cameraCaptureSession;          try {            // 自动对焦            prevIEwRequestBuilder.set(CaptureRequest.CONTRol_AF_MODE,CaptureRequest.CONTRol_AF_MODE_CONTINUOUS_PICTURE);            // 打开闪光灯            prevIEwRequestBuilder.set(CaptureRequest.CONTRol_AE_MODE,CaptureRequest.CONTRol_AE_MODE_ON_auto_FLASH);            // 显示预览            CaptureRequest prevIEwRequest = prevIEwRequestBuilder.build();            mCameraCaptureSession.setRepeatingRequest(prevIEwRequest,null,childHandler);          } catch (CameraAccessException e) {            e.printstacktrace();          }        }        @OverrIDe        public voID onConfigureFailed(CameraCaptureSession cameraCaptureSession) {          Toast.makeText(MainActivity.this,"配置失败",Toast.LENGTH_SHORT).show();        }      },childHandler);    } catch (CameraAccessException e) {      e.printstacktrace();    }  }}

4、AndroIDManifest.xml

<?xml version="1.0" enCoding="utf-8"?><manifest xmlns:androID="http://schemas.androID.com/apk/res/androID"  package="com.hd.hd">  <uses-permission androID:name="androID.permission.WRITE_EXTERNAL_STORAGE"/>  <uses-permission androID:name="androID.permission.READ_EXTERNAL_STORAGE"/>  <uses-permission androID:name="androID.permission.CAMERA"/>  <uses-feature androID:name="androID.harDWare.camera2.full" />  <uses-permission androID:name="androID.permission.INTERNET" />  <application    androID:allowBackup="true"    androID:icon="@mipmap/ic_launcher"    androID:label="@string/app_name"    androID:supportsRtl="true"    androID:theme="@style/Apptheme">    <activity androID:name=".MainActivity">      <intent-filter>        <action androID:name="androID.intent.action.MAIN" />        <category androID:name="androID.intent.category.LAUNCHER" />      </intent-filter>    </activity>  </application></manifest>

今天代码先分享到那么多,明天给大家分享一下Camera2的架构。有不懂的可以评论,一起讨论。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程小技巧。

总结

以上是内存溢出为你收集整理的Android图片识别应用详解全部内容,希望文章能够帮你解决Android图片识别应用详解所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/web/1144811.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-31
下一篇 2022-05-31

发表评论

登录后才能评论

评论列表(0条)

保存