温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

Android中怎么实现图片识别功能

发布时间:2021-06-26 16:59:28 来源:亿速云 阅读:753 作者:Leah 栏目:移动开发

本篇文章为大家展示了Android中怎么实现图片识别功能,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。

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, 0, 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, CaptureRequest request,                         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, 0, 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, stateCallback, mainHandler);         } catch (CameraAccessException e) {           e.printStackTrace();         }       } else {         Toast.makeText(this, "CAMERA PERMISSION DENIED", 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>

上述内容就是Android中怎么实现图片识别功能,你们学到知识或技能了吗?如果还想学到更多技能或者丰富自己的知识储备,欢迎关注亿速云行业资讯频道。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI