Android开发之头像智能裁剪

标签: 头像裁剪 人脸抠图 人脸识别 圆形头像
34人阅读 评论(0) 收藏 举报
分类:

本篇主要是记录头像智能裁剪,如果图片含有人头像就智能提取头像,没有就按照默认scaleType裁剪。

圆角头像采用 circleimageview 开源库

compile ‘de.hdodenhof:circleimageview:2.1.0’

网络图片加载这里采用 Glide

compile ‘com.github.bumptech.glide:glide:3.7.0’

人脸识别抠图辅助类 FaceHelper


import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.PointF;
import android.media.FaceDetector;
import android.util.Log;

import de.hdodenhof.circleimageview.CircleImageView;

public final class FaceHelper {

    public static void clipFacePhotoBitmap(final Activity activity, final CircleImageView circleImageView, final Bitmap bitmap){

        new Thread(new Runnable() {
            @Override
            public void run() {
                Log.e("time","face clip time start:"+System.currentTimeMillis()+"****");
                Bitmap faceBitmap = genFaceBitmap(bitmap);
                if(faceBitmap==null){
                    faceBitmap = bitmap;
                }
                final Bitmap finalFaceBitmap = faceBitmap;
                activity.runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        circleImageView.setImageBitmap(finalFaceBitmap);
                        Log.e("time","face clip time end: "+System.currentTimeMillis()+"****");
                    }
                });
            }
        }).start();
    }
    public static Bitmap genFaceBitmap(Bitmap sourceBitmap) {

        if (!checkBitmap(sourceBitmap)) {
            return null;
        }

        Bitmap cacheBitmap = sourceBitmap.copy(Bitmap.Config.RGB_565, false);

        sourceBitmap = null;

        int cacheWidth = cacheBitmap.getWidth();
        int cacheHeight = cacheBitmap.getHeight();
        if (cacheWidth % 2 != 0) {
            if (0 == cacheWidth - 1) {
                return null;
            }
            final Bitmap localCacheBitmap = Bitmap.createBitmap(cacheBitmap, 0,
                    0, cacheWidth - 1, cacheHeight);
            cacheBitmap.recycle();
            cacheBitmap = localCacheBitmap;
            --cacheWidth;
        }

        final FaceDetector.Face[] faces = new FaceDetector.Face[1];
        final int facefound = new FaceDetector(cacheWidth, cacheHeight, 1)
                .findFaces(cacheBitmap, faces);
        if (0 == facefound) {
            return null;
        }

        final PointF p = new PointF();
        faces[0].getMidPoint(p);

        final int faceX = (int) p.x;
        final int faceY = (int) p.y;

        int startX, startY, width, height;
        if (faceX <= cacheWidth - faceX) {
            startX = 0;
            width = faceX * 2;
        } else {
            startX = faceX - (cacheWidth - faceX);
            width = (cacheWidth - faceX) * 2;
        }
        if (faceY <= cacheHeight - faceY) {
            startY = 0;
            height = faceY * 2;
        } else {
            startY = faceY - (cacheHeight - faceY);
            height = (cacheHeight - faceY) * 2;
        }

        final Bitmap result = Bitmap.createBitmap(cacheBitmap, startX, startY,
                width, height);
        cacheBitmap.recycle();
        return result;
    }

    private static boolean checkBitmap(final Bitmap bitmap) {
        if (null == bitmap || bitmap.isRecycled()) {
            return false;
        }
        if (0 == bitmap.getWidth() || 0 == bitmap.getHeight()) {
            return false;
        }
        return true;
    }
}

测试demo xml文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="200dp"
        android:background="#1a87be"
        >

        <de.hdodenhof.circleimageview.CircleImageView
            android:id="@+id/circleImageView"
            android:layout_width="80dp"
            android:layout_centerInParent="true"
            android:layout_height="80dp"
            android:src="@drawable/icon_cateye_default_photo"
            app:civ_border_color="#55C4FC"
            app:civ_border_width="2dp" />
    </RelativeLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:orientation="horizontal"
        android:layout_height="200dp">

        <ImageView
            android:id="@+id/normal"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_margin="20dp"
            android:layout_weight="1"
            android:src="@drawable/url_normal" />

        <ImageView
            android:id="@+id/photo"
            android:layout_width="0dp"
            android:src="@drawable/url_photo"
            android:layout_height="match_parent"
            android:layout_margin="20dp"
            android:layout_weight="1"/>
    </LinearLayout>

</LinearLayout>

测试代码 MainActivity.class


import android.graphics.Bitmap;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;

import com.bumptech.glide.Glide;
import com.bumptech.glide.request.animation.GlideAnimation;
import com.bumptech.glide.request.target.SimpleTarget;

import de.hdodenhof.circleimageview.CircleImageView;

public class MainActivity extends AppCompatActivity {

    public static final String URL_NORMAL = "http://tgi12.jia.com/119/917/19917355.jpg";

    public static final String URL_PHOTO = "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1524534441&di=c4bf6ab9e77c9ceda8283f43d188f04e&imgtype=jpg&er=1&src=http%3A%2F%2Fimg.pconline.com.cn%2Fimages%2Fupload%2Fupc%2Ftx%2Fitbbs%2F1603%2F03%2Fc40%2F18838489_1457005978542_mthumb.jpg";

    private CircleImageView circleImageView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        circleImageView = (CircleImageView)findViewById(R.id.circleImageView);

        findViewById(R.id.normal).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Glide.with(getApplicationContext()).load(URL_NORMAL).asBitmap().into(new SimpleTarget<Bitmap>() {
                    @Override
                    public void onResourceReady(Bitmap resource, GlideAnimation<? super Bitmap> glideAnimation) {
                        FaceHelper.clipFacePhotoBitmap(MainActivity.this,circleImageView,resource);
                    }
                });
            }
        });

        findViewById(R.id.photo).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Glide.with(getApplicationContext()).load(URL_PHOTO).asBitmap().into(new SimpleTarget<Bitmap>() {
                    @Override
                    public void onResourceReady(Bitmap resource, GlideAnimation<? super Bitmap> glideAnimation) {
                        FaceHelper.clipFacePhotoBitmap(MainActivity.this,circleImageView,resource);
                    }
                });
            }
        });
    }
}

亲门,这次真没有demo了,以上为全部代码了!

查看评论

WindowsCE下Unicode和Ansi字符间互相转换的例子

纵所周知,WindowsCE下编程99%的问题都和Unicode有关.比如文件编辑,一般都保存为Ansi格式;无线通讯中控制Modem需要发送的AT指令,必须是Ansi格式;网络通讯中,PC端一般都是...
  • shiqizheng
  • shiqizheng
  • 2003-02-19 09:12:00
  • 760

【Android开发经验】设置用户头像并裁剪,仅仅是这么简单?

转载请注明出处:http://blog.csdn.net/zhaokaiqiang1992    在做APP的时候,如果有用户系统功能,那么一般都逃不了这个需求,就是给用户设置头像,而设置头像,又包括...
  • bz419927089
  • bz419927089
  • 2015-01-22 17:07:59
  • 11638

Android 实现最新版QQ图像裁剪功能

实现最新版QQ圆形图像裁剪功能,功能待修复。
  • u014061684
  • u014061684
  • 2016-01-15 11:43:30
  • 20816

Android第三方开源图片裁剪截取:cropper

 Android第三方开源图片裁剪截取:cropper 很多app都需要裁剪截取图片作为头像、logo之类,而cropper是github上的一个针对Android平台的、第三方开源图片裁剪截...
  • zhangphil
  • zhangphil
  • 2016-06-12 10:35:21
  • 5244

Android圆形头像设置(实现相机、相册选择并裁剪)兼容6.0/7.0

android头像设置,拍照、相册选择并编辑、兼容7.0 6.0
  • z740852294
  • z740852294
  • 2017-08-22 10:34:33
  • 1180

Android头像上传时裁剪图片过大问题,裁剪大图片导致

原先在完成头像上传功能的时候复制网上写好的代码,虽然也仔细研究过实现的过程但是这次项目中却遇到了一个很不解的问题,使用乐视手机实现图片裁剪的那一步骤中由于图片太大手机性能不够导致图片无法裁剪报出错误 ...
  • xiaoqiang_0719
  • xiaoqiang_0719
  • 2016-10-27 14:15:42
  • 2142

Android高仿微信头像裁剪

最近公司的APP很多用户反应无法上传头像,于是打算修改原来头像裁剪的代码。参考微信、QQ、唱吧头像裁剪的操作,决定就仿微信头像裁剪来上传用户头像,在Android大神鸿洋的一篇高仿微信头像的博客(博客...
  • xiechengfa
  • xiechengfa
  • 2015-05-13 23:42:21
  • 13107

android中华为、小米手机设置头像裁剪失败问题

近期写代码碰到华为、小米手机拍照、从相册获取图片设置头像失败的问题,在网上浏览一些相关博客后,终于解决了此问题,特在此记录,分享给大家,也算是自己的一个笔记了! 问题原因:裁剪时 return-...
  • flying_FFL
  • flying_FFL
  • 2017-01-22 19:45:39
  • 1500

Android7.0 头像 拍照、照片裁剪

作者:夏至,欢迎转载,但请保留这段申明,谢谢。 http://blog.csdn.net/u011418943/article/details/77712662 首先,好规则,看看自己的实现效果...
  • Swollow_
  • Swollow_
  • 2017-09-04 22:20:06
  • 528

Android获取图片、裁剪、压缩、上传头像

Android获取图片、裁剪、压缩、上传头像上传方式为post,上传图片格式为multipart/form-data自己在做毕设找了很多方法,但是没有找到一个符合我需求的,最后自己汇总了一下大家的方法...
  • qq_28147169
  • qq_28147169
  • 2017-03-17 19:42:57
  • 965
    个人资料
    专栏达人
    等级:
    访问量: 24万+
    积分: 3438
    排名: 1万+
    博客专栏
    最新评论