虹软人脸识别

运行虹软应用套件开源代码,发现报错。查看错误信息,说的是缺少类(详细说明看下方)
咨询了下虹软小助手,表示这两个类确实是需要自己实现的
晚上加班把这个做出来了,不得不说虹软开放了应用套件,确实省去了很多研发时间,当天晚上就跑通了
下面把类实现分享在这里,给有需要的人做个参考。。


导航:
? 获取ArcFaceGo包
? 运行ArcFaceGo工程
? 安装及使用


一、获取ArcFaceGo包
进入虹软ArcFaceGo官方页面https://ai.arcsoft.com.cn/product/arcfacego.html,按照步骤获取ArcFaceGo_Source_3.1.1.zip,其中包含ArcFaceGo源码及相关文档信息。


二、运行ArcFaceGo工程
2.1 获取工程
解压ArcFaceGo_Source_3.1.1.zip,解压后进入sourcecode目录,解压其中的ArcFaceGo.zip获取工程


2.2 编译工程
2.2.1 查看编译报错
使用Android Studio打开工程,并执行Build,会提示报错,有两个类里有类不存在,需要自己实现:



2.2.2 实现Camera1Engine类


package com.arcsoft.arcfacesingle.libutil;

import android.graphics.ImageFormat;
import android.graphics.SurfaceTexture;
import android.hardware.Camera;
import android.util.Pair;

import com.arcsoft.asg.libcommon.contract.ICameraEngine;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;

/**
* ICameraEngine的实现
*/
public class Camera1Engine extends ICameraEngine {

private static final int COUNT_CAMERA_ONE = 1;
private static final int COUNT_CAMERA_TWO = 2;
private Camera camera;
private boolean usePreAlloc;

@Override
public void setUsePreAlloc(boolean usePreAlloc) {
this.usePreAlloc = usePreAlloc;
}

@Override
public void onPreviewFrame(byte[] data, Camera camera) {
super.onPreviewFrame(data, camera);
if (usePreAlloc) {
camera.addCallbackBuffer(data);
}
}

@Override
public void startCamera(SurfaceTexture surfaceTexture, int cameraId, int previewRotation, int previewWidth,
int previewHeight, int bufferCount, int bufferSize) throws IOException {
camera = Camera.open(cameraId);
camera.setDisplayOrientation(previewRotation);
Camera.Parameters parameters = camera.getParameters();
parameters.setPreviewFormat(ImageFormat.NV21);
parameters.setPreviewSize(previewWidth, previewHeight);
List supportedFocusModes = parameters.getSupportedFocusModes();
if (supportedFocusModes != null && supportedFocusModes.size() > 0) {
if (supportedFocusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) {
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
} else if (supportedFocusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO)) {
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
} else if (supportedFocusModes.contains(Camera.Parameters.FOCUS_MODE_AUTO)) {
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
}
}
camera.setParameters(parameters);
camera.setPreviewTexture(surfaceTexture);
if (usePreAlloc) {
for (int i = 0; i < bufferCount; i++) {
camera.addCallbackBuffer(new byte[bufferSize]);
}
camera.setPreviewCallbackWithBuffer(this);
} else {
camera.setPreviewCallback(this);
}
camera.startPreview();
}

@Override
public void setPreviewTexture(SurfaceTexture surfaceTexture) {
try {
if (camera != null) {
camera.setPreviewTexture(surfaceTexture);
}
} catch (Exception e) {
e.printStackTrace();
}
}

@Override
public void releaseCamera() {
if (camera != null) {
if (usePreAlloc) {
camera.setPreviewCallbackWithBuffer(null);
} else {
camera.setPreviewCallback(null);
}
camera.stopPreview();
camera.release();
camera = null;
}
}

@Override
public List getCameraPositionList() {
List cameraPosList = new ArrayList<>();
int cameraPosBack = Camera.CameraInfo.CAMERA_FACING_BACK;
int cameraPosFront = Camera.CameraInfo.CAMERA_FACING_FRONT;
int cameraCount = Camera.getNumberOfCameras();
if (cameraCount == COUNT_CAMERA_ONE) {
cameraPosList.add(cameraPosBack);
} else if (cameraCount >= COUNT_CAMERA_TWO) {
cameraPosList.add(cameraPosBack);
cameraPosList.add(cameraPosFront);
}
return cameraPosList;
}

@Override
public List> getCameraPreviewSizeList() {
List commonSizeList = new ArrayList<>();
int cameraPosBack = Camera.CameraInfo.CAMERA_FACING_BACK;
int cameraPosFront = Camera.CameraInfo.CAMERA_FACING_FRONT;
int cameraCount = Camera.getNumberOfCameras();
if (cameraCount == COUNT_CAMERA_ONE) {
try {
Camera backCamera = Camera.open(cameraPosBack);
commonSizeList = backCamera.getParameters().getSupportedPreviewSizes();
backCamera.release();
} catch (Exception e) {
e.printStackTrace();
}
} else if (cameraCount >= COUNT_CAMERA_TWO) {
List backSizeList;
try {
Camera.CameraInfo cameraInfo2 = new Camera.CameraInfo();
Camera.getCameraInfo(cameraPosBack, cameraInfo2);
Camera backCamera = Camera.open(cameraPosBack);
backSizeList = backCamera.getParameters().getSupportedPreviewSizes();
backCamera.release();
} catch (Exception e) {
backSizeList = new ArrayList<>();
}
List frontSizeList;
try {
Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
Camera.getCameraInfo(cameraPosFront, cameraInfo);
Camera frontCamera = Camera.open(cameraPosFront);
frontSizeList = frontCamera.getParameters().getSupportedPreviewSizes();
frontCamera.release();
} catch (Exception e) {
frontSizeList = new ArrayList<>();
}
if (frontSizeList.size() > 0 && backSizeList.size() > 0) {
for (Camera.Size rgbPreviewSize : frontSizeList) {
for (Camera.Size irPreviewSize : backSizeList) {
if (irPreviewSize.width == rgbPreviewSize.width && irPreviewSize.height == rgbPreviewSize.height) {
commonSizeList.add(irPreviewSize);
}
}
}
} else if (frontSizeList.size() > 0) {
commonSizeList = frontSizeList;
} else if (backSizeList.size() > 0) {
commonSizeList = backSizeList;
}
}
Collections.sort(commonSizeList, ((size, t1) -> {
int leftWidth = size.width;
int rightWidth = t1.width;
return leftWidth - rightWidth;
}));
List sizeList = new ArrayList<>(new LinkedHashSet<>(commonSizeList));
List> cameraPairList = new ArrayList<>();
if (sizeList.size() > 0) {
for (Camera.Size size : sizeList) {
int sizeWidth = size.width;
int sizeHeight = size.height;
Pair sizePair = new Pair<>(sizeWidth, sizeHeight);
cameraPairList.add(sizePair);
}
}
return cameraPairList;
}
}


2.2.3 实现ImageUtils类


package com.arcsoft.arcfacesingle.libutil;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.ImageFormat;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.graphics.YuvImage;
import android.graphics.drawable.Drawable;
import android.text.TextUtils;
import android.util.Base64;
import android.util.Pair;

import androidx.annotation.DrawableRes;
import androidx.core.content.ContextCompat;

import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

/**
* 图片管理工具类
*/
public final class ImageUtils {
private static final int FACE_DETECT_IMAGE_WIDTH_LIMIT = 4;
private static final int FACE_DETECT_IMAGE_HEIGHT_LIMIT = 2;

private ImageUtils() {
throw new UnsupportedOperationException("无法初始化!");
}

/**
* 判断bitmap是否为空
*
* @param src Bitmap对象
* @return bitmap是否为空
*/
private static boolean isEmptyBitmap(final Bitmap src) {
return src == null || src.getWidth() == 0 || src.getHeight() == 0;
}


/**
* 根据压缩格式将Bitmap转换为压缩后的图像数据
*
* @param bitmap Bitmap对象
* @param format 压缩格式
* @return 压缩后的图像数据
*/
public static byte[] bitmap2Bytes(final Bitmap bitmap, final Bitmap.CompressFormat format) {
if (bitmap == null) {
return null;
}
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bitmap.compress(format, 100, baos);
return baos.toByteArray();
}

/**
* 将图片文件转换为Bitmap
*
* @param file 图片文件
* @return Bitmap对象
*/
public static Bitmap getBitmap(final File file) {
if (file == null) {
return null;
}
return BitmapFactory.decodeFile(file.getAbsolutePath());
}

/**
* 根据最大宽高,将文件转换为Bitmap
*
* @param filePath 文件路径
* @param maxWidth 最大宽度
* @param maxHeight 最大高度
* @return Bitmap对象
*/
public static Bitmap getBitmap(final String filePath, int maxWidth, int maxHeight) {
if (isSpace(filePath)) {
return null;
}
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(filePath, options);
options.inSampleSize = calculateInSampleSize4(options, maxWidth, maxHeight);
options.inJustDecodeBounds = false;
return BitmapFactory.decodeFile(filePath, options);
}

/**
* 根据最大宽高,将压缩图像数据转换为Bitmap
*
* @param imageBytes 压缩的图像数据,如jpeg/png等
* @param maxWidth 最大宽度
* @param maxHeight 最大高度
* @return Bitmap对象
*/
public static Bitmap getBitmap(final byte[] imageBytes, int maxWidth, int maxHeight) {
if (imageBytes == null || imageBytes.length == 0) {
return null;
}
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length, options);
options.inSampleSize = calculateInSampleSize4(options, maxWidth, maxHeight);
options.inJustDecodeBounds = false;
return BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length, options);
}

/**
* 根据最大宽高,将图片文件转换为Bitmap
*
* @param filePath 图片文件路径
* @param maxWidth 最大宽度
* @param maxHeight 最大高度
* @return Bitmap对象
*/
public static Bitmap decodeFileWithThreshold(final String filePath, int maxWidth, int maxHeight) {
Bitmap tempBitmap = getBitmap(filePath, maxWidth, maxHeight);
if (tempBitmap != null) {
if (tempBitmap.getWidth() > maxWidth || tempBitmap.getHeight() > maxHeight) {
Bitmap scaleBitmap = resizeImage(tempBitmap, maxWidth, maxHeight);
if (!tempBitmap.isRecycled()) {
tempBitmap.recycle();
}
return scaleBitmap;
}
return tempBitmap;
}
return null;
}

/**
* 根据最大宽高,将图片数据转换为Bitmap
*
* @param imgBytes 图片数据,可以是JPEG/PNG等格式的压缩数据
* @param maxWidth 最大宽度
* @param maxHeight 最大高度
* @return Bitmap对象
*/
public static Bitmap decodeFileWithThreshold(byte[] imgBytes, int maxWidth, int maxHeight) {
Bitmap tempBitmap = getBitmap(imgBytes, maxWidth, maxHeight);
if (tempBitmap != null) {
if (tempBitmap.getWidth() > maxWidth || tempBitmap.getHeight() > maxHeight) {
Bitmap scaleBitmap = resizeImage(tempBitmap, maxWidth, maxHeight);
if (!tempBitmap.isRecycled()) {
tempBitmap.recycle();
}
return scaleBitmap;
}
return tempBitmap;
}
return null;
}

/**
* 根据资源ID获取Bitmap
*
* @param resId 资源ID
* @return Bitmap对象
*/
public static Bitmap getBitmap(@DrawableRes final int resId, Context context) {
Drawable drawable = ContextCompat.getDrawable(context, resId);
if (drawable == null) {
return null;
}
Canvas canvas = new Canvas();
Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
canvas.setBitmap(bitmap);
drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
drawable.draw(canvas);
return bitmap;
}

public static int calculateInSampleSize4(BitmapFactory.Options options, int reqWidth, int reqHeight) {
int sampleSize = 1;
int picWidth = options.outWidth;
int picHeight = options.outHeight;
if (picWidth > reqWidth || picHeight > reqHeight) {
final int widthRatio = picWidth / reqWidth;
final int heightRatio = picHeight / reqHeight;
sampleSize = Math.max(heightRatio, widthRatio);
}
return sampleSize;
}


/**
* 保存图片
*
* @param src Bitmap对象
* @param file 要保存的file路径
* @param format 图片格式
* @param recycle 是否回收bitmap
* @return 是否保存成功
*/
public static boolean save(final Bitmap src, final File file, final Bitmap.CompressFormat format, final int quality, final boolean recycle) {
if (isEmptyBitmap(src)) {
return false;
}
if (!createFileByDeleteOldFile(file)) {
if (recycle && !src.isRecycled()) {
src.recycle();
}
return false;
}
OutputStream os;
FileOutputStream fileOutputStream = null;
boolean ret = false;
try {
fileOutputStream = new FileOutputStream(file);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (fileOutputStream != null) {
os = new BufferedOutputStream(fileOutputStream);
ret = src.compress(format, quality, os);
try {
os.flush();
os.close();
} catch (Exception e) {
e.printStackTrace();
}
try {
fileOutputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
if (recycle && !src.isRecycled()) {
src.recycle();
}
}
}
return ret;
}

public static boolean save(final Bitmap src, final File file, final Bitmap.CompressFormat format) {
return save(src, file, format, 100, false);
}

public static boolean save(final Bitmap src, final File file, final int quality, final Bitmap.CompressFormat format) {
return save(src, file, format, quality, true);
}

public static boolean save(final Bitmap src, final String filePath, final Bitmap.CompressFormat format, final boolean recycle) {
return save(src, getFileByPath(filePath), format, 100, recycle);
}

public static boolean save(final Bitmap src, final String filePath, final Bitmap.CompressFormat format) {
return save(src, getFileByPath(filePath), format, 100, false);
}

/**
* 对文件进行base64编码,获取编码后的字符串信息
*
* @param path 文件路径
* @return base64编码后的文件内容
*/
public static String image2Base64(String path) {
if (TextUtils.isEmpty(path)) {
return null;
}
InputStream is = null;
byte[] data;
String result = null;
try {
is = new FileInputStream(path);
data = new byte[is.available()];
int ret = is.read(data);
result = Base64.encodeToString(data, Base64.DEFAULT);
data = null;
} catch (IOException e) {
e.printStackTrace();
} finally {
if (null != is) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}

}
return result;
}

/**
* 对Bitmap进行压缩,以30的质量压缩为jpeg格式数据,再进行base64编码,获取编码后的字符串信息
*
* @param bitmap Bitmap对象
* @return base64编码后的文件内容
*/
public static String bitmapToBase64(Bitmap bitmap) {
// 要返回的字符串
String reslut = null;
ByteArrayOutputStream baos = null;
try {
if (bitmap != null) {
baos = new ByteArrayOutputStream();
//压缩只对保存有效果bitmap还是原来的大小
bitmap.compress(Bitmap.CompressFormat.JPEG, 30, baos);
baos.flush();
baos.close();
// 转换为字节数组
byte[] byteArray = baos.toByteArray();
// 转换为字符串
reslut = Base64.encodeToString(byteArray, Base64.DEFAULT);
} else {
return null;
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (baos != null) {
baos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return reslut;
}


/**
* 将base64编码的图像数据解码为Bitmap对象
*
* @param base64String base64编码的图像数据
* @return Bitmap对象
*/
public static Bitmap base64ToBitmap(String base64String) {
Bitmap bitmap = null;
byte[] decode = null;
try {
decode = Base64.decode(base64String, Base64.DEFAULT);
} catch (Exception e) {
}
if (decode != null && decode.length != 0) {
try {
bitmap = BitmapFactory.decodeByteArray(decode, 0, decode.length);
} catch (Exception e) {
}
}

return bitmap;
}


/**
* 将nv21数据转Bitmap
*
* @param nv21 NV21数据
* @param width NV21图像宽度
* @param height NV21图像高度
* @return 转换后的bitmap对象
*/
public static Bitmap nv21ToBitmap(byte[] nv21, int width, int height) {
Bitmap bitmap = null;
try {
YuvImage image = new YuvImage(nv21, ImageFormat.NV21, width, height, null);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
image.compressToJpeg(new Rect(0, 0, width, height), 100, stream);
bitmap = BitmapFactory.decodeByteArray(stream.toByteArray(), 0, stream.size());
stream.close();
} catch (IOException e) {
e.printStackTrace();
}
return bitmap;
}

/**
* 根据旋转角度、是否镜像处理Bitmap
*
* @param b bitmap对象
* @param rotateDegree 旋转角度
* @param mirror 是否镜像
* @return 处理后的Bitmap对象
*/
public static Bitmap getRotateBitmap(Bitmap b, float rotateDegree, boolean mirror) {
Matrix matrix = new Matrix();
if (mirror) {
if (rotateDegree == 90 || rotateDegree == 270) {
matrix.postScale(1, -1);
} else {
matrix.postScale(-1, 1);
}
}
matrix.postRotate(rotateDegree);
int width = b.getWidth();
int height = b.getHeight();
if (width % 4 != 0) {
width = width >> 2 << 2;
}
if (height % 4 != 0) {
height = height >> 2 << 2;
}
return Bitmap.createBitmap(b, 0, 0, width, height, matrix, true);
}

/**
* 旋转Bitmap
*
* @param src 原bitmap
* @param degrees 旋转角度
* @param px 旋转中心点的x坐标
* @param py 旋转中心点的y坐标
* @return Bitmap对象
*/
public static Bitmap rotate(final Bitmap src, final int degrees, final float px, final float py) {
return rotate(src, degrees, px, py, false);
}

/**
* 旋转Bitmap
*
* @param src 原bitmap
* @param degrees 旋转角度
* @param px 旋转中心点的x坐标
* @param py 旋转中心点的y坐标
* @param recycle 是否回收bitmap
* @return 旋转后的bitmap
*/
public static Bitmap rotate(final Bitmap src, final int degrees, final float px, final float py, final boolean recycle) {
if (isEmptyBitmap(src)) {
return null;
}
if (degrees == 0) {
return src;
}
Matrix matrix = new Matrix();
matrix.setRotate(degrees, px, py);
Bitmap ret = Bitmap.createBitmap(src, 0, 0, src.getWidth(), src.getHeight(), matrix, false);
if (recycle && !src.isRecycled() && ret != src) {
src.recycle();
}
return ret;
}

/**
* 将图片文件转换为Bitmap对象
* TODO: 未理解size参数的概念,可自行理解ArcFaceGo再修改该函数
*
* @param srcPath 图片文件
* @param size
* @return Bitmap对象
*/
public static Bitmap getImagePng(String srcPath, int size) {
return BitmapFactory.decodeFile(srcPath);
}

/**
* 根据最大宽高等比缩放Bitmap
*
* @param bitmap 原Bitmap
* @param maxWidth 最大宽度
* @param maxHeight 最大高度
* @return 等比缩放后的Bitmap对象
*/
public static Bitmap resizeImage(Bitmap bitmap, int maxWidth, int maxHeight) {
int bitmapWidth = bitmap.getWidth();
int bitmapHeight = bitmap.getHeight();
float scale = Math.min((float) maxWidth / bitmapWidth, (float) maxHeight / bitmapHeight);
Matrix matrix = new Matrix();
matrix.postScale(scale, scale);
return Bitmap.createBitmap(bitmap, 0, 0, bitmapWidth, bitmapHeight, matrix, false);
}

/**
* 确保Bitmap宽度是4的倍数,并且高度是2的倍数
*
* @param bm Bitmap对象
* @return 宽度是4的倍数,并且高度是2的倍数的Bitmap
*/
public static Bitmap setBitmap4Align(Bitmap bm) {
Bitmap newBitmap;
int width = bm.getWidth();
int height = bm.getHeight();
int newWidth = width;
int newHeight = height;
if (newWidth % FACE_DETECT_IMAGE_WIDTH_LIMIT != 0) {
newWidth = newWidth >> 2 << 2;
}
if (newHeight % FACE_DETECT_IMAGE_HEIGHT_LIMIT != 0) {
newHeight = newHeight & ~1;
}
// 计算缩放比例.
float scaleWidth = ((float) newWidth) / width;
float scaleHeight = ((float) newHeight) / height;
// 取得想要缩放的matrix参数.
Matrix matrix = new Matrix();
matrix.postScale(scaleWidth, scaleHeight);
// 得到新的图片.
newBitmap = Bitmap.createBitmap(bm, 0, 0, width, height, matrix, true);
return newBitmap;
}

/**
* 缩放Bitmap对象
*
* @param bitmap Bitmap对象
* @param newWidth 新的宽度
* @param newHeight 新的高度
* @return 缩放后的Bitmap对象
*/
public static Bitmap zoomImg(Bitmap bitmap, int newWidth, int newHeight) {
int width = bitmap.getWidth();
int height = bitmap.getHeight();
float scaleWidth = ((float) newWidth) / width;
float scaleHeight = ((float) newHeight) / height;
Matrix matrix = new Matrix();
matrix.postScale(scaleWidth, scaleHeight);
return Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, true);
}

/**
* 获取图片宽高
*
* @param imgPath 图片文件路径
* @return 图片宽高
*/
public static Pair getImageOption(String imgPath) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(imgPath, options);
return new Pair<>(options.outWidth, options.outHeight);
}

/**
* 判断字符串是否为空格类字符串
*
* @param str 待判断的字符串
* @return 是否为空格类字符串
*/
public static boolean isSpace(final String str) {
if (str == null) {
return true;
}
for (int i = 0, len = str.length(); i < len; ++i) {
if (!Character.isWhitespace(str.charAt(i))) {
return false;
}
}
return true;
}

/**
* 创建文件
*
* @param file 文件
* @return 是否创建成果
*/
public static boolean createFileByDeleteOldFile(final File file) {
if (file == null) {
return false;
}
if (file.exists() && !file.delete()) {
return false;
}
if (!createDirOrDirExist(file.getParentFile())) {
return false;
}
try {
return file.createNewFile();
} catch (IOException e) {
return false;
}
}

/**
* 查看文件夹是否存在,如果不存在,则创建文件夹
*
* @param file 文件夹对象
* @return 最终是否存在
*/
public static boolean createDirOrDirExist(final File file) {
return file != null && (file.exists() ? file.isDirectory() : file.mkdirs());
}

/**
* 将文件路径转换为文件对象
*
* @param path 文件路径
* @return 文件对象
*/
public static File getFileByPath(final String path) {
return isSpace(path) ? null : new File(path);
}

/**
* 将输入流转换为Bitmap对象
*
* @param inputStream 输入流
* @param maxWidth 最大宽度
* @param maxHeight 最大高度
* @param chunkSize 临时buffer大小
* @return Bitmap对象
* @throws IOException 读取inputStream时可能出现的异常
*/
public static Bitmap getBitmap(final InputStream inputStream, int maxWidth, int maxHeight, int chunkSize)
throws IOException {
if (inputStream == null) {
return null;
}
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;

byte[] data = inputStream2ByteArr(inputStream, chunkSize);

BitmapFactory.decodeByteArray(data, 0, data.length, options);

options.inSampleSize = ImageUtils.calculateInSampleSize4(options, maxWidth, maxHeight);
options.inJustDecodeBounds = false;

return BitmapFactory.decodeByteArray(data, 0, data.length, options);
}

/**
* 将输入流转换为字节数组
*
* @param inputStream 输入流
* @param chunkSize 临时buffer的大小
* @return 字节数组
* @throws IOException 读取输入流时可能会产生的异常
*/
private static byte[] inputStream2ByteArr(InputStream inputStream, int chunkSize) throws IOException {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
byte[] buff = new byte[chunkSize];
int len;
while ((len = inputStream.read(buff)) != -1) {
outputStream.write(buff, 0, len);
}
outputStream.flush();
outputStream.close();
return outputStream.toByteArray();
}

/**
* 按人脸检测结果截取bitmap
*
* @param rect 人脸位置
* @param orient 人脸角度,详见ArcFace文档
* @param bitmap 原bitmap
* @return 裁剪后的bitmap
*/
public static Bitmap getFaceRegisterCropBitmap(Rect rect, int orient, Bitmap bitmap) {
if (rect == null || bitmap == null) {
return null;
}
int length = Math.max(rect.width(), rect.height()) / 2;
int wPadding = Math.min(Math.min(rect.left, bitmap.getWidth() - rect.right), length);
int width = rect.width() + 2 * wPadding;
int x = rect.left - wPadding;
int tPadding = Math.min(rect.top, length);
int y = rect.top - tPadding;
int bPadding = Math.min(bitmap.getHeight() - rect.bottom, length);
int height = rect.height() + tPadding + bPadding;
if ((width & 0b11) != 0) {
width &= ~0b11;
}
if ((height & 1) != 0) {
height &= ~1;
}
Matrix matrix = new Matrix();
if (orient == 2) {
matrix.setRotate(90);
} else if (orient == 4) {
matrix.setRotate(180);
} else if (orient == 3) {
matrix.setRotate(270);
}

return Bitmap.createBitmap(bitmap, x, y, width, height, matrix, true);
}

/**
* 将图像信息转换为Bitmap对象
*
* @param imgArray 图像数据,可以是JPGPNG等格式
* @return Bitmap对象
*/
public static Bitmap getBitmap(byte[] imgArray) {
return BitmapFactory.decodeByteArray(imgArray, 0, imgArray.length);
}

/**
* 将输入流转换为Bitmap对象
*
* @param inputStream 输入流
* @return Bitmap对象
*/
public static Bitmap getBitmap(InputStream inputStream) {
return BitmapFactory.decodeStream(inputStream);
}
}


2.2.4 编译apk
将上述两个Java类存放到下方目录,


ArcFaceGolibutilsrcmainjavacomarcsoftarcfacesinglelibutil

下图红框即为刚刚存放好的Java类,

点击


Build -> Build bundle(s)/APK(s) -> Build APK(s)

即可编译APK
三、 安装及使用
3.1 安装
直接点击Android Studio的安装或使用adb install或者其他方式将apk安装到设备中


3.2 使用
APP_ID等信息存放到



sdcard/com_arcsoft_arcfacesingle_charge/activeConfig/activeConfig.txt

格式如下(以下为示例数据,非真实数据):


APP_ID:Abvyu5a4ds4vaBhyLSNcp49HW6tuPx3sqWog8i9S41Q7
SDK_KEY:EvvwadsFj7XjL1siCQgSD2qGcmeFsE2bCpgtMJpS4MW3
ACTIVE_KEY:8551-2136-J3HC-E5FH


首次打开ArcFaceGo App,会自动进入激活、配置等界面,配置完成后即可使用。
APK的具体使用说明详见压缩包中的doc/操作指南_Android设备端.pdf


了解更多人脸识别产品相关内容请到虹软视觉开放*台哦

相关文档

  • 不断努力尝试的谚语有哪些
  • 国内外明星辣妈瘦身大公开 让普通的你也窈窕一夏 外食族7个好习惯保持苗条 今夏让你瘦个够
  • 思想政治建设工作会议上的讲话
  • 乳房摄影较精确?与超音波筛检相近
  • The method getDispatcherType() is undefined for the type HttpServletRequest 升级到tomcat8
  • 初二下册语文第六单元综合复习题及答案
  • 琢磨不透的爱
  • 小米5c手机卡机了怎么办
  • 计算机软件XXX热门协议书
  • 大桥鱼精上市计划
  • 关于双调?水仙子?讥时的注释
  • 霸气动漫男生壁纸
  • 血字的研究优秀读后感范文(通用3篇)
  • 合伙做生意的十大禁忌具体内容
  • 水电产业开发工作的调查报告参考精选多篇
  • 海河水利委员会离休干部党支部先进事迹材料
  • 晒美景的心情短语
  • 单位试用期总结报告
  • 幼儿园安全管理工作自查报告范文
  • 大一学生入党思想汇报精选多篇
  • 抖音镜面特效在哪?如何录制抖音镜面视频?
  • git提交时”warning: LF will be replaced by CRLF“提示
  • 对女性好的中药材有哪些
  • 九年级作文倾吐心声3篇
  • 2020年母亲节服饰专卖促销活动主题方案:感恩母亲,母爱永恒
  • IDEA 2020.2.1 Tomcat的部署
  • 四川成都餐饮小吃加盟店有哪些好项目
  • 关于铁道运输的实习报告
  • CCF 2017年12月第5题-商路
  • OPPO手机应用加密的通用密码是什么
  • 电脑版