Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android使用Face++架構包實現人臉識別淺析

Android使用Face++架構包實現人臉識別淺析

編輯:關於Android編程

\

我們點開案例可以看到眾多我們熟知的軟件都是使用的這個公司所提供的SDK

\

\

\

然後我們點擊開發者中心中的開發工具與sdk下載我們所需要的sdk

\

之後再點擊我的應用中的創建應用之後他會給我們兩個密鑰

\

要保存這兩個值我們在程序中要用到它們

我今天實現的是實現面部捕捉並且識別性別和年齡來看一下效果圖

\

\

\

\

閒話不多說我們來看看實現

1.工具類Constant用來存放密鑰

 

public class Constant {
     //設置兩個之前獲取的兩個常量
     public static final String Key="2029451928755e97039b8138cfa8f8ca";
     public static final String Secret="5RNoYATB9vqpA5kerpmo6bp2Aw9fxMl0";
}

2.工具類InternetDetect

 

 

import android.graphics.Bitmap;

import com.facepp.error.FaceppParseException;
import com.facepp.http.HttpRequests;
import com.facepp.http.PostParameters;

import org.json.JSONObject;

import java.io.ByteArrayOutputStream;

public class InternetDetect {
    public interface CallBack
    {
        void success(JSONObject jsonObject);

        void error(FaceppParseException exception);

    }
    public static void dectect(final Bitmap bitmap, final CallBack callBack)
    {
        //因為這裡要向網絡發送數據是耗時操作所以要在新線程中執行
        new Thread(new Runnable() {
            @Override
            public void run() {
                /*1.設置請求
                * 2.創建一個Bitmap
                * 3.創建字符數組流
                * 4.將bitmap轉換為字符並傳入流中
                * 5.新建字符數組接受流
                * 6.創建發送數據包
                * 7.創建接受數據包
                *
                * */
                try {

                    HttpRequests httpRequests=new HttpRequests(Constant.Key,Constant.Secret,true,true);
                    //從0,0點挖取整個視圖,後兩個參數是目標大小
                    Bitmap bitmapsmall = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight());
                    //這裡api要求傳入一個字節數組數據,因此要用字節數組輸出流
                    ByteArrayOutputStream stream=new ByteArrayOutputStream();
                    /*Bitmap.compress()方法可以用於將Bitmap-->byte[]
                      既將位圖的壓縮到指定的OutputStream。如果返回true,
                      位圖可以通過傳遞一個相應的InputStream BitmapFactory.decodeStream(重建)
                      第一個參數可設置JPEG或PNG格式,第二個參數是圖片質量,第三個參數是一個流信息*/
                    bitmapsmall.compress(Bitmap.CompressFormat.JPEG, 100, stream);
                    byte[] arrays=stream.toByteArray();
                    //實現發送參數功能
                    PostParameters parameters=new PostParameters();
                    //發送數據
                    parameters.setImg(arrays);
                    //服務器返回一個JSONObject的數據
                    JSONObject jsonObject=httpRequests.detectionDetect(parameters);
                    System.out.println("jsonObject:"+jsonObject.toString());
                    if(callBack!=null)
                    {
                        //設置回調
                        callBack.success(jsonObject);
                    }
                } catch (FaceppParseException e) {

                    System.out.println("error");
                    e.printStackTrace();
                    if(callBack!=null)
                    {
                        callBack.error(e);
                    }
                }


            }
        }).start();
    }

}

3.MainActivity

 

 

import android.content.Intent;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.provider.MediaStore;
import android.support.v7.app.ActionBarActivity;
import android.text.method.ScrollingMovementMethod;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;

import com.facepp.error.FaceppParseException;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

public class MainActivity extends ActionBarActivity implements View.OnClickListener {
    private static final int PICK_CODE =1;
    private ImageView myPhoto;
    private Button getImage;
    private Button detect;
    private TextView tip;
    private View mWaitting;
    private String ImagePath=null;
    private Paint mypaint;
    private Bitmap myBitmapImage;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mypaint=new Paint();
        initViews();
        initEvent();
    }
    private void initViews()
    {
        myPhoto=(ImageView)findViewById(R.id.id_photo);
        getImage=(Button)findViewById(R.id.get_image);
        detect=(Button)findViewById(R.id.detect);
        tip=(TextView)findViewById(R.id.id_Tip);
        mWaitting=findViewById(R.id.id_waitting);
        tip.setMovementMethod(ScrollingMovementMethod.getInstance());

    }
    private void initEvent()
    {
        getImage.setOnClickListener(this);
        detect.setOnClickListener(this);
    }
    @Override
    public void onClick(View v) {

        switch (v.getId())
        {
            case R.id.get_image:
                //獲取系統選擇圖片intent
                Intent intent=new Intent(Intent.ACTION_PICK);
                intent.setType("image/*");
                //開啟選擇圖片功能響應碼為PICK_CODE
                startActivityForResult(intent,PICK_CODE);
                break;
            case R.id.detect:
                //顯示進度條圓形
                mWaitting.setVisibility(View.VISIBLE);
                //這裡需要注意判斷用戶是否沒有選擇圖片直接點擊了detect按鈕
                //否則會報一個空指針異常而造成程序崩潰
                if(ImagePath!=null&&!ImagePath.trim().equals(""))
                {
                    //如果不是直接點擊的圖片則壓縮當前選中的圖片
                    resizePhoto();
                }else
                {
                    //否則將默認的背景圖作為bitmap傳入
                    myBitmapImage=BitmapFactory.decodeResource(getResources(),R.drawable.test1);
                }
                //設置回調
                InternetDetect.dectect(myBitmapImage, new InternetDetect.CallBack() {
                    @Override
                    public void success(JSONObject jsonObject) {
                        Message message=Message.obtain();
                        message.what=MSG_SUCESS;
                        message.obj=jsonObject;
                        myhandler.sendMessage(message);
                    }
                    @Override
                    public void error(FaceppParseException exception) {
                        Message message=Message.obtain();
                        message.what=MSG_ERROR;
                        message.obj=exception;
                        myhandler.sendMessage(message);
                    }
                });
                break;
        }

    }
    //設置響應intent請求
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
        super.onActivityResult(requestCode, resultCode, intent);
        if(requestCode==PICK_CODE)
        {
            if(intent!=null)
            {
                //獲取圖片路徑
                //獲取所有圖片資源
                Uri uri=intent.getData();
                //設置指針獲得一個ContentResolver的實例
                Cursor cursor=getContentResolver().query(uri,null,null,null,null);
                cursor.moveToFirst();
                //返回索引項位置
                int index=cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
                //返回索引項路徑
                ImagePath=cursor.getString(index);
                cursor.close();
                //這個jar包要求請求的圖片大小不得超過3m所以要進行一個壓縮圖片操作
                resizePhoto();
                myPhoto.setImageBitmap(myBitmapImage);
                tip.setText("Click Detect==>");
            }
        }
    }

    private void resizePhoto() {
        //得到BitmapFactory的操作權
        BitmapFactory.Options options = new BitmapFactory.Options();
        // 如果設置為 true ,不獲取圖片,不分配內存,但會返回圖片的高寬度信息。
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(ImagePath,options);
        //計算寬高要盡可能小於1024
        double ratio=Math.max(options.outWidth*1.0d/1024f,options.outHeight*1.0d/1024f);
        //設置圖片縮放的倍數。假如設為 4 ,則寬和高都為原來的 1/4 ,則圖是原來的 1/16 。
        options.inSampleSize=(int)Math.ceil(ratio);
        //我們這裡並想讓他顯示圖片所以這裡要置為false
        options.inJustDecodeBounds=false;
        //利用Options的這些值就可以高效的得到一幅縮略圖。
        myBitmapImage=BitmapFactory.decodeFile(ImagePath,options);
    }

    private static final int MSG_SUCESS=11;
    private static final int MSG_ERROR=22;
    private Handler myhandler=new Handler()
    {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what)
            {
                case MSG_SUCESS:
                    //關閉緩沖條
                    mWaitting.setVisibility(View.GONE);
                    //拿到新線程中返回的JSONObject數據
                    JSONObject rsobj= (JSONObject) msg.obj;
                    //准備Bitmap,這裡會解析JSONObject傳回的數據
                    prepareBitmap(rsobj);
                    //讓主線程的相框刷新
                    myPhoto.setImageBitmap(myBitmapImage);
                    break;
                case MSG_ERROR:
                    mWaitting.setVisibility(View.GONE);
                    String errormsg= (String) msg.obj;
                    break;
            }
        }


    };

    private void prepareBitmap(JSONObject JS) {
        //新建一個Bitmap使用它作為Canvas操作的對象
        Bitmap bitmap=Bitmap.createBitmap(myBitmapImage.getWidth(),myBitmapImage.getHeight(),myBitmapImage.getConfig());
        //實例化一塊畫布
        Canvas canvas=new Canvas(bitmap);
        //把原圖先畫到畫布上面
        canvas.drawBitmap(myBitmapImage, 0, 0, null);
        //解析傳回的JSONObject數據
        try {
                //JSONObject中包含著眾多JSONArray,但是我們這裡需要關鍵字為face的數組中的信息
                JSONArray faces=JS.getJSONArray("face");
                //獲取得到幾個人臉
                int faceCount=faces.length();
                //讓提示文本顯示人臉數
                tip.setText("find"+faceCount);
               //下面對每一張人臉都進行單獨的信息繪制
                for(int i=0;i布局文件比較簡單因此代碼我就不上傳了

 

這裡我用紅色字體標出我在實現的過程中遇到的問題希望大家可以避免:

1.在寫按鍵響應的時候要注意判斷用戶是否沒有選擇圖片而直接點擊了detect按鈕,這樣的話避免了獲取圖片時存在空指針異常的問題

2.上傳圖片時要保證圖片小於3M因此注意圖片的壓縮

3.氣泡處理有技巧,把它當作Textview更方便

4.在繪制氣泡的時候也要注意縮放不然的話當人臉很小的時候氣泡會占據整個圖片導致用戶體驗降低

 

希望對大家有所幫助,歡迎轉載但要標明出處,謝謝!

有什麼不足的地方可以留言給我我會盡快回復並改正!

 
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved