运行虹软应用套件开源代码,发现报错。查看错误信息,说的是缺少类(详细说明看下方)
咨询了下虹软小助手,表示这两个类确实是需要自己实现的
晚上加班把这个做出来了,不得不说虹软开放了应用套件,确实省去了很多研发时间,当天晚上就跑通了
下面把类实现分享在这里,给有需要的人做个参考。。
导航:
– 获取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;
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("无法初始化!");
}
private static boolean isEmptyBitmap(final Bitmap src) {
return src == null || src.getWidth() == 0 || src.getHeight() == 0;
}
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();
}
public static Bitmap getBitmap(final File file) {
if (file == null) {
return null;
}
return BitmapFactory.decodeFile(file.getAbsolutePath());
}
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);
}
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);
}
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;
}
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;
}
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;
}
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);
}
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;
}
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;
}
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;
}
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;
}
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);
}
public static Bitmap rotate(final Bitmap src, final int degrees, final float px, final float py) {
return rotate(src, degrees, px, py, false);
}
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;
}
public static Bitmap getImagePng(String srcPath, int size) {
return BitmapFactory.decodeFile(srcPath);
}
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);
}
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;
}
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);
}
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);
}
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;
}
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;
}
}
public static boolean createDirOrDirExist(final File file) {
return file != null && (file.exists() ? file.isDirectory() : file.mkdirs());
}
public static File getFileByPath(final String path) {
return isSpace(path) ? null : new File(path);
}
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);
}
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();
}
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);
}
public static Bitmap getBitmap(byte[] imgArray) {
return BitmapFactory.decodeByteArray(imgArray, 0, imgArray.length);
}
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
了解更多人脸识别产品相关内容请到虹软视觉开放平台哦



