Hi there! I’m pretty new to the SDK, and I’m just trying to get a minimal facial expression solving working.
I have already gone through the FaceTrack sample and implemented the features I wanted from that and its working great.
However, no matter what I seem to do NvAR_Run always fails for my facial feature handle. im hoping im just missing something small and someone can notice it. I only want to solve for a single frame that i capture at the beginning of this function.
here is the code:
// solve expressions
NvCV_Status expression_err;
NvAR_FeatureHandle expression_handle;
CUstream expression_stream;
std::vector<NvAR_Point2f> _expression_landmarks;
std::vector<NvAR_Rect> _outputBboxData;
NvAR_BBoxes _outputBboxes;
std::vector<float> _expressions, _expressionZeroPoint, _expressionScale, _expressionExponent, _eigenvalues, _landmark_confidence;
NvCVImage frame_image;
struct Pose {
NvAR_Quaternion rotation;
NvAR_Vector3f translation;
float* data() { return &rotation.x; }
const float* data() const { return &rotation.x; }
};
Pose _pose;
unsigned _filtering = 0;
unsigned _pose_mode = 0;
unsigned _expr_mode = 2;
unsigned _enable_cheek_puff = 0;
unsigned _exprCount;
expression_err = NvAR_Create(NvAR_Feature_FaceExpressions, &expression_handle);
if (expression_err!=NVCV_SUCCESS) {
UtilityFunctions::print("failed to create facial expression feature");
}
expression_err = NvAR_SetCudaStream(expression_handle, NvAR_Parameter_Config(CUDAStream), expression_stream);
if (expression_err!=NVCV_SUCCESS) {
UtilityFunctions::print("failed to set CUDA stream");
}
expression_err = NvAR_SetU32(expression_handle, NvAR_Parameter_Config(Temporal), _filtering);
if (expression_err!=NVCV_SUCCESS) {
UtilityFunctions::print("failed to set temporal filtering");
}
expression_err = NvAR_SetU32(expression_handle, NvAR_Parameter_Config(PoseMode), _pose_mode);
if (expression_err!=NVCV_SUCCESS) {
UtilityFunctions::print("failed to set pose_mode");
}
expression_err = NvAR_SetU32(expression_handle, NvAR_Parameter_Config(EnableCheekPuff), _enable_cheek_puff);
if (expression_err!=NVCV_SUCCESS) {
UtilityFunctions::print("failed to set cheek puff");
}
expression_err = NvAR_Load(expression_handle);
if (expression_err!=NVCV_SUCCESS) {
UtilityFunctions::print("failed to load facial expression feature");
} else {
UtilityFunctions::print("facial expression feature loaded");
}
_outputBboxData.assign(25, { 0.f, 0.f, 0.f, 0.f });
_outputBboxes.boxes = _outputBboxData.data();
_outputBboxes.max_boxes = (uint8_t)_outputBboxData.size();
_outputBboxes.num_boxes = 0;
expression_err = NvAR_SetObject(expression_handle, NvAR_Parameter_Output(BoundingBoxes), &_outputBboxes, sizeof(NvAR_BBoxes));
if (expression_err!=NVCV_SUCCESS) {
UtilityFunctions::print("failed to set bbox object");
}
_expression_landmarks.resize(126);
expression_err = NvAR_SetObject(expression_handle, NvAR_Parameter_Output(Landmarks), _expression_landmarks.data(), sizeof(NvAR_Point2f));
if (expression_err!=NVCV_SUCCESS) {
UtilityFunctions::print("failed to set landmarks object");
}
_landmark_confidence.resize(126);
expression_err = NvAR_SetF32Array(expression_handle, NvAR_Parameter_Output(LandmarksConfidence), _landmark_confidence.data(), 126);
if (expression_err!=NVCV_SUCCESS) {
UtilityFunctions::print("failed to set landmark confidence array");
}
expression_err = NvAR_GetU32(expression_handle, NvAR_Parameter_Config(ExpressionCount), &_exprCount);
if (expression_err!=NVCV_SUCCESS) {
UtilityFunctions::print("failed to get expression count");
}
_expressions.resize(_exprCount);
_expressionZeroPoint.resize(_exprCount, 0.0f);
_expressionScale.resize(_exprCount, 1.0f);
_expressionExponent.resize(_exprCount, 1.0f);
expression_err = NvAR_SetF32Array(expression_handle, NvAR_Parameter_Output(ExpressionCoefficients), _expressions.data(), _exprCount);
if (expression_err!=NVCV_SUCCESS) {
UtilityFunctions::print("failed to set expression coefficient array");
} else {
UtilityFunctions::print("successfully set expression coefficient array");
}
ConvertMatToNvCVImage(frame, &frame_image); // Ensure the implementation of this function
expression_err = NvAR_SetObject(expression_handle, NvAR_Parameter_Input(Image), &frame_image, sizeof(frame_image));
if (expression_err != NVCV_SUCCESS) {
UtilityFunctions::print("failed to set the source image for expression analysis");
}
float cameraIntrinsicParams[3] = {static_cast<float>(inputHeight), inputWidth / 2.0f, inputHeight / 2.0f}; // focal length, cx, cy
expression_err = NvAR_SetF32Array(expression_handle, NvAR_Parameter_Input(CameraIntrinsicParams), cameraIntrinsicParams, 3);
if (expression_err != NVCV_SUCCESS) {
UtilityFunctions::print("failed to set camera intrinsic parameters");
}
expression_err = NvAR_SetObject(expression_handle, NvAR_Parameter_Output(Pose), &_pose.rotation, sizeof(NvAR_Quaternion));
if (expression_err != NVCV_SUCCESS) {
UtilityFunctions::print("failed to set pose rotation object");
}
expression_err = NvAR_SetObject(expression_handle, NvAR_Parameter_Output(PoseTranslation), &_pose.translation, sizeof(NvAR_Vector3f));
if (expression_err != NVCV_SUCCESS) {
UtilityFunctions::print("failed to set pose rotation object");
}
// Run the facial expression feature
expression_err = NvAR_Run(expression_handle);
if (expression_err != NVCV_SUCCESS) {
UtilityFunctions::print("failed to run facial expression feature");
} else {
UtilityFunctions::print("facial expression feature run successfully");
}
// Process and print the expression coefficients
// After running the facial expression feature
for (size_t i = 0; i < _expressions.size(); ++i) {
std::cout << "Expression Coefficient " << i << ": " << _expressions[i] << std::endl;
}
// Cleanup for expression handling
NvAR_Destroy(expression_handle); // Destroy expression feature handle
// Deallocate NvCVImage used for capturing frame
NvCVImage_Dealloc(&frame_image);
// Deallocate std::vectors
_expression_landmarks.clear();
_outputBboxData.clear();
_expressions.clear();
_expressionZeroPoint.clear();
_expressionScale.clear();
_expressionExponent.clear();
_eigenvalues.clear();
_landmark_confidence.clear();
and then here is the function i am trying to use to convert the cv image capture to NvCVImage with
NvCV_Status FaceTrack::ConvertMatToNvCVImage(const cv::Mat& mat, NvCVImage* nvImage) {
if (!mat.empty() && mat.depth() == CV_8U) {
NvCV_Status status = NvCVImage_Alloc(nvImage, mat.cols, mat.rows, NVCV_BGR, NVCV_U8, NVCV_CHUNKY, NVCV_CPU, 1);
if (status != NVCV_SUCCESS) return status;
// Assuming BGR format and contiguous memory in cv::Mat
memcpy(nvImage->pixels, mat.data, mat.total() * mat.elemSize());
return NVCV_SUCCESS;
} else {
return NVCV_ERR_FEATURENOTFOUND;
}
}
if anyone has the time to take a look, and tell me what im missing, I would be greatly appreciative! I’ll keep at it in the meantime, but I am taking a break so I figured I’d toss it up here.
also I know it would be better to break this up into more functions. like i said, i’m just trying to find the minimal implementation right now so i can think about how i wanna design the app.
thanks!