InspireFaceInspireFace1.2.4.d3
首页
快速开始
获取和编译
完整示例
  • English
  • 简体中文
GitHub
首页
快速开始
获取和编译
完整示例
  • English
  • 简体中文
GitHub
  • 介绍
  • 快速开始
  • 功能概览
  • 使用指南

    • 架构与生命周期
    • 模型资源包
    • 图像输入与坐标
    • 会话与跟踪
    • 人脸分析
    • 识别与特征库
    • 人脸关键点
    • 活体检测
    • 人脸抓拍
    • 补充 API 示例
  • 语言与平台

    • C API
    • C++
    • Python
    • Android
    • Apple
    • iOS
    • macOS
    • HarmonyOS
  • 获取和编译

    • 概述与下载
    • 源码准备与通用选项
    • Linux
    • macOS
    • Android
    • iOS
    • HarmonyOS
    • NVIDIA TensorRT
    • Rockchip NPU
    • Python 打包
  • 硬件部署

    • ARM
    • NVIDIA TensorRT
    • Rockchip NPU
    • Rockchip 上的 Python
  • InspireCV
  • 完整示例
  • API 功能索引
  • 性能测量
  • 图像处理性能
  • 常见问题

API 实用示例

本页介绍对齐人脸图像、转换显示分数、查询运行库和检查资源释放。运行前,先按语言接入指南初始化 Session 并准备输入图像。Native、Objective-C / Swift、Python 和 HarmonyOS 示例使用 1.2.4,Android 示例使用 Java SDK 1.2.0。

获取对齐后的人脸图像

人脸对齐根据检测到的关键点,将眼睛等位置调整到识别模型要求的布局。可以保存对齐图,检查识别模型的输入,也可以将它交给接受已对齐图像的后续步骤。

普通识别直接调用 face_feature_extract / FaceFeatureExtract 即可,接口内部包含对齐操作。

C API

调用前用 HFCreateFaceFeature 分配 output,用完后通过 HFReleaseFaceFeature 释放。原始 stream 和 token 在调用期间需要保持有效。

#include <inspireface.h>
#include <stddef.h>

// session has recognition enabled; token belongs to source.
// output was allocated by HFCreateFaceFeature and remains caller-owned.
HResult extract_aligned(HFSession session, HFImageStream source,
                        HFFaceBasicToken token, HFFaceFeature output) {
    HFImageBitmap crop = NULL;
    HFImageStream aligned = NULL;
    HResult status = HFFaceGetFaceAlignmentImage(session, source, token, &crop);
    if (status != HSUCCEED) return status;
    status = HFCreateImageStreamFromImageBitmap(crop, HF_CAMERA_ROTATION_0, &aligned);
    if (status == HSUCCEED) {
        status = HFFaceFeatureExtractWithAlignmentImage(session, aligned, output);
    }
    if (aligned != NULL) HFReleaseImageStream(aligned);
    HFReleaseImageBitmap(crop);
    return status;
}

如果只想保存对齐图,调用 HFFaceGetFaceAlignmentImage,再用 HFImageBitmapWriteToFile 写入文件,最后释放 bitmap。两次调用都要检查返回值。

C++
#include <inspireface/inspireface.hpp>

int32_t extract_aligned(inspire::Session& session,
                        inspirecv::FrameProcess& frame,
                        inspire::FaceTrackWrap& face,
                        inspire::FaceEmbedding& embedding) {
    inspirecv::Image aligned;
    session.GetFaceAlignmentImage(frame, face, aligned);
    if (aligned.Empty()) return HERR_SESS_REC_EXTRACT_FAILURE;
    // aligned can also be inspected or saved with aligned.Write(...).
    return session.FaceFeatureExtractWithAlignmentImage(aligned, embedding);
}

图像和特征各自持有数据。GetFaceAlignmentImage 返回 void,因此继续提取前需要检查输出图像是否为空。

Objective-C

先在会话中启用识别。传入对应原图的有效 token,以及已创建的 IFFeatureBuffer,两者均由调用方管理。函数关闭自己的裁剪图和临时图像流,通过 BOOL/NSError 返回错误。需要保存裁剪图时,在关闭前调用 [crop writeToFile:path error:&error]。

#import <InspireFace/InspireFaceApple.h>

static BOOL ExtractAligned(IFSession *session, IFImageStream *source,
                           HFFaceBasicToken token, IFFeatureBuffer *output,
                           NSError **error) {
    IFImageBitmap *crop = [session alignmentBitmapFromStream:source token:token error:error];
    if (crop == nil) return NO;
    IFImageStream *aligned = nil;
    @try {
        aligned = [crop snapshotStreamWithRotation:HF_CAMERA_ROTATION_0 error:error];
        if (aligned == nil) return NO;
        return [session extractAlignedFeatureFromStream:aligned
            into:output.borrowedFeature error:error];
    } @finally {
        if (aligned != nil) [aligned closeWithError:NULL];
        [crop closeWithError:NULL];
    }
}
Swift

会话启用 .recognition,传入当前原图的 token 和尚未关闭的 FaceFeatureBuffer。snapshotStream 会明确复制裁剪图的像素。即使提取失败,函数也会关闭临时资源;输出特征缓冲区由调用方在使用结束后关闭。保存裁剪图可在关闭前调用 try crop.write(toFile: path)。

import InspireFaceSwift

func extractAligned(session: FaceSession, source: ImageStream,
                    token: FaceToken, into output: FaceFeatureBuffer) throws {
    let crop = try session.alignmentBitmap(from: source, token: token)
    defer { try? crop.close() }
    let aligned = try crop.snapshotStream(rotation: .degrees0)
    defer { try? aligned.close() }
    try session.extractAlignedFeature(from: aligned, into: output.borrowedFeature)
}
Android
// session, stream and faces come from the same detection call.
static android.graphics.Bitmap alignedFace(
        com.insightface.sdk.inspireface.base.Session session,
        com.insightface.sdk.inspireface.base.ImageStream stream,
        com.insightface.sdk.inspireface.base.MultipleFaceData faces) {
    if (faces == null || faces.detectedNum != 1) {
        throw new IllegalArgumentException("Expected exactly one face");
    }
    android.graphics.Bitmap aligned = InspireFace.GetFaceAlignmentImage(
            session, stream, faces.tokens[0]);
    if (aligned == null) throw new IllegalStateException("Alignment failed");
    return aligned;
}

导入 com.insightface.sdk.inspireface.InspireFace 后即可使用。应用可以显示或保存返回的 bitmap,处理完成后释放原始 ImageStream。识别时调用 ExtractFaceFeature(session, stream, token),由接口完成对齐和特征提取。

HarmonyOS

调用方准备已启用识别的 Session、原始 ImageStream 和对应的检测结果,并在调用期间保持它们有效。将结果 faces 中的一张人脸传给下面的函数;函数只释放自己创建的对齐图和 stream。

import { ImageStream, Session, TrackedFace } from '@hyperinspire/inspireface';

function extractAligned(session: Session, image: ImageStream,
                        face: TrackedFace): Float32Array {
  const crop = session.getFaceAlignmentImage(image, face);
  try {
    const aligned = ImageStream.fromBitmap(crop);
    try {
      return session.extractFeatureFromAlignmentImage(aligned);
    } finally {
      aligned.close();
    }
  } finally {
    crop.close();
  }
}

关闭 bitmap 前,可以用 crop.getData() 读取像素、尺寸和通道数。对齐图使用 BGR 像素,显示或编码时需转换成应用图像接口要求的格式。标准 HAR 构建使用内存图像操作。普通识别直接调用 session.extractFeature(image, face),由接口一次完成对齐和提取。

Python

识别时调用 session.face_feature_extract(image, face),由接口完成对齐和特征提取。绘制调试图时,可以用 get_face_five_key_points 读取五点坐标。需要保存对齐图本身时,可使用上方的 C、C++、Objective-C、Swift 或 Android 示例。

将对齐和提取拆开处理时,把 SDK 生成的对齐图传给提取接口,并保持其对齐方式、尺寸和像素格式。

转换用于显示的相似度

识别和 FeatureHub 检索使用原始 cosine similarity 判断是否通过阈值。Similarity converter 按配置的曲线将它转换为显示分数。匹配判断和日志使用原始 cosine 分数。

outputMin 和 outputMax 决定转换后的分数范围,默认约为 0.01–1.0。显示前先读取这两个配置,再决定如何换算。

C API
#include <inspireface.h>
#include <stdio.h>

HResult print_display_score(float cosine) {
    HFloat display = 0.0f;
    HFSimilarityConverterConfig config = {0};
    HResult status = HFGetCosineSimilarityConverter(&config);
    if (status != HSUCCEED) return status;
    status = HFCosineSimilarityConvertToPercentage(cosine, &display);
    if (status == HSUCCEED) {
        printf("cosine=%.4f display=%.4f range=[%.2f, %.2f]\n",
               cosine, display, config.outputMin, config.outputMax);
    }
    return status;
}
C++
#include <inspireface/inspireface.hpp>
#include <iostream>

void print_display_score(float cosine) {
    auto& converter = inspire::SimilarityConverter::getInstance();
    auto config = converter.getConfig();
    std::cout << "cosine=" << cosine
              << " display=" << converter.convert(cosine)
              << " range=[" << config.outputMin << ", " << config.outputMax << "]\n";
}
Objective-C

传入比对得到的原始余弦分数。读取显示值前检查 BOOL/NSError。应用初始化阶段可用 setSimilarityConverter:error: 设置共享转换曲线。

#import <InspireFace/InspireFaceApple.h>

static BOOL PrintDisplayScore(float cosine, NSError **error) {
    HFSimilarityConverterConfig config = {0};
    float display = 0;
    if (![IFFeatureBuffer getSimilarityConverter:&config error:error] ||
        ![IFFeatureBuffer convertSimilarity:cosine percentage:&display error:error]) return NO;
    NSLog(@"cosine=%.4f display=%.4f range=[%.2f, %.2f]",
        cosine, display, config.outputMin, config.outputMax);
    return YES;
}
Swift

函数失败时抛出错误。应用初始化阶段可用 FaceFeatureBuffer.setSimilarityConverter(_:) 修改共享曲线;匹配判断仍使用原始余弦分数。

import InspireFaceSwift

func printDisplayScore(cosine: Float) throws {
    var config = HFSimilarityConverterConfig()
    var display: Float = 0
    try FaceFeatureBuffer.getSimilarityConverter(&config)
    try FaceFeatureBuffer.convert(similarity: cosine, percentage: &display)
    print("cosine=\(cosine) display=\(display) range=[\(config.outputMin), \(config.outputMax)]")
}
Android
static void printDisplayScore(float cosine) {
    com.insightface.sdk.inspireface.base.SimilarityConverterConfig config =
            InspireFace.GetCosineSimilarityConverter();
    if (config == null) throw new IllegalStateException("Converter unavailable");
    float display = InspireFace.CosineSimilarityConvertToPercentage(cosine);
    android.util.Log.i("FaceScore", "cosine=" + cosine + " display=" + display
            + " range=[" + config.outputMin + ", " + config.outputMax + "]");
}
HarmonyOS
import { InspireFace } from '@hyperinspire/inspireface';

// cosine is the raw result of InspireFace.compareFeatures(first, second).
function printDisplayScore(cosine: number): void {
  const config = InspireFace.getSimilarityConverter();
  const display = InspireFace.similarityToPercentage(cosine);
  console.info(`cosine=${cosine} display=${display} ` +
    `range=[${config.outputMin}, ${config.outputMax}]`);
}

需要在应用初始化时调整曲线,可将 SimilarityConverterConfig 传给 InspireFace.updateSimilarityConverter(config)。

Python
import inspireface as isf

# cosine is the raw result of isf.feature_comparison(feature_a, feature_b).
def print_display_score(cosine):
    config = isf.get_similarity_converter_config()
    display = isf.cosine_similarity_convert_to_percentage(cosine)
    print("cosine", cosine, "display", display,
          "range", (config["outputMin"], config["outputMax"]))

可以通过 HFUpdateCosineSimilarityConverter、C++ SimilarityConverter::updateConfig、Objective-C setSimilarityConverter:error:、Swift FaceFeatureBuffer.setSimilarityConverter(_:)、Java UpdateCosineSimilarityConverter、ArkTS InspireFace.updateSimilarityConverter 或 Python set_similarity_converter_config 修改曲线。配置字段为 threshold、middleScore、steepness、outputMin 和 outputMax。通常在应用初始化时设置一次。识别阈值另外用具有代表性的同人、非同人图片对来评估。

检查运行库与错误信息

排查部署问题时,记录实际加载的库版本、模型包和已启用后端。Native 和 Python 的诊断查询可以在加载模型前调用。组件状态中,known 表示版本已读取,unknown 表示版本无法读取,disabled 表示后端未启用。

C API
#include <inspireface.h>
#include <stdio.h>
#include <stdlib.h>

int print_diagnostics(void) {
    HInt32 required = 0;
    HResult status = HFQueryInspireFaceDiagnosticInformation(NULL, 0, &required);
    if (status != HSUCCEED || required <= 0) return 1;
    char *text = (char *)malloc((size_t)required);
    if (text == NULL) return 1;
    status = HFQueryInspireFaceDiagnosticInformation(text, required, &required);
    if (status == HSUCCEED) puts(text);
    free(text);
    return status == HSUCCEED ? 0 : 1;
}

void print_sdk_error(HResult failure) {
    char message[256];
    HInt32 required = 0;
    HResult status = HFGetErrorMessage(failure, message, sizeof(message), &required);
    if (status == HSUCCEED) {
        fprintf(stderr, "InspireFace %ld: %s\n", (long)failure, message);
    } else {
        fprintf(stderr, "InspireFace %ld (message needs %d bytes)\n",
                (long)failure, required);
    }
}

第一次查询得到所需容量,包含字符串结尾的空字符;第二次查询传入该容量。HFGetErrorMessage 同样会报告所需长度,示例在消息缓冲区不足时仍记录原始错误码。

C++
#include <inspireface/component_version.h>
#include <iostream>

void print_diagnostics() {
    std::cout << inspire::GetDiagnosticInfo() << '\n';
    auto cv = inspire::GetComponentVersion(inspire::ComponentType::INSPIRECV);
    if (cv.IsVersionKnown()) {
        std::cout << "InspireCV " << cv.GetVersionString() << '\n';
    }
}

C++ 操作返回错误码时,也可以包含 <inspireface.h>,使用上面的 HFGetErrorMessage 辅助函数读取错误文字。

Objective-C

模型启动前也能查询。先获取包含末尾空字符的所需容量。SDK 失败时,NSError.domain 为 IFErrorDomain,code 保留 C 接口的 HResult。记录这两个字段,并附上 localizedDescription,有说明文本时便于一起排查。每次调用都要检查 BOOL 或 nil。

#import <InspireFace/InspireFaceApple.h>
#include <stdlib.h>

static BOOL PrintDiagnostics(NSError **error) {
    HInt32 required = 0;
    if (![IFDiagnostics getDiagnosticInformation:NULL capacity:0
        requiredSize:&required error:error]) return NO;
    if (required <= 0) return IFCheck(HERR_INVALID_PARAM, error);
    char *buffer = calloc((size_t)required, 1);
    if (buffer == NULL) return IFCheck(HERR_INVALID_PARAM, error);
    BOOL ok = [IFDiagnostics getDiagnosticInformation:buffer capacity:required
        requiredSize:&required error:error];
    if (ok) NSLog(@"%s", buffer);
    free(buffer);
    return ok;
}

static void LogSDKError(NSError *error) {
    NSLog(@"%@ code=%ld: %@", error.domain, (long)error.code, error.localizedDescription);
}
// NSError *error = nil;
// if (!PrintDiagnostics(&error)) LogSDKError(error);
Swift

Swift 方法通过抛出 NSError 传递同一套 SDK 错误。分配前先查询容量,在应用层记录 domain、数值 code 和说明。跟踪调用成功但结果为零张人脸时属于正常结果,不会因此抛出异常。

import InspireFaceSwift

func printDiagnostics() throws {
    var required: Int32 = 0
    try InspireFaceDiagnostics.getDiagnosticInformation(nil, capacity: 0, requiredSize: &required)
    guard required > 0 else {
        throw NSError(domain: IFErrorDomain, code: Int(HERR_INVALID_PARAM))
    }
    let buffer = UnsafeMutablePointer<CChar>.allocate(capacity: Int(required))
    defer { buffer.deallocate() }
    try InspireFaceDiagnostics.getDiagnosticInformation(buffer, capacity: required,
                                                        requiredSize: &required)
    print(String(cString: buffer))
}

func logSDKError(_ error: Error) {
    let failure = error as NSError
    print("\(failure.domain) code=\(failure.code): \(failure.localizedDescription)")
}
// do { try printDiagnostics() } catch { logSDKError(error) }
Android
static void printDiagnostics() {
    com.insightface.sdk.inspireface.base.InspireFaceVersion version =
            InspireFace.QueryInspireFaceVersion();
    if (version == null) throw new IllegalStateException("Version query failed");
    android.util.Log.i("FaceSDK", version.major + "." + version.minor + "."
            + version.patch + " " + version.information);
    InspireFace.SetLogLevel(InspireFace.LOG_INFO);
}

Java SDK 1.2.0 提供版本信息和日志设置。每次调用都检查 null 或 boolean 结果,并在应用日志中记录具体操作和输入格式。

HarmonyOS
import { FaceTrackResult, ImageStream, InspireFace, LogLevel, Session }
  from '@hyperinspire/inspireface';

function printDiagnostics(): void {
  const version = InspireFace.getVersion();
  console.info(`${version.major}.${version.minor}.${version.patch} ` +
    `C API level=${InspireFace.getCapiLevel()}`);
  console.info(InspireFace.getDiagnosticInformation());
  console.info(InspireFace.getComponentVersions());
  InspireFace.setLogLevel(LogLevel.INFO);
}

// The caller owns session/image and releases the returned face result.
function detectWithContext(session: Session, image: ImageStream): FaceTrackResult {
  try {
    return session.track(image);
  } catch (error) {
    const failure = error as Error;
    console.error(`track failed: ${failure.message}`);
    throw error;
  }
}

ArkTS 调用失败时会抛出异常。保留异常消息,其中包含操作名称和 SDK 错误文字。已有数字错误码时,可以用 InspireFace.getErrorMessage(code) 查询说明。调用成功且 detectedNum === 0 表示没有检测到人脸。

Python
import inspireface as isf

print(isf.version(), "C API level", isf.c_api_level())
print(isf.diagnostic_info())
for name, component in isf.component_versions().items():
    print(name, component["state"], component["version"])

# At the application boundary, preserve the original exception.
def detect_with_context(session, image):
    try:
        return session.face_detection(image)
    except isf.InspireFaceError as error:
        print(error.error_code, error.error_name, str(error))
        raise

这些诊断方法需要配套的 1.2.4 wrapper 和 Native 库。处理异常时记录错误,并与检测结果分开处理。空列表表示检测成功,但没有符合条件的人脸。

检查资源是否释放

开发时可以反复创建、使用和关闭一组对象,对比操作前后的资源数量。对比时先暂停其他工作线程,避免把它们仍在使用的 Session 算进结果。

C API
#include <inspireface.h>
#include <stdio.h>

HResult print_open_handles(void) {
    HInt32 sessions = 0, streams = 0;
    HResult status = HFDeBugGetUnreleasedSessionsCount(&sessions);
    if (status != HSUCCEED) return status;
    status = HFDeBugGetUnreleasedStreamsCount(&streams);
    if (status != HSUCCEED) return status;
    printf("open sessions=%d streams=%d\n", sessions, streams);
    return HFDeBugShowResourceStatistics();
}
C++

C++ 的 Session、Image 和 capture selector 在离开作用域时释放自己持有的资源。应用同时使用 C API 时,可以用上面的诊断函数统计仍在使用的 C Session 和 stream handle。Native C++ 对象和 GPU 分配可通过内存分析工具检查。

Objective-C

在处理队列空闲时,于任务前后各调用一次。closeWithError: 会立即释放对象持有的原生句柄;ARC 在对象销毁时也会释放。先关闭抓拍再关闭父会话,先关闭借用图像流再释放输入像素。计数器只统计会话和图像流,不代表全部内存分配。

#import <InspireFace/InspireFaceApple.h>

static BOOL PrintOpenHandles(NSError **error) {
    HInt32 sessions = 0, streams = 0;
    if (![IFDiagnostics getLiveSessionCount:&sessions error:error] ||
        ![IFDiagnostics getLiveStreamCount:&streams error:error]) return NO;
    NSLog(@"open sessions=%d streams=%d", sessions, streams);
    return [IFDiagnostics printResourceStatisticsWithError:error];
}
Swift

函数内创建的资源,可以紧接着写 defer { try? resource.close() }。长期保留的相机对象在串行工作队列停止后关闭。Swift 闭包辅助接口限制借用范围,但不会让已保存的指针在关闭或后续处理后继续有效。

import InspireFaceSwift

func printOpenHandles() throws {
    var sessions: Int32 = 0
    var streams: Int32 = 0
    try InspireFaceDiagnostics.getLiveSessionCount(&sessions)
    try InspireFaceDiagnostics.getLiveStreamCount(&streams)
    print("open sessions=\(sessions) streams=\(streams)")
    try InspireFaceDiagnostics.printResourceStatistics()
}
Android

每个 CreateSession 对应一个 ReleaseSession,每个 stream 创建操作对应一个 ReleaseImageStream,一般放在 finally 中释放。较新的 FaceCapture 和 FaceDetectionSnapshot 支持 try-with-resources,使用时配套更新 JNI 库。

HarmonyOS

调用前先加载模型。输入为紧凑排列的 RGBA 数据;每次调用创建并释放一个 Session、image stream 和检测结果。

import { DetectMode, ImageFormat, InspireFace } from '@hyperinspire/inspireface';

function checkResourceLifetime(rgba: Uint8Array, width: number, height: number): void {
  const before = InspireFace.getDebugResourceCounts();
  const session = InspireFace.createSession({ detectMode: DetectMode.ALWAYS_DETECT });
  try {
    const image = InspireFace.createImageStream(rgba, width, height, ImageFormat.RGBA);
    try {
      const faces = session.track(image);
      try {
        console.info(`faces=${faces.detectedNum}`);
      } finally {
        session.releaseFaceResult(faces);
      }
    } finally {
      image.close();
    }
  } finally {
    session.close();
    const after = InspireFace.getDebugResourceCounts();
    console.info(`sessions=${before.sessions}->${after.sessions} ` +
      `streams=${before.streams}->${after.streams}`);
    InspireFace.showDebugResourceStatistics();
  }
}

计数器统计 Session 和 stream。自己创建的 ImageBitmap、FaceCaptureSession 也要调用 close(),每次 session.track() 返回的结果都要释放。Capture session 需在它所依赖的 Session 关闭前结束使用。

Python
import inspireface as isf

# Call before and after a bounded workload during development.
isf.show_system_resource_statistics()

Session、stream、snapshot 和 capture 优先使用上下文管理器。长期存在的应用对象可以在结束使用时调用 close() 或 release()。

计数器报告仍在使用的 SDK handle。进程内存需单独测量,其中也包含运行中的工作线程所保留的模型内存和分配器缓存。逐帧耗时的测量方法见性能测试。

编辑此页
最近更新: 2026/9/28 20:17
贡献者: Jingyu
上一页
人脸抓拍