Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Visual Studioのプロジェクトを開き,SDK中のLicenseファイル(license_online.licに変更してください)、runtime_check.exe、opengl_check.exe、st_mobile.dllおよびst_mobile.libをビルドして生成した実行(exe)ファイルのフォルダにコピーする。実行ファイルの上位フォルダにモデルフォルダ、ステッカーフォルダ、フィルターフォルダおよびメークアップフォルダをそれぞれ作成し、該当素材をフォルダにコピーする。
Visual Studio 2013またはそれ以上のバージョン、OpenCV 2.4.11または2.4.13。
windowsの場合は、runtime_check.exeを用いてFMAとAVX命令集の存在有無を確認します。
FMAとAVX命令集をサポートしない場合は,SSE命令集の指定が必要です。
SDK は、ライセンスファイルに従って、アルゴリズムライブラリの権限をチェックします。通常、アクティベーション完了後にのみ、SDK の機能を使用できます。
license_online.licファイルを実行ファイルと同じフォルダにコピーしてください。,check_license_online()メソッドはライセンス認証を行います。詳細は helper.hに参照してください。
アクティベーションコードの認証順番は以下の通り
(1)ライセンスファイルのコンテンツを読み込みます。
(2)ローカルコンピューターに保存されたアクティベーションコードを取得します。
(3)利用可能なアクティベーションコードがない場合は、生成します。
(4)checkActiveCode * コマンドを直接実行して、アクティベーションコードが有効であるかどうか確認します。
(5)確認に失敗した場合は、別のアクティベーションコードを生成します。
(6)生成に失敗した場合は、エラーメッセージが表示されます。成功すると、新しいアクティベーションコードが保存され、成功したことを示すメッセージが表示されます。
st_mobile_human_action_createとst_mobile_human_action_create_with_sub_modelsを用いてmodelファイルをロードします。詳細はSampleプロジェクトにhelper.hの中にmodelモデルファイルの利用方法に参照してください。
Sampleの素材ファイルはstickers,makeups,filtersフォルダに格納しています。
helper.h中のDfsFolderメソッドを用いて素材ファイルのパスをSDKに渡します。
// システムがサポートする命令集を確認する
// FMA/AVXパラメーターを用いてruntime_check.exeを実行させます
// 返り値は"true"の場合は, FMA/AVXは利用可能です。
static bool runtime_check(bool *fma, bool *avx) {
if (!fma || !avx) {
return false;
}
*fma = true;
*avx = true;
char exe[] = "runtime_check.exe ";
bool is_exist = false;
if (_access(exe, 0) == 0) {
is_exist = true;
}
if (is_exist) {
char arg[2][4] = { "FMA", "AVX" };
PROCESS_INFORMATION pi;
STARTUPINFO si;
memset(&pi, 0, sizeof(PROCESS_INFORMATION));
memset(&si, 0, sizeof(STARTUPINFO));
si.cb = sizeof(STARTUPINFO);
si.dwFlags |= STARTF_USESTDHANDLES; // STARTF_USESTDHANDLES is Required.
si.dwFlags |= STARTF_USESHOWWINDOW;
si.wShowWindow = SW_HIDE;
BOOL bSuccess;
int i;
for (i = 0; i < 2; i++) {
SECURITY_ATTRIBUTES saAttr;
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
saAttr.bInheritHandle = TRUE;
saAttr.lpSecurityDescriptor = NULL;
HANDLE hChildStdoutRd = NULL;
HANDLE hChildStdoutWr = NULL;
if (!CreatePipe(&hChildStdoutRd, &hChildStdoutWr, &saAttr, 0)) {
printf("cannot create pipe\n");
return false;
}
// Ensure the read handle to the pipe for STDOUT is not inherited.
if (!SetHandleInformation(hChildStdoutRd, HANDLE_FLAG_INHERIT, 0)) {
printf("Stdout SetHandleInformation");
return false;
}
si.hStdOutput = hChildStdoutWr;
si.hStdError = hChildStdoutWr;
// Requires STARTF_USESTDHANDLES in dwFlags
// Requires STARTF_USESTDHANDLES in dwFlags
char *cmd = new char[strlen(exe) + strlen(arg[i]) + 1];
strcpy(cmd, exe);
strcat(cmd, arg[i]);
bSuccess = CreateProcess(
NULL, // No module name (use command line)
cmd, // Command line
NULL, // Process handle not inheritable
NULL, // Thread handle not inheritable
TRUE, // Set handle inheritance to TRUE
0, // No creation flags
NULL, // Use parent's environment block
NULL, // Use parent's starting directory
&si, // Pointer to STARTUPINFO structure
&pi); // Pointer to PROCESS_INFORMATION structure
delete[] cmd;
if (bSuccess) {
if (0 == i) *fma = false;
if (1 == i) *avx = false;
WaitForSingleObject(pi.hProcess, INFINITE);
if (!CloseHandle(hChildStdoutWr)) {
printf("cannot close handle");
return false;
}
std::string strResult;
// Read output from the child process.
for (;;) {
DWORD dwRead;
char chBuf[64];
// Read from pipe that is the standard output for child process.
bSuccess = ReadFile(hChildStdoutRd, chBuf, 64, &dwRead, NULL);
if (!bSuccess || 0 == dwRead) {
break;
}
strResult += std::string(chBuf, dwRead);
}
if (strResult.length() > 0) {
std::size_t pos = strResult.find(":");
strResult = strResult.substr(pos + 2, 4);
if (strResult == "true") {
if (0 == i) *fma = true;
if (1 == i) *avx = true;
}
}
CloseHandle(hChildStdoutRd);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
else {
printf("CreateProcess failed: %d\n", GetLastError());
*fma = false;
*avx = false;
return false;
}
}
if (bSuccess && (!(*fma) || !(*avx)))
return false;
}
return true;
}static std::string g_FilterDir = "../filters";
static std::string g_StickerDir = "../stickers";
static std::string g_MakeupDir = "../makeups";static int check_license_online() {
// generate and check active code
char activate_buf[10000] = { 0 };
int activate_buf_len = sizeof(activate_buf);
const char* license_path = "license_online.lic";
const char* activate_path = "activate_code.lic";
std::ifstream in(activate_path);
if (!in.eof()) {
in >> activate_buf;
in.close();
}
int ret = st_mobile_check_activecode(license_path, activate_buf, strlen(activate_buf));
if (ret != ST_OK){
printf("we will generate new activate_code %d\n", ret);
ret = st_mobile_generate_activecode(license_path, activate_buf, &activate_buf_len);
if (ret == ST_OK) {
std::ofstream out(activate_path);
out << activate_buf;
out.close();
} else{
printf("fail to generate activate_code %d\n", ret);
return -1;
}
}
return 0;
}
const char* face_model = "M_SenseME_Face_Video_7.0.3.model";
const char* face_282_model = "M_SenseME_Face_Extra_Advanced_6.0.8.model";
const char* hand_model = "M_SenseME_Hand_6.0.8.model";
const char* segment_model = "M_SenseME_Segment_4.12.8.model";
const char* body14_model = "M_SenseME_Body_5.5.6.model";
const char* body_contour_model = "M_SenseME_Body_Contour_77_1.2.2.model";
const char* face_extra_model = "M_SenseME_Face_Extra_Advanced_6.0.8.model";
const char* mouth_parse_model = "M_SenseME_MouthOcclusion_1.0.0.model";
const char* eyeball_model = "M_SenseME_Iris_2.0.0.model";
const char* ear_model = "M_SenseME_Ear_1.0.1.model";
const char* body4_model = "M_SenseME_Body_Four_1.0.0.model";
const char* body8_model = "body8.model";
const char* hair_model = "M_SenseME_Segment_Hair_1.3.4.model";
const char* tongue_model = "M_SenseME_Tongue_1.0.0.model";
const char* face_mesh_model = "M_SenseME_3Dmesh_1.4.0.model";
const char* avatar_helper_model = "M_SenseME_Avatar_Help_2.2.0.model";
const char* gaze_model = "M_SenseME_GazeTracking_2.1.3.model";
const char* dynamic_gesture_model = "M_SenseME_Hand_Dynamic_Gesture_1.0.0.model";
const char* hand_skeleton_model = "M_SenseME_Hand_Skeleton_2d3d_1.0.0.model";
const char* multi_segment_model = "M_SenseME_Segment_Multiclass_1.0.0.model";
const char* attribute_model = "M_SenseME_Attribute_2.2.0.model";
const char* animal_model = "M_SenseME_CatFace_3.0.0.model";
const char* classify_model = "M_SenseME_Classify_3.4.10.model";
const char* verify_model = "M_SenseME_Verify_3.91.0.model";
const char* p_db_path = "M_SenseME_Classify_Table_1.0.7.db";
const char* p_custom_db_path = "M_SenseME_Classify_Custom_Table_1.0.7.db";
const char* upbody_model = "M_SenseME_Upper_Body_0.0.42.model";
static std::string g_ModelDir = "../models/";
inline void DfsFolder(const std::string& DirPath, const std::string&
suffix,std::vector<std::string>& files)
{
#ifdef _MSC_VER
_finddata_t file_info;
std::string current_path = DirPath + "/*.*";
intptr_t handle = _findfirst(current_path.c_str(), &file_info);
if (-1 == handle) {
return; }
do {
std::string tmpName = file_info.name;
if (tmpName.find(".") == 0)
continue;
std::string FullPath = DirPath + "/" + tmpName;
if (file_info.attrib == _A_SUBDIR) {
DfsFolder(FullPath, suffix, files);
}
else if (tmpName.find(suffix) != std::string::npos) {
files.push_back(FullPath);
}
} while (!_findnext(handle, &file_info));
_findclose(handle);
#else
... ...
#endif
} st_mobile_human_action_detectを利用する際に顔の向きを正常の位置にする必要があります。
//画像回転方向
typedef enum {
ST_CLOCKWISE_ROTATE_0 = 0, ///< 回転不要,画像の中に顔は正常の位置である
ST_CLOCKWISE_ROTATE_90 = 1, ///< 時計回りで90度回転し,顔を正常の位置に戻す
ST_CLOCKWISE_ROTATE_180 = 2,///< 時計回りで180度回転し,顔を正常の位置に戻す
ST_CLOCKWISE_ROTATE_270 = 3 ///< 時計回りで270度回転し,顔を正常の位置に戻す
} st_rotate_type;SDKはst_mobile_human_action_rotateのAPIも提供しています。詳細はst_mobile_human_action.hに参照してください。
// @brief human_actionのチェック結果.
// @param[in] image_width human_actionの画像のWidth(pixel単位)
// @param[in] image_height human_actionの画像のHeight(pixel単位)
// @param[in] orientation 時計回りの回転角度
// @param[in] b_rotate_image 回転要否
// @param[in,out] p_human_action human_actionのチェック結果
ST_SDK_API void
st_mobile_human_action_rotate(
int image_width,
int image_height,
st_rotate_type orientation,
bool b_rotate_image,
st_mobile_human_action_t* p_human_action
)st_mobile_human_action_mirrorを用いて、カメラで取得した画像と実際のシーンでミラーリングします。詳細はst_mobile_human_action.hに参照してください。
// @brief human_actionのミラーリング結果
// @param[in] image_width human_actionの画像のWidth(pixel単位) )
// @param[in,out] p_human_action human_actionのミラーリング結果
ST_SDK_API void
st_mobile_human_action_mirror(
int image_width,
st_mobile_human_action_t *p_human_action
);美顔、ステッカー、フィルターおよびメークアップ効果の実現にOpenGLの利用が必要です。
opengl_check.exeを実行し,システムおよびGPUドライバーのopengl32.dllバージョンを確認する
opengl_checkが失敗の場合は、Mesa版のopengl32.dllを用いてOpenGLの初期化を行う
opengl_checkが成功の場合は、glfwライブラリを初期化し、glfwウィンドウを作成する。glfwウィンドウ作成が失敗の場合は、Mesa版のopengl32.dllを用いてOpenGLの初期化を行う
glfwウィンドウの作成が成功したら,gl3wの初期化を行う。gl3wの初期化が失敗シた場合は,
Mesa版のopengl32.dllを用いてOpenGLの初期化を行う
OpenGLのバージョンを確認し,2.1以下またはOpenGLSLバージョンは1.2以下の場合は,エラーで返す
OpenGL初期化の詳細はhelper_opengl.hに参照してください。
Mesa版opengl32.dllによるOpenGLの初期化は以下の通り。
Mesa版opengl32.dllをロードする
glfwライブラリの初期化を行い,glfwウィンドウを作成し,gl3wの初期化を行う
opengl32.dllと区別するため、Mesa版opengl32.dllはMesaOpengl32.dllに命名されています。MesaOpenGLが利用されると、自動的にopengl32.dllに名前が変更されます。
画像を処理する前に、テクスチャにバインドする必要があります。 テクスチャのバインド処理は、次のように行います。
テクスチャのインデックスを生成する。
テクスチャインデックスがテクスチャオブジェクトにバインドされていない場合、テクスチャインデックスをテクスチャユニットにバインドし、glTexImage2Dを使用して2Dテクスチャを生成してバインドを完了させます。
後続のビデオフレームでは、glTexSubImage2Dを使用して既存のテクスチャを変更します。
ビデオ解像度が変更された場合は、手順2へ戻ります。
process textureインターフェースを使用して、効果をレンダリングする前に入力と出力のテクスチャーをバインドします。
process bufferを使用したエフェクトのレンダリングでは、テクスチャのバインディングは不要で、関数内部で行われます。
この効果はOpenGLでprocess textureインターフェイスまたはprocess bufferインターフェイスを使って、次のように描画されます。他の効果については4.4を参照してください:
プログラムの終了時には、glfw が作成したウィンドウを閉じて、glfwを終了させる必要があります。
inline bool InitGL() {
glfwSetErrorCallback(PrintglfwError);
bool bGLInited = false;
if (!window) {
try {
int err = 0;
#ifdef WIN32
if (opengl_check()) {
#endif
err = glfwInit();
if (!err) {
throw "OpenGL: fail to create window context!";
}
// Create a offscream mode window and its OpenGL context
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
window = glfwCreateWindow(10, 10, "hello", NULL, NULL);
#ifdef WIN32
}
#endif
if (!window) {
#ifdef WIN32
MesaOpenGL();
#else
throw "OpenGL: fail to init glfw";
#endif
}
else {
// Make the window's context current
glfwMakeContextCurrent(window);
#ifdef WIN32
err = gl3wInit();
if (err != GL3W_OK) {
MesaOpenGL();
}
#else
glewExperimental = GL_TRUE;
err = glewInit();
if (err != GLEW_OK) {
throw "OpenGL: fail to init glew\n";
}
#endif
}
const unsigned char* glVer = glGetString(GL_VERSION);
const unsigned char* glslVer = glGetString(GL_SHADING_LANGUAGE_VERSION);
float OpenglVersion = 0.f, GLSLVersion = 0.f;
StringTo((char*)glVer, OpenglVersion);
StringTo((char*)glslVer, GLSLVersion);
fprintf(stdout, "Renderer: %s\n", glGetString(GL_RENDERER));
fprintf(stdout, "OpenGL version supported %s\n", glGetString(GL_VERSION));
fprintf(stdout, "OpenGLSL version supported %s\n",
glGetString(GL_SHADING_LANGUAGE_VERSION));
if (OpenglVersion <2.1f || GLSLVersion < 1.2f) {
throw "OpenGL version is too old, we only support above opengl2.1 and glsl1.2.0";
}
bGLInited = true;
}
catch (std::exception &e){
fprintf(stderr, "%s\n", e.what());
}
catch (const char* e){
fprintf(stderr, "%s\n", e);
}
catch (...) {
return false;
} }
else {
GLFWwindow* curCtx = glfwGetCurrentContext();
if (!curCtx)
glfwMakeContextCurrent(window);
bGLInited = true;
}
return bGLInited;
}
inline void MesaOpenGL() {
unInitGL();
char work_path[_MAX_PATH] = { 0 };
GetModuleFileName(NULL, work_path, _MAX_PATH);
std::string str_work_path(work_path);
str_work_path = str_work_path.substr(0, str_work_path.find_last_of('\\') + 1);
#ifdef _WIN64
str_work_path = str_work_path + "..\\external\\libs\\windows-x86_64";
#else
str_work_path = str_work_path + "..\\external\\libs\\windows-x86";
#endif
SetDllDirectory(str_work_path.data());
std::string rename_path = str_work_path + "\\MesaOpengl32.dll";
str_work_path = str_work_path + "\\opengl32.dll";
// judge opengl32.dll exist or not
if (access(str_work_path.data(), 0) == -1) {
// rename and SetDllDirectory are must, because glfw loadlibrary("opengl32.dll")
if (rename(rename_path.data(), str_work_path.data()) != 0)
throw "MESA OpenGL: fail to rename opengl32.dll!";
}
GLenum err = false;
err = glfwInit();
if (!err) {
throw "MESA OpenGL: fail to init glfw";
}
// Create a offscream mode window and its OpenGL context
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
window = glfwCreateWindow(10, 10, "hello", NULL, NULL);
if (!window) {
unInitGL();
throw "MESA OpenGL: fail to create window context!";
}
// Make the window's context current
glfwMakeContextCurrent(window);
//str_work_path = str_work_path + "\\opengl32.dll";
err = gl3wInitWithPath(str_work_path.data());
if (err != GL3W_OK) {
fprintf(stderr, "gl3wInit error: %d\n", err);
throw "MESA OpenGL: fail to init gl3w\n";
}
}
static GLboolean BindTexture(uchar *buffer, int width, int height, GLuint& texId) {
if (!glIsTexture(texId) || (gTextures.find(texId) == gTextures.end())) {
glGenTextures(1, &texId);
std::vector<int> tmp(2);
tmp[0] = width;
tmp[1] = height;
gTextures[texId] = tmp;
}
int &OldW = gTextures[texId][0];
int &OldH = gTextures[texId][1];
if (!glIsTexture(texId) || (OldW != width) || (OldH != height)) {
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texId);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA,
GL_UNSIGNED_BYTE, buffer);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
OldW = width;
OldH = height;
}
else if(buffer) {
glBindTexture(GL_TEXTURE_2D, texId);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA,
GL_UNSIGNED_BYTE, buffer);
}
bool tmp = glIsTexture(texId);
GLenum error = glGetError();
if (error != GL_NO_ERROR) {
printf("error : %d\n", error);
// result = RESULT_TEXTURE_ERR;
error = GL_NO_ERROR;
return false;
}
return true;
}
BindTexture(rgba_frame.data, rgba_frame.cols, rgba_frame.rows, texture_src);
BindTexture(NULL, rgba_frame.cols, rgba_frame.rows, texture_dst);//process_texture
ret = st_mobile_beautify_process_and_output_texture(handle_beautify, texture_src,
read_frame.cols, read_frame.rows,
ST_CLOCKWISE_ROTATE_0,
&human_action,texture_dst,
temp_frame.data,ST_PIX_FMT_BGR888,
NULL);
//process_buffer
ret = st_mobile_beautify_process_buffer(handle_beautify, temp_frame.data,
ST_PIX_FMT_BGR888, temp_frame.cols,
temp_frame.rows, temp_frame.step,
ST_CLOCKWISE_ROTATE_0, &human_action,
temp_frame.data, ST_PIX_FMT_BGR888, NULL);inline void unInitGL() {
if (window)
glfwDestroyWindow(window);
window = nullptr;
glfwTerminate();
}一部重要なファイルの内容を説明します。
画像の形式やエラーコードなどを定義するファイルです。それに関するメソッドも含まれます。
ライセンス認証関連メソッドが含まれます。
st_mobile_human_actionのAPI関連設定が含まれます。
st_mobile_face_attributeのAPI関連設定が含まれます。
st_mobile_beautifyのAPI関連設定が含まれます。
st_mobile_stickerのAPI関連設定が含まれます。
st_mobile_filter(顔のフィルター)のAPI関連設定が含まれます。
st_mobile_object(物体識別)のAPI関連設定が含まれます。
st_mobile_makeup(メークアップ)のAPI関連設定が含まれます。
st_mobile_animal(猫顔の識別)のAPI関連設定が含まれます。
st_mobile_body_beautify(体型の美化)のAPI関連設定が含まれます。
st_mobile_avatar(アバターの設定)のAPI関連設定が含まれます。
//// @brief Blink動作の閾値設定。[0,1]の範囲内で設定可能であり,デフォルト設定値は0.5である
ST_SDK_API void
st_mobile_set_eyeblink_threshold(
float threshold
);
/// @brief 口開ける動作の閾値設定。[0,1]の範囲内で設定可能であり,デフォルト設定値は0.5である
ST_SDK_API void
st_mobile_set_mouthah_threshold(
float threshold
);
/// @brief 頭振る動作の閾値設定。[0,1]の範囲内で設定可能であり,デフォルト設定値は0.5である
ST_SDK_API void
st_mobile_set_headyaw_threshold(
float threshold
);
/// @brief 頷く動作の閾値設定。[0,1]の範囲内で設定可能であり,デフォルト設定値は0.5である
ST_SDK_API void
st_mobile_set_headpitch_threshold(
float threshold
);
/// @brief 眉毛動く動作の閾値設定。[0,1]の範囲内で設定可能であり,デフォルト設定値は0.5である
ST_SDK_API void
st_mobile_set_browjump_threshold(
float threshold
);
/// @brief 顔識別のスムーズさを設定する。デフォルトは0.8である
ST_SDK_API void
st_mobile_set_smooth_threshold(
float threshold
);
/// @brief 顔識別の3D回転角度を設定する。デフォルトは0.8である
ST_SDK_API void
st_mobile_set_headpose_threshold(
float threshold
);
/// @brief SSE命令集のみ利用可能の設定
ST_SDK_API void st_mobile_set_sse_only(
bool sse_only
);
/// @brief 画像色の転換
ST_SDK_API st_result_t
st_mobile_color_convert(
const unsigned char *image_src,
unsigned char *image_dst,
int image_width,
int image_height,
st_color_convert_type type
);
/// @brief 画像の回転
ST_SDK_API st_result_t st_mobile_image_rotate(
const unsigned char *image_src,
unsigned char *image_dst,
int image_width,
int image_height,
int image_stride,
st_pixel_format pixel_format,
st_rotate_type rotate_type
);
/// @brief st_mobileのカレントログレベルを設定
/// ST_LOG_DISABLEで設定した場合はログを禁止する
///
@param[in] level ログレベルを設定する
///
@return 正常の場合はST_OKで返す、異常の場合はエラーで返す
ST_SDK_API st_result_t
st_mobile_set_log_level(
st_log_level_t level
);
/// @brief ログのレベルを取得する
/// @param[out] p_level カレントログレベルの結果
/// @return 正常の場合はST_OKで返す、異常の場合はエラーで返す
ST_SDK_API st_result_t
st_mobile_get_log_level(
st_log_level_t* p_level
);
/// @brief ログパスを設定する
/// @param[in] p_file_path ログファイルのパスを設定する
/// @param[in] b_tranc_file ファイル内容削除可否,true - 削除可,false - 削除不可
/// @return 正常の場合はST_OKで返す、異常の場合はエラーで返す
ST_SDK_API st_result_t
st_mobile_redirect_log_to_file(
const char* p_file_path, bool b_tranc_file
);
/// @brief sdkバージョンを取得する
ST_SDK_API
const char* st_mobile_get_version(); /// @brief ライセンスファイルからアクティベーションコードを生成し、新しいライセンスファイルを使用する際に使用します。Androidでは、以下の使用を推奨しています。st_mobile_generate_activecode_from_buffer
ST_SDK_API
st_result_t
st_mobile_generate_activecode(
const char* license_path,
char* activation_code,
int* activation_code_len
);
/// @brief アクティベーションコードを確認するためには、すべてのインターフェースの前に呼び出す必要があります。Androidにおすすめです。
st_mobile_check_activecode_from_buffer
ST_SDK_API
st_result_t
st_mobile_check_activecode(
const char* license_path,
const char* activation_code,
int activation_code_len
);
/// @brief ライセンスファイルキャッシュからアクティベーションコードを生成し、新しいライセンスファイルを使用する際に呼び出される
ST_SDK_API st_result_t st_mobile_generate_activecode_from_buffer(
const char* license_buf,
int license_size,
char* activation_code,
int* activation_code_len
);
/// @brief アクティベーションコードのチェック、すべてのインターフェースの前に呼び出される必要があります。
ST_SDK_API st_result_t st_mobile_check_activecode_from_buffer(
const char* license_buf,
int license_size,
const char* activation_code,
int activation_code_len
);
/// @brief ライセンスファイルからオンラインでアクティベーションコードを生成、オンラインライセンスとインターネットアクセスが必要です
ST_SDK_API st_result_t st_mobile_generate_activecode_online(
const char* license_path,
char* activation_code,
int* activation_code_len
);
/// @brief ライセンスファイルバッファからオンラインでアクティベーションコードを生成、オンラインライセンスとインターネットアクセスが必要です。
ST_SDK_API st_result_t st_mobile_generate_activecode_from_buffer_online(
const char* license_buf,
int license_size,
char* activation_code,
int* activation_code_len
);/// @brief 人間行動探知機のハンドルを作成する。Androidではst_mobile_human_action_create_from_buffer ST_SDK_API st_result_t
st_mobile_human_action_create(
const char *model_path,
unsigned int config,
st_handle_t *handle
);
/// @brief サブモデルの追加 Androidではst_mobile_human_action_add_sub_model_from_buffer ST_SDK_API st_result_t
st_mobile_human_action_add_sub_model(
st_handle_t handle,
const char *model_path
);
/// @brief 人間行動探知機のハンドルを解除する ST_SDK_API
void st_mobile_human_action_destroy(
st_handle_t handle
);
/// @brief 人体行動検知 ST_SDK_API st_result_t st_mobile_human_action_detect(
st_handle_t handle,
const unsigned char *image,
st_pixel_format pixel_format,
int image_width,
int image_height,
int image_stride,
st_rotate_type orientation,
unsigned long long detect_config,
st_mobile_human_action_t *p_human_action
);
/// @brief Human_Actionの検出結果のミラーリング。フレーム間検出では、結果をコピーしてミラーリングします ST_SDK_API void
st_mobile_human_action_mirror(
int image_width,
st_mobile_human_action_t *p_human_action
);
/// @brief human_actionの検出結果を回転させる。ST_SDK_API void st_mobile_human_action_rotate(
int image_width,
int image_height,
st_rotate_type orientation,
bool b_rotate_image,
st_mobile_human_action_t* p_human_action
);/// @brief 顔属性検出ハンドルの作成 ST_SDK_API st_result_t st_mobile_face_attribute_create(
const char *model_path,
st_handle_t *handle
);
/// @brief 初期化された顔属性検出ハンドルを破棄する ST_SDK_API void st_mobile_face_attribute_destroy(
st_handle_t handle
);
ST_SDK_API st_result_t
st_mobile_face_attribute_detect_ext2(
st_handle_t handle,
const unsigned char *image,
st_pixel_format pixel_format,
int image_width,
int image_height,
int image_stride,
const st_mobile_face_t *p_face_array,
int face_count,
float** p_attribute_array
);/// @brief 美化ハンドル作成 ST_SDK_API st_result_t st_mobile_beautify_create(
st_handle_t *handle
);
/// @brief 美化パラメータを設定、デフォルトですべての機能パラメータと強度パラメータが含まれている ST_SDK_API st_result_t st_mobile_beautify_setparam(
st_handle_t handle,
st_beautify_type type,
float value
);
/// @brief 画像バッファを美化するためには、OpenGL環境下で呼び出す必要があります。 ST_SDK_API st_result_t st_mobile_beautify_process_buffer(
st_handle_t handle,
const unsigned char *img_in, st_pixel_format fmt_in,
int image_width, int image_height, int image_stride,
st_rotate_type rotate,
const st_mobile_human_action_t* p_human,
unsigned char *img_out, st_pixel_format fmt_out,
st_mobile_human_action_t* p_human_out
);
/// @brief このインターフェースは,OpenGL環境で関数を実行しないユーザーを対象としており,内部で環境を初期化し,速度が遅く,単一の画像にしか適していない ST_SDK_API st_result_t
st_mobile_beautify_process_picture(
st_handle_t handle,
const unsigned char *img_in, st_pixel_format fmt_in,
int image_width, int image_height, int image_stride,
st_rotate_type rotate,
const st_mobile_human_action_t* p_human,
unsigned char *img_out, st_pixel_format fmt_out,
st_mobile_human_action_t* p_human_out
);
/// @brief OpenGLにおけるテクスチャの装飾 ST_SDK_API st_result_t st_mobile_beautify_process_texture(
st_handle_t handle,
unsigned int textureid_src,
int image_width, int image_height,
st_rotate_type rotate,
const st_mobile_human_action_t* p_human,
unsigned int textureid_dst,
st_mobile_human_action_t* p_human_out
);
/// @brief OpenGLのテクスチャを美化し、出力テクスチャをバッファ出力に変換する ST_SDK_API st_result_t st_mobile_beautify_process_and_output_texture(
st_handle_t handle,
unsigned int textureid_src,
int image_width, int image_height,
st_rotate_type rotate,
const st_mobile_human_action_t* p_human,
unsigned int textureid_dst,
unsigned char *img_out, st_pixel_format fmt_out,
st_mobile_human_action_t* p_human_out
);
/// @brief 美化ハンドルを解除する。OpenGLスレッドで呼び出す必要があります ST_SDK_API void st_mobile_beautify_destroy(
st_handle_t handle
);/// @brief ステッカーハンドルを作成 ST_SDK_API st_result_t st_mobile_sticker_create(
st_handle_t* handle
);
/// @brief パッケージの置き換え(既存パッケージの削除) ST_SDK_API st_result_t st_mobile_sticker_change_package(
st_handle_t handle,
const char* zip_path,
int* package_id
);
/// @brief トリガーアクションの種類を取得します。 現在、表示する必要がある ST_SDK_API st_result_t st_mobile_sticker_get_trigger_action(
st_handle_t handle,
unsigned long long *action
);
/// @brief OpenGLESでのテクスチャのデカップリングとバッファリング、openglでの実行が必要、RGBAイメージのみサポート texture
ST_SDK_API st_result_t
st_mobile_sticker_process_and_output_texture(
st_handle_t handle,
unsigned int textureid_src, int image_width, int image_height,
st_rotate_type rotate, st_rotate_type frontRotate, bool need_mirror,
st_mobile_human_action_t* human_action,
st_mobile_input_params_t* input_params,
unsigned int textureid_dst,
unsigned char* img_out, st_pixel_format fmt_out
);
/// @brief OpenGLスレッドで呼び出される必要がありますST_SDK_API void
st_mobile_sticker_destroy(
st_handle_t handle
);/// cpu filter インターフェース /// @brief フィルタハンドルの作成 ST_SDK_API st_result_t st_mobile_filter_create(
st_handle_t *handle
);
/// @brief フィルタースタイルを設定する ST_SDK_API st_result_t
st_mobile_filter_set_style(
st_handle_t handle,
const char* style_model_path
);
/// @brief フィルターパラメーターの設定 ST_SDK_API st_result_t st_mobile_filter_set_param(
st_handle_t handle,
st_filter_type type,
float value
);
/// @brief 画像のフィルタリング ST_SDK_API st_result_t st_mobile_filter_process(
st_handle_t handle,
unsigned char *img_in, st_pixel_format fmt_in, int image_width, int image_height, int
image_stride,
unsigned char *img_out, st_pixel_format fmt_out
);
/// @brief フィルターハンドルを離す ST_SDK_API void st_mobile_filter_destroy(
st_handle_t handle
);
/// gpu filter interface, glスレッドで実行する必要があります。
/// @brief OpenGLフィルタハンドルの作成 ST_SDK_API st_result_t st_mobile_gl_filter_create( st_handle_t *handle)
);
/// ST_SDK_API st_result_t st_mobile_gl_filter_set_style( st_handle_t handle.handle.handle)を呼び出す必要があります。
const char* style_model_path
);
/// @brief フィルターパラメーターの設定 ST_SDK_API st_result_t st_mobile_gl_filter_set_param( st_handle_t handle.St_gl_filter_type type),
st_gl_filter_type type,
フロート値
);
/// OpenGLでのテクスチャのフィルタリング、OpenGLスレッドで呼び出す必要がある ST_SDK_API st_result_t st_mobile_gl_filter_process_texture(
st_handle_t handle,
unsigned int textureid_src,
int image_width, int image_height,
unsigned int textureid_dst
); /// @brief OpenGLでテクスチャにフィルタ処理を施し、バッフルを出力します。 OpenGLスレッドで呼び出す必要があります。
ST_SDK_API st_result_t
St_mobile_gl_filter_process_texture_and_output_buffer(
st_handle_t handle,
unsigned int textureid_src,
int image_width, int image_height,
unsigned int textureid_dst,
unsigned char *img_out, st_pixel_format fmt_out
); /// @brief 画像バッファのフィルタリング、OpenGLスレッドで呼び出す必要があります。 ST_SDK_API st_result_t st_mobile_gl_filter_process_buffer(
st_handle_t handle,
const unsigned char *img_in, st_pixel_format fmt_in, int image_width, int image_height,
int image_stride,
unsigned char *img_out, st_pixel_format fmt_out
);
/// @brief OpenGLフィルターハンドルを解放するために、OpenGLスレッドでST_SDK_APIを呼び出す必要があります。 void st_mobile_gl_filter_destroy( ).
st_handle_t handle
);
/// @brief 汎用オブジェクト追跡ハンドルの作成
ST_SDK_API
st_result_t st_mobile_object_tracker_create(
st_handle_t* handle
);
/// @brief 連続したビデオフレーム内のターゲットをリアルタイムで高速追跡します。
ST_SDK_API st_result_t
st_mobile_object_tracker_track(
st_handle_t handle,
const unsigned char *image,
st_pixel_format pixel_format,
int image_width,
int image_height,
int image_stride,
st_rect_t *rects,
float *score
);
/// @brief 初期化された汎用オブジェクトトラッキングハンドルを破棄する
ST_SDK_API void
st_mobile_object_tracker_destroy(
st_handle_t handle
);/// @brief ビューティハンドル作成 ST_SDK_API st_result_t st_mobile_makeup_create(
st_handle_t* handle
);
/// @brief パッケージの置き換え(既存パッケージの削除) ST_SDK_API st_result_t st_mobile_makeup_set_makeup_for_type(
st_handle_t handle,
st_makeup_type makeup_type,
const char* zip_path,
int* package_id
);
/// @brief OpenGLESでテクスチャのビューティー処理を行い、バッファに出力するには、opengl環境で実行する必要があり、RGBA画像フォーマットのみをサポートしています texture
ST_SDK_API st_result_t
st_mobile_makeup_process_and_output_texture(
st_handle_t handle,
unsigned int textureid_src, int image_width, int image_height,
st_rotate_type rotate,
st_mobile_human_action_t* human_action,
unsigned int textureid_dst,
unsigned char* img_out, st_pixel_format fmt_out
);
/// @brief 指定した種類の美しさの強さを調整する ST_SDK_API void st_mobile_makeup_set_strength_for_type(
st_handle_t handle,
st_makeup_type makeup_type,
float value
);
/// @brief 指定された種類のピールの強度を調整します。 ST_SDK_API void st_mobile_makeup_set_smooth_strength(
st_handle_t handle,
st_makeup_type makeup_type,
float value
);
/// @brief 美のハンドルを解放する、OpenGLスレッドで呼び出されなければならない ST_SDK_API void
st_mobile_makeup_destroy(
st_handle_t handle
);
/// @brief 猫の顔のキーポイントをリアルタイムで追跡するハンドルの作成
ST_SDK_API
st_result_t st_mobile_tracker_animal_face_create(
const char *model_path,
unsigned int config,
st_handle_t *handle
);
/// @brief 連続したビデオフレームに対するリアルタイム高速猫顔キーポイントトラッキング
ST_SDK_API st_result_t
st_mobile_tracker_animal_face_track(
st_handle_t handle,
const unsigned char *image,
st_pixel_format pixel_format,
int image_width,
int image_height,
int image_stride,
st_rotate_type orientation,
st_mobile_animal_face_t **p_faces_array,
int *p_faces_count
);
/// @brief 初期化された猫の顔追跡ハンドルを破棄する
ST_SDK_API void st_mobile_tracker_animal_face_destroy(
st_handle_t handle
);
/// @brief 本体ハンドルを作成します。Androidでは
st_mobile_body_beautify_create_from_buffer
ST_SDK_API st_result_t
st_mobile_body_beautify_create(
st_handle_t *handle,
unsigned int config,
const char *model_path
);
/// @brief 既存のボディハンドルからボディハンドルを作成する
ST_SDK_API st_result_t
st_mobile_body_beautify_create_from_handle(
st_handle_t *handle,
st_handle_t handle_src,
unsigned int config
);
/// @brief 画像バッファは綺麗に処理されているので、OpenGL環境で呼び出す必要があります。
ST_SDK_API st_result_t
st_mobile_body_beautify_process_buffer(
st_handle_t handle,
const unsigned char *image_in,
st_pixel_format format_in,
int image_width,
int image_height,
int image_stride,
st_rotate_type rotate,
st_rect_t* process_region,
unsigned char *image_out,
st_pixel_format format_out,
st_body_beautify_result *p_result
);
/// @brief OpenGLテクスチャに対して美的処理を行うには、OpenGL環境内から呼び出す必要があります。image_in と texture_src の画像は同じである必要があります。
ST_SDK_API st_result_t
st_mobile_body_beautify_process_texture(
st_handle_t handle,
unsigned int texture_src,
const unsigned char *image_in,
st_pixel_format format_in,
int image_width,
int image_height,
int image_stride,
st_rotate_type rotate,
st_rect_t* process_region,
unsigned int texture_dst,
unsigned char *image_out,
st_pixel_format format_out,
st_body_beautify_result *p_result
);
/// @brief ボディワークのパラメータを設定する
ST_SDK_API st_result_t
st_mobile_body_beautify_set_param(
st_handle_t handle,
st_body_beautify_param_type type,
float value
);
/// @brief US本体のハンドルを離す。呼び出されない場合st_mobile_body_beautify_gl_release, OpenGLスレッドで呼び出される必要がある
ST_SDK_API void
st_mobile_body_beautify_destroy(
st_handle_t handle
);
/// @brief アバターハンドルの作成、ノンスレッドセーフ
ST_SDK_API st_result_t st_mobile_avatar_create(
st_handle_t *p_handle,
const char* p_model_file_path
);
/// @brief アバターハンドルの破壊、非スレッドセーフ
ST_SDK_API void st_mobile_avatar_destroy(
st_handle_t handle
);
/// @brief Avatarに必要な検出設定を取得する(非スレッドセーフ)
ST_SDK_API unsigned long long st_mobile_avatar_get_detect_config(
st_handle_t handle
);
/// @brief 入力されたキーポイントに Avatar の表現係数を当てはめた結果を取得します(ノンスレッドセーフ)
ST_SDK_API st_result_t
st_mobile_avatar_get_expression(
st_handle_t handle,
int width, int height,
st_rotate_type rotate,
const st_mobile_face_t* p_face,
float* p_expression_array
); 1.HumanAction の初期化
2.顔属性 API ハンドルの初期化
3.美化 API ハンドルの初期化
4.スタンプ API ハンドルの初期化
5.フィルター API ハンドルの初期化
6.一般的なオブジェクト API ハンドルの初期化
SDK ハンドルの初期化が終了しました。詳細については、公式のデモをご参照ください。 注記: 本 SDK は、オブジェクトの美化およびフィルター化の統一されたコンテキスト内にある必要があります。次のように設定します。
注記: コンテキストが異なると、エラーが発生する可能性があるため、OpenGL コンテキストが同じであることを確認してください。
1.STCamera の使用
STCamera: iOS システムに合わせたカメラ用 SenseTime パッケージ。解像度や出力フォーマットなど、多数のパラメーターを簡単に設定できます。詳細については、STCamera.h ファイルをご参照ください。
2.STCamera からテクスチャを取得
1.HumanAction API の使用
回転角度: 写真を撮り、携帯電話に対して回転させて、顔を検知できる方向を確認します。これが顔を検知する際の角度です。詳細については、enum パラメーターをご参照ください。
2.表情 API の使用
表情に関する API は、動作検知の関数の結果を必要とします。したがって、次のように 動作検知の関数の後に呼び出されます。
3.顔属性 API の使用
FaceAttribute API は、HumanAction パラメーターからパラメーターを入力します。したがって、顔属性 API の実行前に、HumanAction パラメーターを設定する必要があります。
4.美化 API の使用
同様に、目の拡大や顎の縮小などの美化 API の関数も、HumanAction に由来します。
detectResult 項目は、人間の動作の検知結果用で、processedResult 項目は目の拡大や顎の縮小などの美化を行った後の顔特徴点用です (processResult 項目は、上位層で手動で割り当てられます。detectResult 項目と同じか、detectResult 項目から取り込まれたものです)。
美化パラメーターの設定:
5.スタンプ API の使用
スタンプには、主に 2D スタンプ、3D スタンプ、顔変形スタンプ、前面と背面の背景スタンプ、ジェスチャスタンプ、音楽スタンプ、メイクスタンプ、パーティクルアニメーションスタンプ、アバタースタンプ、スカイボックススタンプが含まれます。スタンプ機能を実装するには、顔情報が利用可能であることを確認し、事前に HumanAction を実行します。
スタンプのレンダリング
注記:
1.本 API は、前景スタンプの回転角度を追加します。必要に応じて使用できます。
2.スカイボックススタンプを使用するには、カメラのクォータニオンを入力してください。スカイボックスの inputEvent 項目が必要ない場合は、NULL を入力します。
詳細については、サンプルをご参照ください。
スタンプの変更:
アクションをトリガーするスタンプの取得: (st_mobile_sticker_change_package 関数を取得後にのみ、スタンプを取得します。アクションはヘッダーファイルで定義されています。)
6.フィルター API の使用
7.一般的なオブジェクト API の使用
1.GL リソースは、GL スレッドで解放する必要があります。
まとめ: 第 3 章では、本 SDK の API の使用方法に関する概要を説明しました。デモのプレゼンテーションは、SDK のより迅速な統合を促進します。いくつかの考慮すべき点を以下に示します。
1.顔属性の検知、美化、スタンプを使用するには、事前に humanAction を検知する必要があります。
2.美化、スタンプ、フィルターは、OpenGL によりレンダリングされます。そのため、同じ EAGLContext 内にある必要があります。次のように実装します。
//HumanAction ハンドルを初期化します
//モデルのパスを取得します
NSString *strModelPath = [[NSBundle mainBundle]
pathForResource:@"M_SenseME_Action" ofType:@"model"];
//HumanAction ハンドルを作成します
//注記: 本 SDK の API では、2 種類の HumanAction ハンドル作成方法を提供します。
//検知対象がビデオである場合は ST_MOBILE_HUMAN_ACTION_DEFAULT_CONFIG_CREATE
//に設定し、画像である場合は ST_MOBILE_HUMAN_ACTION_DEFAULT_CONFIG_IMAGE に
//設定します。詳細については、st_mobile_human_action.h ファイルをご参照ください。
//ハンドル作成用の config コマンドと、人間の動作を検知するための config コマンドを
//区別するように注意してください。動作を検知するための config コマンドは、config
//コマンドを使用してハンドルを作成できる場合にのみ有効になります。
iRet = st_mobile_human_action_create(
strModelPath.UTF8String,
ST_MOBILE_HUMAN_ACTION_DEFAULT_CONFIG_VIDEO,
&_hDetector
);
//他のモデルをロードして、st_mobile_human_action_add_sub_model を呼び出します
NSString *strEyeCenter = [[NSBundle mainBundle]
pathForResource:@"xx" ofType:@"model"];
iRet = st_mobile_human_action_add_sub_model(
_hDetector,
strEyeCenter.UTF8String
);
//アバタースタンプは、目の輪郭点モデルと専用のアバターモデル (avatar_core.model)
// を一緒に読み込む必要があることに注意してください
//モデルを削除します。必要に応じて、動的にモデルを追加、または削除できます。
//詳細についてはサンプルをご参照ください。
iRet = st_mobile_human_action_remove_model_by_config(
_hDetector,
ST_MOBILE_ENABLE_FACE_EXTRA_DETECT
);
//人間の動作用のパラメーターを設定します。2 フレームごとに 1 回ジェスチャを検知するよう
//に設定しています。必要に応じて設定できます。
//他のパラメーターに関しては、st_mobile_human_action.h ファイルをご参照ください。
iRet = st_mobile_human_action_setparam(
_hDetector,
ST_HUMAN_ACTION_PARAM_HAND_PROCESS_INTERVAL,
2
);//顔属性ハンドルを初期化します
//顔属性モデルのパスを取得します
NSString *strAttriModelPath = [[NSBundle mainBundle]
pathForResource:@"face_attribute" ofType:@"model"];
//顔属性ハンドルを作成します
iRet = st_mobile_face_attribute_create(
strAttriModelPath.UTF8String,
&_hAttribute
);iRet = st_mobile_beautify_create(&_hBeautify);
//美化 API ハンドルを作成後、関連するパラメーターを設定できます
//美白の強度を設定します。値の範囲: [0, 1.0]、デフォルト値: 0.02
//美白を適用しない場合は 0.0。
st_mobile_beautify_setparam(
_hBeautify,
ST_BEAUTIFY_WHITEN_STRENGTH,
self.fWhitenStrength
);
//デフォルトの赤みの強度を設定します。値の範囲: [0, 1.0]、デフォルト値: 0.36
//赤みなしの場合は 0.0。
st_mobile_beautify_setparam(
_hBeautify,
ST_BEAUTIFY_REDDEN_STRENGTH,
self.fReddenStrength
);
//デフォルトの肌補正の強度を設定します。値の範囲: [0, 1.0]、デフォルト値: 0.74
//補正しない場合は 0.0。
st_mobile_beautify_setparam(
_hBeautify,
ST_BEAUTIFY_SMOOTH_STRENGTH,
self.fSmoothStrength
);
//ハイライト除去の強度: [0, 1.0]、デフォルト値: 1、除去しない場合は 0.0。
st_mobile_beautify_setparam(
_hBeautify,
ST_BEAUTIFY_DEHIGHLIGHT_STRENGTH,
self.fDehighlightStrength
);
//デフォルトの目の拡大強度を設定します。値の範囲: [0, 1.0]、デフォルト値: 0.13
//拡大しない場合は 0.0。
st_mobile_beautify_setparam(
_hBeautify,
ST_BEAUTIFY_ENLARGE_EYE_RATIO,
self.fEnlargeEyeStrength
);
//顔の縮小強度を設定します。値の範囲: [0, 1.0]、デフォルト値: 0.11
//縮小しない場合は 0.0。
st_mobile_beautify_setparam(
_hBeautify,
ST_BEAUTIFY_SHRINK_FACE_RATIO,
self.fShrinkFaceStrength
);
//顎の縮小強度を設定します。値の範囲: [0, 1.0]、デフォルト値: 0.10
//縮小しない場合は 0.0。
st_mobile_beautify_setparam(
_hBeautify,
ST_BEAUTIFY_SHRINK_JAW_RATIO,
self.fShrinkJawStrength
);
//顔の幅を狭める割合を設定します。値の範囲: [0, 1.0]、デフォルト値: 0.0
//狭めない場合は 0.0。
st_mobile_beautify_setparam(
_hBeautify,
ST_BEAUTIFY_NARROW_FACE_RATIO,
self.fShrinkJawStrength
);
///SDK の新しい 3D 美化機能パラメータの設定は以下のとおりです
///鼻を狭める割合: [0, 1.0]、デフォルト値: 0.0、狭めない場合は 0.0
st_mobile_beautify_setparam(
_hBeautify,
ST_BEAUTIFY_NARROW_NOSE_RATIO,
self.fNarrowNoseStrength
);
///鼻の長さの割合: [-1, 1]、デフォルト値: 0.0
//短くする場合は [-1, 0] で長くする場合は [0, 1]
st_mobile_beautify_setparam(
_hBeautify,
ST_BEAUTIFY_LENGTH_NOSE_RATIO,
self.fLongNoseStrength
);
///顎の長さの割合: [-1, 1]、デフォルト値: 0.0
//短くする場合は [-1, 0] で長くする場合は [0, 1]
st_mobile_beautify_setparam(
_hBeautify,
ST_BEAUTIFY_LENGTH_CHIN_RATIO,
self.fChinStrength
);
///口の大きさの割合: [-1, 1]、デフォルト値: 0.0
//拡大する場合は [-1, 0] で縮小する場合は [0, 1]
st_mobile_beautify_setparam(
_hBeautify,
ST_BEAUTIFY_SIZE_MOUTH_RATIO,
self.fMouthStrength
);
///人中の長さの割合: [-1, 1]、デフォルト値: 0.0
//長くする場合は [-1, 0] で短くする場合は [0, 1]
st_mobile_beautify_setparam(
_hBeautify,
ST_BEAUTIFY_LENGTH_PHILTRUM_RATIO,
self.fPhiltrumStrength
);
///生え際の高さの割合: [-1, 1]、デフォルト値: 0.0
//低くする場合は [-1, 0] で高くする場合は [0, 1]
st_mobile_beautify_setparam(
_hBeautify,
ST_BEAUTIFY_LOW_HAIRLINE_RATIO,
self.fHairLineStrength
);
//コントラストを設定します。値の範囲: [0, 1.0]、デフォルト値: 0.0。
iRet = st_mobile_beautify_setparam(
_hBeautify,
ST_BEAUTIFY_CONTRAST_STRENGTH,
self.fContrastStrength
);
//彩度を設定します。値の範囲: [0, 1.0]、デフォルト値: 0.0。
iRet = st_mobile_beautify_setparam(
_hBeautify,
ST_BEAUTIFY_SATURATION_STRENGTH,
self.fSaturationStrength
);
//シャープネスパラメーター
iRet = st_mobile_beautify_setparam(
_hBeautify,
ST_BEAUTIFY_SHARPEN_STRENGTH,
self.fSharpenStrength
);
//SDK の美化機能パラメーターは以下のように設定できます
//ボディの美化パラメーターを設定します。値の範囲: [0, + ∞)
//デフォルト値: 1.0 (美化を行わない)。
iRet = st_mobile_beautify_setparam(
_hBeautify,
ST_BEAUTIFY_BODY_WHOLE_RATIO,
self.fBeautifyBodyRatio
);
//頭の美化パラメーターを設定します。値の範囲: [0, + ∞)
//デフォルト値: 1.0 (美化を行わない)。
iRet = st_mobile_beautify_setparam(
_hBeautify,
ST_BEAUTIFY_BODY_HEAD_RATIO,
self.fBeautifyHeadRatio
);
//肩の美化パラメーターを設定します。値の範囲: [0, + ∞)
//デフォルト値: 1.0 (美化を行わない)。
iRet = st_mobile_beautify_setparam(
_hBeautify,
ST_BEAUTIFY_BODY_SHOULDER_RATIO,
self.fBeautifyShouldersRatio
);
//ウエストの美化パラメーターを設定します。値の範囲: [0, + ∞)
//デフォルト値: 1.0 (美化を行わない)。
iRet = st_mobile_beautify_setparam(
_hBeautify,
ST_BEAUTIFY_BODY_WAIST_RATIO,
self.fBeautifyWaistRatio
);
//腰の美化パラメーターを設定します。値の範囲: [0, + ∞)
//デフォルト値: 1.0 (美化を行わない)。
iRet = st_mobile_beautify_setparam(
_hBeautify,
ST_BEAUTIFY_BODY_HIP_RATIO,
self.fBeautifyHipsRatio
);
//足の美化パラメーターを設定します。値の範囲: [0, + ∞)
//デフォルト値: 1.0 (美化を行わない)。
iRet = st_mobile_beautify_setparam(
_hBeautify,
ST_BEAUTIFY_BODY_LEG_RATIO,
self.fBeautifyLegsRatio
);//スタンプハンドルを初期化します
iRet = st_mobile_sticker_create(&_hSticker);
//素材の読み込みを待つかどうかを指定します。
//フレームや 3D ショートビデオなどのモデルが、
//読み込みおよびレンダリングされるのを待つ場合に使用します。
//初期化後、ハンドルを呼び出します。このメソッドは、
//サンプルの画像を処理するために使用されています。
iRet = st_mobile_sticker_set_param_bool(
_hSticker,
-1,
ST_STICKER_PARAM_WAIT_MATERIAL_LOADED_BOOL,
true
);
//音楽スタンプを使用するには、コールバックを設定します
st_mobile_sticker_set_param_ptr(
_hSticker,
-1,
ST_STICKER_PARAM_SOUND_LOAD_FUNC_PTR,
load_sound
);
st_mobile_sticker_set_param_ptr(
_hSticker,
-1,
ST_STICKER_PARAM_SOUND_PLAY_FUNC_PTR,
play_sound
);
st_mobile_sticker_set_param_ptr(
_hSticker,
-1,
ST_STICKER_PARAM_SOUND_STOP_FUNC_PTR,
stop_sound
);
//音楽を読み込みます
void load_sound(void* sound, const char* sound_name, int length) {
if ([messageManager.delegate respondsToSelector:@selector(loadSound:name:)]) {
NSData *soundData = [NSData dataWithBytes:sound length:length];
NSString *strName = [NSString stringWithUTF8String:sound_name];
[messageManager.delegate loadSound:soundData name:strName];
}
}
//音楽を再生します
void play_sound(const char* sound_name, int loop) {
if ([messageManager.delegate respondsToSelector:@selector(playSound:loop:)]) {
NSString *strName = [NSString stringWithUTF8String:sound_name];
[messageManager.delegate playSound:strName loop:loop];
}
}
//再生を停止します
void stop_sound(const char* sound_name) {
if ([messageManager.delegate respondsToSelector:@selector(stopSound:)]) {
NSString *strName = [NSString stringWithUTF8String:sound_name];
[messageManager.delegate stopSound:strName];
}
}//フィルターハンドルを初期化します
iRet = st_mobile_gl_filter_create(&_hFilter);//スタンプハンドルを初期化します
st_result_t iRet = st_mobile_object_tracker_create(&_hTracker);if ([EAGLContext currentContext] != self.glContext) {
[EAGLContext setCurrentContext:self.glContext];
}self.stCamera = [[STCamera alloc]
initWithDevicePosition:AVCaptureDevicePositionFront //フロントまたはリアポジション
sessionPresset:self.currentSessionPreset //解像度
fps:30 //フレームレート
needYuvOutput:NO]; //出力データ形式
self.stCamera.delegate = self; //カメラデータのプロキシを設定します//STCameraDelegate からフレームデータを取得し、テクスチャに変換します
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection
{
//フレームごとに画像データを取得します
CVPixelBufferRef pixelBuffer = (CVPixelBufferRef)CMSampleBufferGetImageBuffer(sampleBuffer);
//フレームのデータをロックします
CVPixelBufferLockBaseAddress(pixelBuffer, 0);
//ビデオデータのアドレスを取得します
unsigined char* pBGRAImageIn = (unsingned char *)CVPixelBufferGetBaseAddress(pixelBuffer);
//ビデオデータの幅と高さを取得します
int iBytesPerRow = (int)CVPixelBufferGetBytesPerRow(pixelBuffer);
int iWidth = (int)CVPixelBufferGetWidth(pixelBuffer);
int iHeight = (int)CVPixelBufferGetHeight(pixelBuffer);
//pixelBuffer とテクスチャを関連付けます
CVReturn cvRet = CVOpenGLESTextureCacheCreateTextureFromImage(kCFAllocatorDefault,
_cvTextureCache,//テクスチャのキャッシュ
pixelBuffer,//出力ビデオデータバッファーは NULL
GL_TEXTURE_2D,//2D テクスチャ
GL_RGBA,//色の形式
self.imageWidth,//画像の幅
self.imageHeight,//画像の高さ
GL_BGRA,//iOS 形式
GL_UNSIGNED_BYTE,
0,
&_cvTextureOrigin//出力するテクスチャ
);
if (!_cvTextureOrigin || kCVReturnSuccess != cvRet) {
NSLog(@"CVOpenGLESTextureCacheCreateTextureFromImage %d" , cvRet);
return NO;
}
//テクスチャを取得します
_textureOriginInput = CVOpenGLESTextureGetName(_cvTextureOrigin);
//テクスチャをバインドします
glBindTexture(GL_TEXTURE_2D , _textureOriginInput);
//テクスチャフィルター機能は、テクスチャ画像領域からフレームバッファー画像領域に画像をマッピングします (画像をマッピングするには、テクスチャ画像を再構築し、ポリゴンに適用された画像を変形します)。テクスチャピクセルをピクセルにマッピングする方法を指定するには、glTexParmeteri() 関数を有効にします。
//GL_TEXTURE_2D: 2D テクスチャの処理
//GL_TEXTURE_MIN_FILTER: 縮小およびフィルター
//GL_TEXUTRE_MAG_FILTER: 拡大およびフィルター
//GL_TEXTURE_WRAP_S: S 方向でのスタンプモード。テクスチャ座標は st、物理座標は xy。
//GL_TEXTURE_WRAP_T: T 方向でのスタンプモード
//GL_CLAMP_TO_EDGE: テクスチャ座標の値の範囲は [0,1] です。特定の方向の値が 0 未満の場合は、0 に設定します。値が 1 より大きい場合は、1 に設定します。
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);//2D テクスチャを縮小およびフィルターし、真ん中のテクスチャに最も近い 4 つのテクスチャ要素の加重平均を返します。
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);//2D テクスチャを拡大およびフィルターし、真ん中のテクスチャに最も近い 4 つのテクスチャ要素の加重平均を返します。
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);//2D テクスチャを S 方向でフィルターします。テクスチャ座標の値の範囲は [0,1] です。S 方向の値が 0 未満の場合は、0 に設定します。値が 1 より大きい場合は、1 に設定します。
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);//2D テクスチャを T 方向でフィルタリングします。テクスチャ座標の値の範囲は [0,1] です。T 方向の値が 0 未満の場合は、0 に設定します。値が 1 より大きい場合は、1 に設定します。
glBindTexture(GL_TEXTURE_2D, 0);//デフォルトのテクスチャをバインドし、以前にバインドされたテクスチャを無効にします。
};//テクスチャを初期化します
- (void)initResultTexture
{
//美化のためのテクスチャを作成します
[self setupTextureWithPixelBuffer:&_cvBeautifyBuffer w:self.imageWidth h:self.imageHeight glTexture:&_textureBeautifyOutput cvTexture:&_cvTextureBeautify];
//スタンプテクスチャを作成します
[self setupTextureWithPixelBuffer:&_cvStickerBuffer w:self.imageWidth h:self.imageHeight glTexture:&__textureStickerOutput cvTexture:&_cvTextureSticker];
//フィルターテクスチャを作成します
[self setupTextureWithPixelBuffer:&_cvFilterBuffer w:self.imageWidth h:self.imageHeight glTexture:&_textureFilterOutput cvTexture:&_cvTextureFilter];
}
- (BOOL)setupTextureWithPixelBuffer:(CVPixelBufferRef *)pixelBufferOut w:(int)iWidth h:(int)iHeight glTexture:(GLuint *)glTexture cvTexture:(CVOpenGLESTextureRef *)cvTexture
{
//配列を作成します
CFDictionaryRef empty = CFDictionaryCreate(kCFAllocatorDefault, NULL, NULL, 0, &kCFTypeDictionaryKeyCallBack, &kCFTypeDictionaryValueCallBacks);
//動的配列を作成します
CFMutableDictionaryRef attrs = CFDictionaryCreateMutable(kCFAllocatorDefault, 1, &kCFTypeDictionaryKeyCallBacks, kCFTypeDictionaryValueCallBacks );
//値を設定します
CFDictionarySetValue(attrs, kCVPixelBufferIOSurfacePropertiesKey, empty);
//pixelBuffer を作成します
CVReturn cvRet = CVPixelBufferCreate(kCFAllocatorDefault, iWidth, iHeight, kCVPixelFormatType_32BGRA, attrs, pixelBufferOut);
if(kCVRetrunSuccess != cvRet){
NSLog(@"CVPixelBufferCreate %d", cvRet);
}
//バッファーとテクスチャを関連付けます
cvRet = CVOpenGLESTextureCacheCreateTextureFromImage(kCFAllocatorDefault, _cvTextureCache, *pixelBufferOut, NULL, GL_TEXTREU_2D, GL_RGBA, self.imageWidth, self.imageHeight, GL_BGRA, GL_UNSIGNED_BYTE, 0, cvTexture);
if(kCVReturnSuccess != cvRet){
NSLog(@"CVOpenGLESTextureCacheCreateTextureFromImage %d", cvRet);
returen NO;
}
//リソースを解放します
CFRelease(attrs);
CFRelease(empty);
//テクスチャのポインターを取得します
*glTexture = CVOpenGLESTextureGetName(*cvTexture);
//テクスチャをバインドします
glBindTexture(CVOpenGLESTextureGetTarget(*cvTexture), *glTexture);
//テクスチャ属性を設定します
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WARP_T, GL_CLAMP_TO_EDGE);
glBindTexture(GL_TEXTURE_2D, 0);
}//cofig コマンドで設定された顔、顔の動き、表情、ジェスチャ、前景と背景のセグメンテーション、体、および体の動きの特徴点を検知します。
//config コマンドを利用可能な場合にのみ、データが検知結果に表示されます。
//検知結果の構造は、st_mobile_human_action.h ファイルで定義されています。詳細に関しては、サンプルをご参照ください。
iRet = st_mobile_human_action_detect(_hDetector,//顔検知ハンドル
pBGRAImageIn,//出力データのアドレス
ST_PIX_FMT_BGRA8888,//画像形式
iWidth,//幅
iHeight,//高さ
iBytesPerRow,//iWidth * 4 (BGRA の 4 チャンネル)
stMobileRotate,//回転角度
iConfig,//動きの検知
&detectResult//検知結果
);typedef enum {
ST_CLOCKWISE_ROTATE_0 = 0, ///< 正面からの顔認証を維持するために、画像を回転させる必要はありません。
ST_CLOCKWISE_ROTATE_90 = 1, ///< 正面からの顔認証を維持するために、画像を 90 度回転する必要があります。
ST_CLOCKWISE_ROTATE_180 = 2,///< 正面からの顔認証を維持するために、画像を 180 度回転する必要があります。
ST_CLOCKWISE_ROTATE_270 = 3 ///< 正面からの顔認証を維持するために、画像を 270 度回転する必要があります。
} st_rotate_type;//表情の検知結果。各要素により示される表情は、ST_MOBILE_EXPRESSION 関数の列挙で定義されます。
bool expressionResult[128] = {0};
st_result_t iRet = st_mobile_get_expression(&detectResult, stMobileRotate, NO, expressionResult);
//表情のしきい値を設定します。デフォルトのしきい値を推奨します。手動で設定する必要はありません。
iRet = st_mobile_set_expression_threshold(ST_MOBILE_EXPRESSION_HEAD_NORMAL, 0.5);iRet = st_mobile_face_attribute_detect(_hAttribute,
pBGRAImageIn,
ST_PIX_FMT_BGRA8888,
iWidth,
iHeight,
iBytesPerRow,
_pFacesDetection,
1, //デモ用に、最初に検知した 1 つの顔の属性を取得します。
&pAttrArray);//テクスチャを美化します
iRet = st_mobile_beautify_process_texture(_hBeautify,
_textureOriginInput,
iWidth,
iHeight,
&detectResult,
_textureBeautifyOutput,
&processedResult);//美化パラメーターを設定します
iRet = st_mobile_beautify_setparam(_hBeautify, ST_BEAUTIFY_REDDEN_STRENGTH, 0.36f);//赤みの強度、値の範囲: [0, 1.0]、赤みなしの場合は 0.0iRet = st_mobile_sticker_process_texture(_hSticker ,//スタンプのハンドル
_textureOriginInput,//入力テクスチャ
iWidth,//幅
iHeight,//高さ
stMobileRotate,//回転角度
ST_CLOCKWISE_ROTATE_0,//前景スタンプの回転角度
false,//ミラーリングするかどうか
&detectResult,//動作の検知結果
&inputEvent, //特定のハードウェアパラメーターおよびカスタムイベント
_textureStickerOutput//処理された画像データ);st_mobile_input_params_t inputEvent;
memset(&inputEvent, 0, sizeof(st_mobile_input_params_t));
int type = ST_INPUT_PARAM_NONE;
iRet = st_mobile_sticker_get_needed_input_params(_hSticker, &type);
if (CHECK_FLAG(type, ST_INPUT_PARAM_CAMERA_QUATERNION)) {
CMDeviceMotion *motion = self.motionManager.deviceMotion;
inputEvent.camera_quaternion[0] = motion.attitude.quaternion.x;
inputEvent.camera_quaternion[1] = motion.attitude.quaternion.y;
inputEvent.camera_quaternion[2] = motion.attitude.quaternion.z;
inputEvent.camera_quaternion[3] = motion.attitude.quaternion.w;
if (self.stCamera.devicePosition == AVCaptureDevicePositionBack) {
inputEvent.is_front_camera = false;
} else {
inputEvent.is_front_camera = true;
}
} else {
inputEvent.camera_quaternion[0] = 0;
inputEvent.camera_quaternion[1] = 0;
inputEvent.camera_quaternion[2] = 0;
inputEvent.camera_quaternion[3] = 1;
}st_result_t iRet = st_mobile_sticker_change_package(_hSticker, stickerPath, NULL);st_result_t iRet = st_mobile_sticker_get_trigger_action(_hSticker, &action);//フィルタータイプを設定するには、OpenGL スレッドで呼び出す必要があります
st_result_t iRet = st_mobile_gl_filter_set_style(_hFilter, [model.strPath UTF8String]);
//フィルター強度を [0,1] の範囲で設定します。0 の場合はフィルターエフェクトなし、1 は最大の強度を示します。
iRet = st_mobile_gl_filter_set_param(_hFilter, ST_GL_FILTER_STRENGTH, self.fFilterStrength);
//フィルター用関数
iRet = st_mobile_gl_filter_process_texture(_hFilter, textureResult, iWidth, iHeight, _textureFilterOutput);//トラッキングする領域を一度だけ設定します。リセット後に、対象領域を再設定します。
st_result_t iRet =
st_mobile_object_tracker_set_target(
st_handle_t handle, //初期化された、一般的なオブジェクトのトラッキングハンドル
const unsigned char *image, //検知対象の画像
st_pixel_format pixel_format, //検知用画像データのピクセル形式。一律にグレースケール画像に変換されます。
int image_width, //検知用画像の幅 (ピクセル単位)
int image_height, //検知用画像の高さ (ピクセル単位)
int image_stride, //検知用画像のスパン (ピクセル単位)。各行のバイト数のこと。
st_rect_t* target_rect //指定されたターゲットの顔枠を入力します。現在は、2 ^ n の正方形のみトラッキングできます。
);
//リアルタイムで連続ビデオフレームのターゲットを高速トラッキングします
st_result_t iRet =
st_mobile_object_tracker_track(
st_handle_t handle, ////初期化された、一般的なオブジェクトのトラッキングハンドル
const unsigned char *image, //検知対象の画像データ
st_pixel_format pixel_format,//検知対象の画像データのピクセル形式
int image_width, //検知対象の画像の幅
int image_height, //検知対象の画像の高さ
int image_stride, //検知対象の画像スパン
st_rect_t *result_rect //トラッキングされた顔枠の新しい位置を出力
float *result_score //信頼係数。必要に応じて、トラッキンが失敗したかどうかを判断する場合は、値を (0, 1) に設定します。
);
//一般的なオブジェクトトラッキング API ハンドルをリセットします
st_mobile_object_tracker_reset(
st_handle_t handle //一般的なオブジェクトトラッキングハンドル
);- (void)releaseResources
{
if ([EAGLContext currentContext] != self.glContext) {
[EAGLContext setCurrentContext:self.glContext];
}
//スタンプ API ハンドルを解放します
if (_hSticker) {
st_mobile_sticker_destroy(_hSticker);
_hSticker = NULL;
}
//美化 API ハンドルを解放します
if (_hBeautify) {
st_mobile_beautify_destroy(_hBeautify);
_hBeautify = NULL;
}
//顔検知ハンドルを解放します
if (_hDetector) {
st_mobile_human_action_destroy(_hDetector);
_hDetector = NULL;
}
//顔属性ハンドルを解放します
if (_hAttribute) {
st_mobile_face_attribute_destroy(_hAttribute);
_hAttribute = NULL;
}
//フィルターハンドルを解放します
if (_hFilter) {
st_mobile_gl_filter_destroy(_hFilter);
_hFilter = NULL;
}
//一般的なオブジェクトハンドルを解放します
if (_hTracker) {
st_mobile_object_tracker_destroy(_hTracker);
_hTracker = NULL;
}
//検知出力から顔配列を解放します
if (_pFacesDetection) {
free(_pFacesDetection);
_pFacesDetection = NULL;
}
//美化出力から顔配列を解放します
if (_pFacesBeautify) {
free(_pFacesBeautify);
_pFacesBeautify = NULL;
}
//テクスチャのリソースを解放します
[self releaseResultTexture];
//テクスチャのキャッシュを解放します
if (_cvTextureCache) {
CFRelease(_cvTextureCache);
_cvTextureCache = NULL;
}
[EAGLContext setCurrentContext:nil];
}if ([EAGLContext currentContext] != self.glContext) {
[EAGLContext setCurrentContext:self.glContext];
}