• How Old Are You?


    今天要分享的是一个测年龄的小应用,就类似是http://how-old.net官网测年龄的功能一样,我的也是这样一个功能,细节捕获当然没有how-old多啦,不过这些主要是基于一个第三方的jar包,我这里用到的是Face++的jar包,用到的是这个版本:Java SDK (Android) (Android2.3及以上)。

    一、功能展示:

    LY`%5SE7RI_JR`8XA[YPIVL

    (F36JJ)~2N}MSOHR3NRVETK

    2HVI)T{XX}5EEA}7%9%}O6I

    图一展示的是从图库选择测试图片的一个界面;图二是解析欲测试图片的一个界面;图三是一个测试结果的界面。下面说一下这个小应用的一些要点:

    • 实现图库:

    这里是采用Intent.ACTION_PICK中调用图库的用法来实现的,当然图片也要适当的压缩;

    public void onClick(View v) {
            switch (v.getId()) {
            case R.id.btnGetImage:
                Intent intent=new Intent(Intent.ACTION_PICK);
                intent.setType("image/*");
                startActivityForResult(intent,PICK_CODE);
                break;
            }
        }
    onClick()
    @Override
        protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
            if (requestCode==PICK_CODE) 
            {
                if (intent!=null) 
                {
                    Uri uri=intent.getData();
                    Cursor cursor=getContentResolver().query(uri, null, null,null, null);
                    cursor.moveToFirst();
                    int idx=cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
                    currentPhotoString=cursor.getString(idx);
                    cursor.close();
                    resizePhono();
                    ivPhoto.setImageBitmap(photoImg);
                    tvTip.setText("Click Detect==>");
                }
            }
            super.onActivityResult(requestCode, resultCode, intent);
        }
        /**
         * 压缩图片
         */
        private void resizePhono() {
            BitmapFactory.Options options=new BitmapFactory.Options();
            options.inJustDecodeBounds=true;//仅仅加载图片
            BitmapFactory.decodeFile(currentPhotoString, options);
            double radio=Math.max(options.outWidth*1.0d/1024f, options.outHeight*1.0d/1024f);
            options.inSampleSize=(int) Math.ceil(radio);
            options.inJustDecodeBounds=false;
            photoImg=BitmapFactory.decodeFile(currentPhotoString,options);
        }
    onActivityResult
    • detect工具类实现:

    对应于detect()方法,如果图片解析成功的话,就返回一个json字符串;如果失败的话,返回一个异常的数据。对应于不同的情况有不同的返回值,我定义了一个CallBackinterface;detetct()方法内部呢是要执行一个耗时的操作,所以要开启一个线程;那这个方法的主要功能也就是将图片转化为字节数组,封装到PostParameters中,通过detectionDetect方法返回JSON对象。

    package com.example.how_old;
    
    import java.io.ByteArrayOutputStream;
    
    import org.json.JSONObject;
    
    import android.graphics.Bitmap;
    import android.util.Log;
    
    import com.facepp.error.FaceppParseException;
    import com.facepp.http.HttpRequests;
    import com.facepp.http.PostParameters;
    
    public class FaceppDetect
    {
        public interface CallBack
        {
            void success(JSONObject result);
            void error(FaceppParseException exception);
        }
        /**
         * 将图片转化为字节数组,封装到PostParameters中,
         * 通过detectionDetect方法返回JSON对象
         * @param bitmap
         * @param callBack
         */
        public static void detect(final Bitmap bitmap,final CallBack callBack)
        {
            //匿名内部类参数最好声明成final类型
            Log.v("aaaaa", "aaaa");
            new Thread(new Runnable() {
                
                public void run() {
                    try {
                        Log.v("qqq", "11111");
                        HttpRequests requests=new HttpRequests(Constant.KET,Constant.SECRET,true,true);
                        Bitmap bmSmall=Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight());
                        ByteArrayOutputStream stream=new ByteArrayOutputStream();
                        bmSmall.compress(Bitmap.CompressFormat.JPEG, 100, stream);
                        
                        byte[] arrays=stream.toByteArray();
                        
                        PostParameters parameters=new PostParameters();
                        parameters.setImg(arrays);
                        JSONObject jsonObject=requests.detectionDetect(parameters);
                        Log.v("TAG", jsonObject.toString());
                        if (callBack!=null) {
                            callBack.success(jsonObject);
                        }
                    } catch (FaceppParseException e) {
                        e.printStackTrace();
                        if (callBack!=null) {
                            callBack.error(e);
                        }
                    }
                }
            }).start();
        }
        
    }
    detect
    • JSON解析,捕获属性值:

    根据JSON的格式我们来解析JSON,获取到我们想要的属性值,说到JSON解析呢,有一个很好的JSON校验网站,bejson.com可以将无序的json字符串格式化,能帮助我们很好的解析json。将获取到的属性值赋值给控件,这里需要在主线程中更新UI,当然这也是Android的一个机制,Handler机制,通过Handler来更新主线程中的UI。

    JSONArray faces;
                    faces = rs.getJSONArray("face");
                    int faceCount=faces.length();
                    tvTip.setText("find "+faceCount);
                    for (int i = 0; i < faceCount; i++) {
                        JSONObject face = faces.getJSONObject(i);
                        JSONObject posObj=face.getJSONObject("position");
                        
                        
                        float x=(float) posObj.getJSONObject("center").getDouble("x");
                        float y=(float) posObj.getJSONObject("center").getDouble("y");
                        
                        float w=(float) posObj.getDouble("width");
                        float h=(float) posObj.getDouble("height");
                        
                        x=x/100*bitmap.getWidth();
                        y=y/100*bitmap.getHeight();
                        
                        w=w/100*bitmap.getWidth();
                        h=h/100*bitmap.getHeight();
    解析JSON
    private Handler handler=new Handler()
        {
            public void handleMessage(android.os.Message msg) 
            {
                switch (msg.what) {
                case MSG_SUCCESS:
                    flWaitting.setVisibility(View.GONE);
                    JSONObject rs=(JSONObject) msg.obj;
                    prepareRsBitmap(rs);
                    ivPhoto.setImageBitmap(photoImg);
                    break;
                case MSG_ERROR:
                    flWaitting.setVisibility(View.GONE);
                    String errorMsg=(String) msg.obj;
                    if (TextUtils.isEmpty(errorMsg)) {
                        tvTip.setText("Error");
                    }
                    else {
                        tvTip.setText(errorMsg);
                    }
                    break;
                }
                super.handleMessage(msg);
            }
    Handler
    • 绘制脸部及年龄显示框:

    脸部显示框用到的主要的一个方法就是Canvas的drawLine()方法,而显示年龄的气泡,我们采用一个简单的控件Textview控件,简单设置下背景background、drawableLeft、text即可显示出气泡的赶脚,无需使用Canvas绘制。而主要的一个就是如何将Textview转化为Bitmap,我写了一个buildAgeBitmap()方法来转化。当然对应于图片的缩放,我们的气泡也是有一个缩放的,这样才合理嘛。哇咔咔!!!!

    mPaint.setColor(0xffffffff);
                        mPaint.setStrokeWidth(3);
                        //画脸部方框
                        canvas.drawLine(x-w/2, y-h/2, x-w/2, y+h/2,mPaint);
                        canvas.drawLine(x-w/2, y-h/2, x+w/2, y-h/2,mPaint);
                        canvas.drawLine(x+w/2, y-h/2, x+w/2, y+h/2,mPaint);
                        canvas.drawLine(x-w/2, y+h/2, x+w/2, y+h/2,mPaint);
                        
                        JSONObject attrObj=face.getJSONObject("attribute");
                        int ageValue=attrObj.getJSONObject("age").getInt("value");
    //                    int ageRange=attrObj.getJSONObject("age").getInt("range");
                        String genderValue=attrObj.getJSONObject("gender").getString("value");
    
                        Bitmap ageBitmap=buildAgeBitmap(ageValue,"Male".equals(genderValue));
                        //气泡缩放
                        int ageWidth=ageBitmap.getWidth();
                        int ageHeight=ageBitmap.getHeight();
                        if (bitmap.getWidth()<ivPhoto.getWidth()&&bitmap.getHeight()<ivPhoto.getHeight()) {
                            float ratio=Math.max(bitmap.getWidth()*1.0f/ivPhoto.getWidth(), bitmap.getHeight()*1.0f/ivPhoto.getHeight());
                            ageBitmap=Bitmap.createScaledBitmap(ageBitmap, (int)(ageWidth*ratio),(int)(ageHeight*ratio), false);
                        }
                        canvas.drawBitmap(ageBitmap, x-ageBitmap.getWidth()/2,y-h/2-ageBitmap.getHeight(), null);
                        photoImg=bitmap;
    绘制显示框
    private Bitmap buildAgeBitmap(int ageValue, boolean isMale) {
                TextView tvQp=(TextView) flWaitting.findViewById(R.id.tvAgeGender);
                tvQp.setText(ageValue+"");
                if (isMale) {
                    tvQp.setCompoundDrawablesWithIntrinsicBounds(getResources().getDrawable(R.drawable.male), null, null, null);
                }
                else {
                    tvQp.setCompoundDrawablesWithIntrinsicBounds(getResources().getDrawable(R.drawable.female), null, null, null);
                }
                tvQp.setDrawingCacheEnabled(true);
                Bitmap bitmap=Bitmap.createBitmap(tvQp.getDrawingCache());
                tvQp.destroyDrawingCache();
                return bitmap;
            };
    buildAgeBitmap

    其中,JSON解析和绘制显示框等操作都是放置在prepareRsBitmap()方法中的。基本上就这么多啦。啊你哦!!!!o 0我应该大家看一下JSON的格式:

    {
        "face": [
            {
                "position": {
                    "mouth_right": {
                        "y": 28.476451,
                        "x": 54.946591
                    },
                    "mouth_left": {
                        "y": 30.445734,
                        "x": 44.776818
                    },
                    "center": {
                        "y": 25.255973,
                        "x": 47.272727
                    },
                    "height": 16.723549,
                    "width": 22.272727,
                    "nose": {
                        "y": 25.643515,
                        "x": 45.270455
                    },
                    "eye_left": {
                        "y": 23.175427,
                        "x": 41.6
                    },
                    "eye_right": {
                        "y": 21.064334,
                        "x": 51.402045
                    }
                },
                "attribute": {
                    "race": {
                        "value": "Asian",
                        "confidence": 99.53840000000001
                    },
                    "gender": {
                        "value": "Female",
                        "confidence": 99.9903
                    },
                    "smiling": {
                        "value": 88.3311
                    },
                    "age": {
                        "value": 35,
                        "range": 7
                    }
                },
                "tag": "",
                "face_id": "ac2a5139c9293e8b18d2cc26fe6b3d54"
            }
        ],
        "session_id": "09739b73148e45af98a1dd87671973d4",
        "img_height": 586,
        "img_width": 440,
        "img_id": "ff62269ed6c0fff160d8f3a77c2eb4e3",
        "url": null,
        "response_code": 200
    }
    JSON
  • 相关阅读:
    图->存储结构->十字链表
    图->存储结构->邻接表
    P2278-[HNOI2003]操作系统
    P1801-黑匣子_NOI导刊2010提高(06)
    P1197-[JSOI2008]星球大战
    P2024- [NOI2001]食物链
    P1111-修复公路
    ACM模板——二分图匹配
    P2055-[ZJOI2009]假期的宿舍
    ACM模板——强连通分量
  • 原文地址:https://www.cnblogs.com/wucaiyun1/p/4935838.html
Copyright © 2020-2023  润新知