最近在学习ai,了解到了华为HiAI这么一个app开发神器。他是华为对外开放的一套AI工具,包含SDK,IDE,用户指南等。能帮助小白用户迅速开发出ai应用,而且能用上华为手机的NPU能力,性能对比CPU提升不少。
目前已经开放出来的API包含人脸检测、人脸对比、图像超分、美学评分、码识别、分词、意图识别、语音识别等等。详细的介绍可以上华为的开发者联盟看看。http://developer.huawei.com/consumer/cn/devservice/doc/31403
这里介绍下学习的过程,拿人脸检测做一个简单的demo。
1、首先下载IDE,其实就是一个Android studio的插件,不过对于开发HiAI应用来说十分方便。下载地址:http://developer.huawei.com/consumer/cn/devservice/doc/3141902
2、安装完成之后,打开插件,效果是这样的。
可以看到API的介绍,代码示例。比较方便的是,代码可以用鼠标拖到到自己工程的java代码里,插件同时也会把需要的SDK复制到工程lib目录下,并改写gradle配置。这个功能不错。
3、开始编码,我写了一个简单的例子,选择一张相册的图片,然后调用人脸识别API,把识别出来的人脸框出来。
需要注意的是,调用人脸检测API的操作不能放在工作线程中,否则会报错。
本文源码在文末。。。
4、调试,说到调试就不得不提起IDE的一个强大功能,远程真机。这对于买不起p20的码农来说无异于雪中送炭,调试当然要选最贵的机型。效果如图,不过缺点就是比本地真机要慢一些,看在这么多免费机型的份上也就忍了。另外,使用真机需要注册一个华为开发者账号。
人脸检测的速度还是很快的,看来NPU对于ai的加成还是很不错的。
以下为demo源码
activity_main.xml
MainActivity.java
package com.hiai.face;
import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.ImageView;
import android.widget.Toast;
import com.huawei.hiai.vision.common.ConnectionCallback;
import com.huawei.hiai.vision.common.VisionBase;
import com.huawei.hiai.vision.visionkit.common.BoundingBox;
import com.huawei.hiai.vision.visionkit.face.Face;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private static final int REQUEST_STORE_PERMISSION = 1;
private static final int REQUEST_CHOOSE_PHOTO = 2;
private ImageView imageView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imageView = findViewById(R.id.img);
/** 应用VisionBase静态类进行初始化,异步拿到服务的连接*/
VisionBase.init(this, new ConnectionCallback() {
@Override
public void onServiceConnect() {
/** 这个回调方法在服务连接成功时被调用; 您可以执行探测器类的初始化,标记服务连接状态等*/
}
@Override
public void onServiceDisconnect() {
/** 当服务断开时,调用此回调方法; 您可以选择在此重新连接服务,或者处理异常*/
}
});
findViewById(R.id.btn1).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (ContextCompat.checkSelfPermission(MainActivity.this,
Manifest.permission.WRITE_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(MainActivity.this,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
REQUEST_STORE_PERMISSION);
} else {
choosePhoto();
}
}
});
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
if (requestCode == REQUEST_STORE_PERMISSION) {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
choosePhoto();
} else {
Toast.makeText(MainActivity.this, "Permission Denied", Toast.LENGTH_SHORT).show();
}
}
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
if (resultCode == RESULT_OK && requestCode == REQUEST_CHOOSE_PHOTO) {
Uri selectedImage = data.getData();
String[] filePathColumn = {MediaStore.Images.Media.DATA};
Cursor cursor = getContentResolver().query(selectedImage,
filePathColumn, null, null, null);
cursor.moveToFirst();
int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
final String imgPath = cursor.getString(columnIndex);
cursor.close();
Bitmap bitmap = BitmapFactory.decodeFile(imgPath);
imageView.setImageBitmap(bitmap);
new FaceDetectTask(new FaceDetectTask.FaceDetectListener() {
@Override
public void onDetectFinish(List faces) {
if (faces != null && !faces.isEmpty()) {
drawFace(imgPath, faces);
}
}
}).execute(bitmap);
}
super.onActivityResult(requestCode, resultCode, data);
}
private void choosePhoto() {
Intent intent = new Intent(
Intent.ACTION_PICK,
android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(intent, REQUEST_CHOOSE_PHOTO);
}
private void drawFace(String imgPath, List faces) {
Bitmap bitmap = BitmapFactory.decodeFile(imgPath).copy(Bitmap.Config.ARGB_8888, true);
Canvas canvas = new Canvas(bitmap);
Paint paint = new Paint();
paint.setColor(Color.GREEN);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(3);
for (Face face : faces) {
BoundingBox faceRect = face.getFaceRect();
canvas.drawRect(faceRect.getLeft(), faceRect.getTop(), faceRect.getLeft() + faceRect.getWidth(),
faceRect.getTop() + faceRect.getHeight(), paint);
}
imageView.setImageBitmap(bitmap);
}
@Override
protected void onDestroy() {
super.onDestroy();
/** 释放资源*/
VisionBase.destroy();
}
}
FaceDetectTask.java
package com.hiai.face;
import android.graphics.Bitmap;
import android.os.AsyncTask;
import android.util.Log;
import com.huawei.hiai.vision.face.FaceDetector;
import com.huawei.hiai.vision.visionkit.common.Frame;
import com.huawei.hiai.vision.visionkit.face.Face;
import org.json.JSONObject;
import java.util.List;
public class FaceDetectTask extends AsyncTask> {
private static final String LOG_TAG = "face_detect";
private FaceDetectListener listener;
public FaceDetectTask(FaceDetectListener listener) {
this.listener = listener;
}
@Override
protected List doInBackground(Bitmap... bitmaps) {
Log.i(LOG_TAG, "init FaceDetector");
FaceDetector faceDetector = new FaceDetector(null);
Frame frame = new Frame();
frame.setBitmap(bitmaps[0]);
long l = System.currentTimeMillis();
JSONObject jsonObject = faceDetector.detect(frame,null);
Log.i(LOG_TAG, String.format("face detect: %s, cost: %d ms", jsonObject.toString(), System.currentTimeMillis() - l));
List faces = faceDetector.convertResult(jsonObject);
return faces;
}
@Override
protected void onPostExecute(List faces) {
listener.onDetectFinish(faces);
super.onPostExecute(faces);
}
public interface FaceDetectListener {
void onDetectFinish(List faces);
}
}
最后,加上浏览相册的权限