diff --git a/c_api/fastdeploy_capi/fd_type.h b/c_api/fastdeploy_capi/fd_type.h index a7860e982..6833fd601 100644 --- a/c_api/fastdeploy_capi/fd_type.h +++ b/c_api/fastdeploy_capi/fd_type.h @@ -23,7 +23,12 @@ typedef struct FD_C_OneDimArrayUint8 { size_t size; uint8_t* data; -} FD_C_OneDimArrayUint8; // std::vector +} FD_C_OneDimArrayUint8; // std::vector + +typedef struct FD_C_OneDimArrayInt8 { + size_t size; + int8_t* data; +} FD_C_OneDimArrayInt8; // std::vector typedef struct FD_C_OneDimArrayInt32 { size_t size; @@ -60,6 +65,21 @@ typedef struct FD_C_TwoDimArraySize { FD_C_OneDimArraySize* data; } FD_C_TwoDimArraySize; // std::vector> +typedef struct FD_C_TwoDimArrayInt8 { + size_t size; + FD_C_OneDimArrayInt8* data; +} FD_C_TwoDimArrayInt8; // std::vector> + +typedef struct FD_C_TwoDimArrayInt32 { + size_t size; + FD_C_OneDimArrayInt32* data; +} FD_C_TwoDimArrayInt32; // std::vector> + +typedef struct FD_C_ThreeDimArrayInt32 { + size_t size; + FD_C_TwoDimArrayInt32* data; +} FD_C_ThreeDimArrayInt32; // std::vector>> + typedef struct FD_C_TwoDimArrayFloat { size_t size; FD_C_OneDimArrayFloat* data; diff --git a/c_api/fastdeploy_capi/types_internal.cc b/c_api/fastdeploy_capi/types_internal.cc index 988b39af1..55d126e0b 100644 --- a/c_api/fastdeploy_capi/types_internal.cc +++ b/c_api/fastdeploy_capi/types_internal.cc @@ -27,6 +27,11 @@ DECL_AND_IMPLEMENT_RESULT_FUNC_FOR_GET_PTR_FROM_WRAPPER( DECL_AND_IMPLEMENT_RESULT_FUNC_FOR_GET_PTR_FROM_WRAPPER( DetectionResult, fd_detection_result_wrapper, detection_result) +// OCRResult +DECL_AND_IMPLEMENT_RESULT_FUNC_FOR_GET_PTR_FROM_WRAPPER(OCRResult, + fd_ocr_result_wrapper, + ocr_result) + // Models: // Classification @@ -120,6 +125,28 @@ DECL_AND_IMPLEMENT_DETECTION_MODEL_FUNC_FOR_GET_PTR_FROM_WRAPPER(GFL, fd_gfl_wrapper, gfl_model) +// OCR models + +// Recognizer +DECL_AND_IMPLEMENT_OCR_MODEL_FUNC_FOR_GET_PTR_FROM_WRAPPER( + Recognizer, fd_recognizer_wrapper, recognizer_model); + +// DBDetector +DECL_AND_IMPLEMENT_OCR_MODEL_FUNC_FOR_GET_PTR_FROM_WRAPPER( + DBDetector, fd_dbdetector_wrapper, dbdetector_model); + +// Classifier +DECL_AND_IMPLEMENT_OCR_MODEL_FUNC_FOR_GET_PTR_FROM_WRAPPER( + Classifier, fd_classifier_wrapper, classifier_model); + +// PPOCRv2 +DECL_AND_IMPLEMENT_PIPELINE_MODEL_FUNC_FOR_GET_PTR_FROM_WRAPPER( + PPOCRv2, fd_ppocrv2_wrapper, ppocrv2_model); + +// PPOCRv3 +DECL_AND_IMPLEMENT_PIPELINE_MODEL_FUNC_FOR_GET_PTR_FROM_WRAPPER( + PPOCRv3, fd_ppocrv3_wrapper, ppocrv3_model); + #endif std::unique_ptr& diff --git a/c_api/fastdeploy_capi/types_internal.h b/c_api/fastdeploy_capi/types_internal.h index c3238de51..f9b0d206e 100644 --- a/c_api/fastdeploy_capi/types_internal.h +++ b/c_api/fastdeploy_capi/types_internal.h @@ -22,6 +22,11 @@ #include "fastdeploy/vision/classification/ppcls/model.h" #include "fastdeploy/vision/common/result.h" #include "fastdeploy/vision/detection/ppdet/model.h" +#include "fastdeploy/vision/ocr/ppocr/classifier.h" +#include "fastdeploy/vision/ocr/ppocr/dbdetector.h" +#include "fastdeploy/vision/ocr/ppocr/recognizer.h" +#include "fastdeploy/vision/ocr/ppocr/ppocr_v2.h" +#include "fastdeploy/vision/ocr/ppocr/ppocr_v3.h" #define DEFINE_RESULT_WRAPPER_STRUCT(typename, varname) typedef struct FD_C_##typename##Wrapper { \ std::unique_ptr varname; \ @@ -36,6 +41,14 @@ std::unique_ptr varname; \ } FD_C_##typename##Wrapper +#define DEFINE_OCR_MODEL_WRAPPER_STRUCT(typename, varname) typedef struct FD_C_##typename##Wrapper { \ + std::unique_ptr varname; \ +} FD_C_##typename##Wrapper + +#define DEFINE_PIPELINE_MODEL_WRAPPER_STRUCT(typename, varname) typedef struct FD_C_##typename##Wrapper { \ + std::unique_ptr varname; \ +} FD_C_##typename##Wrapper + // ------------- belows are wrapper struct define --------------------- // // Results: @@ -47,6 +60,10 @@ DEFINE_RESULT_WRAPPER_STRUCT(ClassifyResult, classify_result); DEFINE_RESULT_WRAPPER_STRUCT(DetectionResult, detection_result); +// OCRResult +DEFINE_RESULT_WRAPPER_STRUCT(OCRResult, ocr_result); + + // Models: // Classification @@ -119,6 +136,23 @@ DEFINE_DETECTION_MODEL_WRAPPER_STRUCT(TOOD, tood_model); // GFL DEFINE_DETECTION_MODEL_WRAPPER_STRUCT(GFL, gfl_model); +// OCR models + +// Recognizer +DEFINE_OCR_MODEL_WRAPPER_STRUCT(Recognizer, recognizer_model); + +// DBDetector +DEFINE_OCR_MODEL_WRAPPER_STRUCT(DBDetector, dbdetector_model); + +// Classifier +DEFINE_OCR_MODEL_WRAPPER_STRUCT(Classifier, classifier_model); + +// PPOCRv2 +DEFINE_PIPELINE_MODEL_WRAPPER_STRUCT(PPOCRv2, ppocrv2_model); + +// PPOCRv3 +DEFINE_PIPELINE_MODEL_WRAPPER_STRUCT(PPOCRv3, ppocrv3_model); + // ------------- belows are function declaration for get ptr from wrapper --------------------- // @@ -134,6 +168,16 @@ FD_C_CheckAndConvert##typename##Wrapper( \ FD_C_CheckAndConvert##typename##Wrapper( \ FD_C_##typename##Wrapper* varname) + +#define DECLARE_OCR_MODEL_FUNC_FOR_GET_PTR_FROM_WRAPPER(typename, varname) std::unique_ptr& \ +FD_C_CheckAndConvert##typename##Wrapper( \ + FD_C_##typename##Wrapper* varname) + +#define DECLARE_PIPELINE_MODEL_FUNC_FOR_GET_PTR_FROM_WRAPPER(typename, varname) std::unique_ptr& \ +FD_C_CheckAndConvert##typename##Wrapper( \ + FD_C_##typename##Wrapper* varname) + + namespace fastdeploy { // results: @@ -145,6 +189,12 @@ DECLARE_RESULT_FUNC_FOR_GET_PTR_FROM_WRAPPER(ClassifyResult, DECLARE_RESULT_FUNC_FOR_GET_PTR_FROM_WRAPPER(DetectionResult, fd_detection_result_wrapper); + +// OCRResult +DECLARE_RESULT_FUNC_FOR_GET_PTR_FROM_WRAPPER(OCRResult, + fd_ocr_result_wrapper); + + // Models: // Classification @@ -257,6 +307,23 @@ DECLARE_DETECTION_MODEL_FUNC_FOR_GET_PTR_FROM_WRAPPER(TOOD, DECLARE_DETECTION_MODEL_FUNC_FOR_GET_PTR_FROM_WRAPPER(GFL, fd_gfl_wrapper); +// OCR models + +// Recognizer +DECLARE_OCR_MODEL_FUNC_FOR_GET_PTR_FROM_WRAPPER(Recognizer, fd_recognizer_wrapper); + +// DBDetector +DECLARE_OCR_MODEL_FUNC_FOR_GET_PTR_FROM_WRAPPER(DBDetector, fd_dbdetector_wrapper); + +// Classifier +DECLARE_OCR_MODEL_FUNC_FOR_GET_PTR_FROM_WRAPPER(Classifier, fd_classifier_wrapper); + +// PPOCRv2 +DECLARE_PIPELINE_MODEL_FUNC_FOR_GET_PTR_FROM_WRAPPER(PPOCRv2, fd_ppocrv2_wrapper); + +// PPOCRv3 +DECLARE_PIPELINE_MODEL_FUNC_FOR_GET_PTR_FROM_WRAPPER(PPOCRv3, fd_ppocrv3_wrapper); + } // namespace fastdeploy #endif @@ -299,3 +366,20 @@ FD_C_CheckAndConvert##typename##Wrapper( \ "The pointer of " #var_wrapper_name " shouldn't be nullptr."); \ return var_wrapper_name->var_ptr_name; \ } + + +#define DECL_AND_IMPLEMENT_OCR_MODEL_FUNC_FOR_GET_PTR_FROM_WRAPPER(typename, var_wrapper_name, var_ptr_name) std::unique_ptr& \ +FD_C_CheckAndConvert##typename##Wrapper( \ + FD_C_##typename##Wrapper* var_wrapper_name) { \ + FDASSERT(var_wrapper_name != nullptr, \ + "The pointer of " #var_wrapper_name " shouldn't be nullptr."); \ + return var_wrapper_name->var_ptr_name; \ +} + +#define DECL_AND_IMPLEMENT_PIPELINE_MODEL_FUNC_FOR_GET_PTR_FROM_WRAPPER(typename, var_wrapper_name, var_ptr_name) std::unique_ptr& \ +FD_C_CheckAndConvert##typename##Wrapper( \ + FD_C_##typename##Wrapper* var_wrapper_name) { \ + FDASSERT(var_wrapper_name != nullptr, \ + "The pointer of " #var_wrapper_name " shouldn't be nullptr."); \ + return var_wrapper_name->var_ptr_name; \ +} diff --git a/c_api/fastdeploy_capi/vision.h b/c_api/fastdeploy_capi/vision.h index a27a6c8dd..1b03eba0a 100644 --- a/c_api/fastdeploy_capi/vision.h +++ b/c_api/fastdeploy_capi/vision.h @@ -18,6 +18,7 @@ #ifdef ENABLE_VISION #include "fastdeploy_capi/vision/classification/ppcls/model.h" #include "fastdeploy_capi/vision/detection/ppdet/model.h" +#include "fastdeploy_capi/vision/ocr/ppocr/model.h" #include "fastdeploy_capi/vision/result.h" #include "fastdeploy_capi/vision/visualize.h" #endif diff --git a/c_api/fastdeploy_capi/vision/detection/ppdet/base_define.h b/c_api/fastdeploy_capi/vision/detection/ppdet/base_define.h index 13a647f3d..807419788 100644 --- a/c_api/fastdeploy_capi/vision/detection/ppdet/base_define.h +++ b/c_api/fastdeploy_capi/vision/detection/ppdet/base_define.h @@ -15,7 +15,7 @@ #pragma once #define DECLARE_CREATE_WRAPPER_FUNCTION(model_type) FASTDEPLOY_CAPI_EXPORT extern __fd_give FD_C_##model_type##Wrapper* \ -FD_C_Creates##model_type##Wrapper( \ +FD_C_Create##model_type##Wrapper( \ const char* model_file, const char* params_file, const char* config_file, \ FD_C_RuntimeOptionWrapper* fd_c_runtime_option_wrapper, \ const FD_C_ModelFormat model_format) @@ -88,7 +88,7 @@ return model->Initialized(); } \ return successful; -#define DECLARE_AND_IMPLEMENT_CREATE_WRAPPER_FUNCTION(model_type, var_name) FD_C_##model_type##Wrapper* FD_C_Creates##model_type##Wrapper(\ +#define DECLARE_AND_IMPLEMENT_CREATE_WRAPPER_FUNCTION(model_type, var_name) FD_C_##model_type##Wrapper* FD_C_Create##model_type##Wrapper(\ const char* model_file, const char* params_file, const char* config_file, \ FD_C_RuntimeOptionWrapper* fd_c_runtime_option_wrapper, \ const FD_C_ModelFormat model_format) { \ diff --git a/c_api/fastdeploy_capi/vision/detection/ppdet/model.cc b/c_api/fastdeploy_capi/vision/detection/ppdet/model.cc index 7bfbd67f0..68771edea 100644 --- a/c_api/fastdeploy_capi/vision/detection/ppdet/model.cc +++ b/c_api/fastdeploy_capi/vision/detection/ppdet/model.cc @@ -23,7 +23,7 @@ extern "C" { // PPYOLOE -FD_C_PPYOLOEWrapper* FD_C_CreatesPPYOLOEWrapper( +FD_C_PPYOLOEWrapper* FD_C_CreatePPYOLOEWrapper( const char* model_file, const char* params_file, const char* config_file, FD_C_RuntimeOptionWrapper* fd_c_runtime_option_wrapper, const FD_C_ModelFormat model_format) { diff --git a/c_api/fastdeploy_capi/vision/ocr/ppocr/base_define.h b/c_api/fastdeploy_capi/vision/ocr/ppocr/base_define.h new file mode 100644 index 000000000..4cd568e85 --- /dev/null +++ b/c_api/fastdeploy_capi/vision/ocr/ppocr/base_define.h @@ -0,0 +1,59 @@ +// Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#define OCR_DECLARE_DESTROY_WRAPPER_FUNCTION(model_type, wrapper_var_name) FASTDEPLOY_CAPI_EXPORT extern void \ +FD_C_Destroy##model_type##Wrapper(__fd_take FD_C_##model_type##Wrapper* wrapper_var_name); + +#define OCR_DECLARE_INITIALIZED_FUNCTION(model_type, wrapper_var_name) FASTDEPLOY_CAPI_EXPORT extern FD_C_Bool FD_C_##model_type##WrapperInitialized( \ + __fd_keep FD_C_##model_type##Wrapper* wrapper_var_name) + +#define OCR_IMPLEMENT_DESTROY_WRAPPER_FUNCTION(model_type, wrapper_var_name) delete wrapper_var_name + +#define OCR_DECLARE_AND_IMPLEMENT_DESTROY_WRAPPER_FUNCTION(model_type, wrapper_var_name) void FD_C_Destroy##model_type##Wrapper( \ + __fd_take FD_C_##model_type##Wrapper* wrapper_var_name) { \ + OCR_IMPLEMENT_DESTROY_WRAPPER_FUNCTION(model_type, wrapper_var_name); \ +} + +#define OCR_IMPLEMENT_INITIALIZED_FUNCTION(model_type, wrapper_var_name) auto& model = \ + CHECK_AND_CONVERT_FD_TYPE(model_type##Wrapper, wrapper_var_name); \ +return model->Initialized(); + +#define OCR_DECLARE_AND_IMPLEMENT_INITIALIZED_FUNCTION(model_type, wrapper_var_name) FD_C_Bool FD_C_##model_type##WrapperInitialized( \ + FD_C_##model_type##Wrapper* wrapper_var_name) { \ + OCR_IMPLEMENT_INITIALIZED_FUNCTION(model_type, wrapper_var_name); \ +} + +#define PIPELINE_DECLARE_DESTROY_WRAPPER_FUNCTION(model_type, wrapper_var_name) FASTDEPLOY_CAPI_EXPORT extern void \ +FD_C_Destroy##model_type##Wrapper(__fd_take FD_C_##model_type##Wrapper* wrapper_var_name); + +#define PIPELINE_DECLARE_INITIALIZED_FUNCTION(model_type, wrapper_var_name) FASTDEPLOY_CAPI_EXPORT extern FD_C_Bool FD_C_##model_type##WrapperInitialized( \ + __fd_keep FD_C_##model_type##Wrapper* wrapper_var_name) + +#define PIPELINE_IMPLEMENT_DESTROY_WRAPPER_FUNCTION(model_type, wrapper_var_name) delete wrapper_var_name + +#define PIPELINE_DECLARE_AND_IMPLEMENT_DESTROY_WRAPPER_FUNCTION(model_type, wrapper_var_name) void FD_C_Destroy##model_type##Wrapper( \ + __fd_take FD_C_##model_type##Wrapper* wrapper_var_name) { \ + PIPELINE_IMPLEMENT_DESTROY_WRAPPER_FUNCTION(model_type, wrapper_var_name); \ +} + +#define PIPELINE_IMPLEMENT_INITIALIZED_FUNCTION(model_type, wrapper_var_name) auto& model = \ + CHECK_AND_CONVERT_FD_TYPE(model_type##Wrapper, wrapper_var_name); \ +return model->Initialized(); + +#define PIPELINE_DECLARE_AND_IMPLEMENT_INITIALIZED_FUNCTION(model_type, wrapper_var_name) FD_C_Bool FD_C_##model_type##WrapperInitialized( \ + FD_C_##model_type##Wrapper* wrapper_var_name) { \ + PIPELINE_IMPLEMENT_INITIALIZED_FUNCTION(model_type, wrapper_var_name); \ +} diff --git a/c_api/fastdeploy_capi/vision/ocr/ppocr/model.cc b/c_api/fastdeploy_capi/vision/ocr/ppocr/model.cc new file mode 100644 index 000000000..f9d8bba30 --- /dev/null +++ b/c_api/fastdeploy_capi/vision/ocr/ppocr/model.cc @@ -0,0 +1,503 @@ +// Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "fastdeploy_capi/vision/ocr/ppocr/model.h" + +#include "fastdeploy_capi/types_internal.h" +#include "fastdeploy_capi/vision/visualize.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// Recognizer + +FD_C_RecognizerWrapper* FD_C_CreateRecognizerWrapper( + const char* model_file, const char* params_file, const char* label_path, + FD_C_RuntimeOptionWrapper* fd_c_runtime_option_wrapper, + const FD_C_ModelFormat model_format) { + auto& runtime_option = CHECK_AND_CONVERT_FD_TYPE(RuntimeOptionWrapper, + fd_c_runtime_option_wrapper); + FD_C_RecognizerWrapper* fd_c_recognizer_wrapper = + new FD_C_RecognizerWrapper(); + fd_c_recognizer_wrapper->recognizer_model = + std::unique_ptr( + new fastdeploy::vision::ocr::Recognizer( + std::string(model_file), std::string(params_file), + std::string(label_path), *runtime_option, + static_cast(model_format))); + return fd_c_recognizer_wrapper; +} + +OCR_DECLARE_AND_IMPLEMENT_DESTROY_WRAPPER_FUNCTION(Recognizer, + fd_c_recognizer_wrapper) + +FD_C_Bool FD_C_RecognizerWrapperPredict( + FD_C_RecognizerWrapper* fd_c_recognizer_wrapper, FD_C_Mat img, + FD_C_Cstr* text, float* rec_score) { + cv::Mat* im = reinterpret_cast(img); + auto& model = + CHECK_AND_CONVERT_FD_TYPE(RecognizerWrapper, fd_c_recognizer_wrapper); + + std::string res_string; + + bool successful = model->Predict(*im, &res_string, rec_score); + if (successful) { + text->size = res_string.size(); + text->data = new char[res_string.size() + 1]; + strcpy(text->data, res_string.c_str()); + } + return successful; +} + +OCR_DECLARE_AND_IMPLEMENT_INITIALIZED_FUNCTION(Recognizer, + fd_c_recognizer_wrapper) + +FD_C_Bool FD_C_RecognizerWrapperBatchPredict( + FD_C_RecognizerWrapper* fd_c_recognizer_wrapper, FD_C_OneDimMat imgs, + FD_C_OneDimArrayCstr* texts, FD_C_OneDimArrayFloat* rec_scores) { + std::vector imgs_vec; + std::vector texts_out; + std::vector rec_scores_out; + for (int i = 0; i < imgs.size; i++) { + imgs_vec.push_back(*(reinterpret_cast(imgs.data[i]))); + } + auto& model = + CHECK_AND_CONVERT_FD_TYPE(RecognizerWrapper, fd_c_recognizer_wrapper); + bool successful = model->BatchPredict(imgs_vec, &texts_out, &rec_scores_out); + if (successful) { + // copy results back to FD_C_OneDimArrayCstr and FD_C_OneDimArrayFloat + texts->size = texts_out.size(); + texts->data = new FD_C_Cstr[texts->size]; + for (int i = 0; i < texts_out.size(); i++) { + texts->data[i].size = texts_out[i].length(); + texts->data[i].data = new char[texts_out[i].length() + 1]; + strncpy(texts->data[i].data, texts_out[i].c_str(), texts_out[i].length()); + } + + rec_scores->size = rec_scores_out.size(); + rec_scores->data = new float[rec_scores->size]; + memcpy(rec_scores->data, rec_scores_out.data(), + sizeof(float) * rec_scores->size); + } + return successful; +} + +FD_C_Bool FD_C_RecognizerWrapperBatchPredictWithIndex( + FD_C_RecognizerWrapper* fd_c_recognizer_wrapper, FD_C_OneDimMat imgs, + FD_C_OneDimArrayCstr* texts, FD_C_OneDimArrayFloat* rec_scores, + size_t start_index, size_t end_index, FD_C_OneDimArrayInt32 indices) { + std::vector imgs_vec; + std::vector texts_out; + std::vector rec_scores_out; + std::vector indices_in; + for (int i = 0; i < imgs.size; i++) { + imgs_vec.push_back(*(reinterpret_cast(imgs.data[i]))); + } + for (int i = 0; i < indices.size; i++) { + indices_in.push_back(indices.data[i]); + } + auto& model = + CHECK_AND_CONVERT_FD_TYPE(RecognizerWrapper, fd_c_recognizer_wrapper); + bool successful = model->BatchPredict(imgs_vec, &texts_out, &rec_scores_out, + start_index, end_index, indices_in); + if (successful) { + // copy results back to FD_C_OneDimArrayCstr and FD_C_OneDimArrayFloat + texts->size = texts_out.size(); + texts->data = new FD_C_Cstr[texts->size]; + for (int i = 0; i < texts_out.size(); i++) { + texts->data[i].size = texts_out[i].length(); + texts->data[i].data = new char[texts_out[i].length() + 1]; + strncpy(texts->data[i].data, texts_out[i].c_str(), texts_out[i].length()); + } + + rec_scores->size = rec_scores_out.size(); + rec_scores->data = new float[rec_scores->size]; + memcpy(rec_scores->data, rec_scores_out.data(), + sizeof(float) * rec_scores->size); + } + return successful; +} + +// Classifier + +FD_C_ClassifierWrapper* FD_C_CreateClassifierWrapper( + const char* model_file, const char* params_file, + FD_C_RuntimeOptionWrapper* fd_c_runtime_option_wrapper, + const FD_C_ModelFormat model_format) { + auto& runtime_option = CHECK_AND_CONVERT_FD_TYPE(RuntimeOptionWrapper, + fd_c_runtime_option_wrapper); + FD_C_ClassifierWrapper* fd_c_classifier_wrapper = + new FD_C_ClassifierWrapper(); + fd_c_classifier_wrapper->classifier_model = + std::unique_ptr( + new fastdeploy::vision::ocr::Classifier( + std::string(model_file), std::string(params_file), + *runtime_option, + static_cast(model_format))); + return fd_c_classifier_wrapper; +} + +OCR_DECLARE_AND_IMPLEMENT_DESTROY_WRAPPER_FUNCTION(Classifier, + fd_c_classifier_wrapper) + +FD_C_Bool FD_C_ClassifierWrapperPredict( + FD_C_ClassifierWrapper* fd_c_classifier_wrapper, FD_C_Mat img, + int32_t* cls_label, float* cls_score) { + cv::Mat* im = reinterpret_cast(img); + auto& model = + CHECK_AND_CONVERT_FD_TYPE(ClassifierWrapper, fd_c_classifier_wrapper); + bool successful = model->Predict(*im, cls_label, cls_score); + return successful; +} + +OCR_DECLARE_AND_IMPLEMENT_INITIALIZED_FUNCTION(Classifier, + fd_c_classifier_wrapper) + +FD_C_Bool FD_C_ClassifierWrapperBatchPredict( + FD_C_ClassifierWrapper* fd_c_classifier_wrapper, FD_C_OneDimMat imgs, + FD_C_OneDimArrayInt32* cls_labels, FD_C_OneDimArrayFloat* cls_scores) { + std::vector imgs_vec; + std::vector cls_labels_out; + std::vector cls_scores_out; + for (int i = 0; i < imgs.size; i++) { + imgs_vec.push_back(*(reinterpret_cast(imgs.data[i]))); + } + auto& model = + CHECK_AND_CONVERT_FD_TYPE(ClassifierWrapper, fd_c_classifier_wrapper); + bool successful = + model->BatchPredict(imgs_vec, &cls_labels_out, &cls_scores_out); + if (successful) { + // copy results back to FD_C_OneDimArrayInt32 and FD_C_OneDimArrayFloat + cls_labels->size = cls_labels_out.size(); + cls_labels->data = new int[cls_labels->size]; + memcpy(cls_labels->data, cls_labels_out.data(), + sizeof(int) * cls_labels->size); + + cls_scores->size = cls_scores_out.size(); + cls_scores->data = new float[cls_scores->size]; + memcpy(cls_scores->data, cls_scores_out.data(), + sizeof(int) * cls_scores->size); + } + return successful; +} + +FD_C_Bool FD_C_ClassifierWrapperBatchPredictWithIndex( + FD_C_ClassifierWrapper* fd_c_classifier_wrapper, FD_C_OneDimMat imgs, + FD_C_OneDimArrayInt32* cls_labels, FD_C_OneDimArrayFloat* cls_scores, + size_t start_index, size_t end_index) { + std::vector imgs_vec; + std::vector cls_labels_out; + std::vector cls_scores_out; + for (int i = 0; i < imgs.size; i++) { + imgs_vec.push_back(*(reinterpret_cast(imgs.data[i]))); + } + auto& model = + CHECK_AND_CONVERT_FD_TYPE(ClassifierWrapper, fd_c_classifier_wrapper); + bool successful = model->BatchPredict( + imgs_vec, &cls_labels_out, &cls_scores_out, start_index, end_index); + if (successful) { + // copy results back to FD_C_OneDimArrayInt32 and FD_C_OneDimArrayFloat + cls_labels->size = cls_labels_out.size(); + cls_labels->data = new int[cls_labels->size]; + memcpy(cls_labels->data, cls_labels_out.data(), + sizeof(int) * cls_labels->size); + + cls_scores->size = cls_scores_out.size(); + cls_scores->data = new float[cls_scores->size]; + memcpy(cls_scores->data, cls_scores_out.data(), + sizeof(int) * cls_scores->size); + } + return successful; +} + +// DBDetector +FD_C_DBDetectorWrapper* FD_C_CreateDBDetectorWrapper( + const char* model_file, const char* params_file, + FD_C_RuntimeOptionWrapper* fd_c_runtime_option_wrapper, + const FD_C_ModelFormat model_format) { + auto& runtime_option = CHECK_AND_CONVERT_FD_TYPE(RuntimeOptionWrapper, + fd_c_runtime_option_wrapper); + FD_C_DBDetectorWrapper* fd_c_dbdetector_wrapper = + new FD_C_DBDetectorWrapper(); + fd_c_dbdetector_wrapper->dbdetector_model = + std::unique_ptr( + new fastdeploy::vision::ocr::DBDetector( + std::string(model_file), std::string(params_file), + *runtime_option, + static_cast(model_format))); + return fd_c_dbdetector_wrapper; +} + +OCR_DECLARE_AND_IMPLEMENT_DESTROY_WRAPPER_FUNCTION(DBDetector, + fd_c_dbdetector_wrapper) + +FD_C_Bool FD_C_DBDetectorWrapperPredict( + FD_C_DBDetectorWrapper* fd_c_dbdetector_wrapper, FD_C_Mat img, + FD_C_TwoDimArrayInt32* boxes_result) { + cv::Mat* im = reinterpret_cast(img); + std::vector> boxes_result_out; + auto& model = + CHECK_AND_CONVERT_FD_TYPE(DBDetectorWrapper, fd_c_dbdetector_wrapper); + bool successful = model->Predict(*im, &boxes_result_out); + if (successful) { + // copy boxes + const int boxes_coordinate_dim = 8; + boxes_result->size = boxes_result_out.size(); + boxes_result->data = new FD_C_OneDimArrayInt32[boxes_result->size]; + for (size_t i = 0; i < boxes_result_out.size(); i++) { + boxes_result->data[i].size = boxes_coordinate_dim; + boxes_result->data[i].data = new int[boxes_coordinate_dim]; + for (size_t j = 0; j < boxes_coordinate_dim; j++) { + boxes_result->data[i].data[j] = boxes_result_out[i][j]; + } + } + } + return successful; +} + +OCR_DECLARE_AND_IMPLEMENT_INITIALIZED_FUNCTION(DBDetector, + fd_c_dbdetector_wrapper) + +FD_C_Bool FD_C_DBDetectorWrapperBatchPredict( + FD_C_DBDetectorWrapper* fd_c_dbdetector_wrapper, FD_C_OneDimMat imgs, + FD_C_ThreeDimArrayInt32* det_results) { + std::vector imgs_vec; + std::vector>> det_results_out; + for (int i = 0; i < imgs.size; i++) { + imgs_vec.push_back(*(reinterpret_cast(imgs.data[i]))); + } + auto& model = + CHECK_AND_CONVERT_FD_TYPE(DBDetectorWrapper, fd_c_dbdetector_wrapper); + bool successful = model->BatchPredict(imgs_vec, &det_results_out); + if (successful) { + // copy results back to FD_C_ThreeDimArrayInt32 + det_results->size = det_results_out.size(); + det_results->data = new FD_C_TwoDimArrayInt32[det_results->size]; + for (int batch_indx = 0; batch_indx < det_results->size; batch_indx++) { + const int boxes_coordinate_dim = 8; + det_results->data[batch_indx].size = det_results_out[batch_indx].size(); + det_results->data[batch_indx].data = + new FD_C_OneDimArrayInt32[det_results->data[batch_indx].size]; + for (size_t i = 0; i < det_results_out[batch_indx].size(); i++) { + det_results->data[batch_indx].data[i].size = boxes_coordinate_dim; + det_results->data[batch_indx].data[i].data = + new int[boxes_coordinate_dim]; + for (size_t j = 0; j < boxes_coordinate_dim; j++) { + det_results->data[batch_indx].data[i].data[j] = + det_results_out[batch_indx][i][j]; + } + } + } + } + return successful; +} + +// PPOCRv2 + +FD_C_PPOCRv2Wrapper* FD_C_CreatePPOCRv2Wrapper( + FD_C_DBDetectorWrapper* fd_c_det_model_wrapper, + FD_C_ClassifierWrapper* fd_c_cls_model_wrapper, + FD_C_RecognizerWrapper* fd_c_rec_model_wrapper) { + FD_C_PPOCRv2Wrapper* fd_c_ppocrv2_wrapper = new FD_C_PPOCRv2Wrapper(); + auto& det_model = + CHECK_AND_CONVERT_FD_TYPE(DBDetectorWrapper, fd_c_det_model_wrapper); + auto& cls_model = + CHECK_AND_CONVERT_FD_TYPE(ClassifierWrapper, fd_c_cls_model_wrapper); + auto& rec_model = + CHECK_AND_CONVERT_FD_TYPE(RecognizerWrapper, fd_c_rec_model_wrapper); + fd_c_ppocrv2_wrapper->ppocrv2_model = + std::unique_ptr( + new fastdeploy::pipeline::PPOCRv2(det_model.get(), cls_model.get(), + rec_model.get())); + return fd_c_ppocrv2_wrapper; +} + +PIPELINE_DECLARE_AND_IMPLEMENT_DESTROY_WRAPPER_FUNCTION(PPOCRv2, + fd_c_ppocrv2_wrapper) + +FD_C_Bool FD_C_PPOCRv2WrapperPredict(FD_C_PPOCRv2Wrapper* fd_c_ppocrv2_wrapper, + FD_C_Mat img, + FD_C_OCRResult* fd_c_ocr_result) { + cv::Mat* im = reinterpret_cast(img); + auto& model = CHECK_AND_CONVERT_FD_TYPE(PPOCRv2Wrapper, fd_c_ppocrv2_wrapper); + FD_C_OCRResultWrapper* fd_c_ocr_result_wrapper = + FD_C_CreateOCRResultWrapper(); + auto& ocr_result = + CHECK_AND_CONVERT_FD_TYPE(OCRResultWrapper, fd_c_ocr_result_wrapper); + + bool successful = model->Predict(im, ocr_result.get()); + if (successful) { + FD_C_OCRResult* res = FD_C_OCRResultWrapperGetData(fd_c_ocr_result_wrapper); + *fd_c_ocr_result = *res; + } + return successful; +} + +PIPELINE_DECLARE_AND_IMPLEMENT_INITIALIZED_FUNCTION(PPOCRv2, + fd_c_ppocrv2_wrapper) + +FD_C_OCRResult* FD_C_OCRResultToC(fastdeploy::vision::OCRResult* ocr_result) { + // Internal use, transfer fastdeploy::vision::OCRResult to + // FD_C_OCRResult + FD_C_OCRResult* fd_c_ocr_result = new FD_C_OCRResult(); + // copy boxes + const int boxes_coordinate_dim = 8; + fd_c_ocr_result->boxes.size = ocr_result->boxes.size(); + fd_c_ocr_result->boxes.data = + new FD_C_OneDimArrayInt32[fd_c_ocr_result->boxes.size]; + for (size_t i = 0; i < ocr_result->boxes.size(); i++) { + fd_c_ocr_result->boxes.data[i].size = boxes_coordinate_dim; + fd_c_ocr_result->boxes.data[i].data = new int[boxes_coordinate_dim]; + for (size_t j = 0; j < boxes_coordinate_dim; j++) { + fd_c_ocr_result->boxes.data[i].data[j] = ocr_result->boxes[i][j]; + } + } + // copy text + fd_c_ocr_result->text.size = ocr_result->text.size(); + fd_c_ocr_result->text.data = new FD_C_Cstr[fd_c_ocr_result->text.size]; + for (size_t i = 0; i < ocr_result->text.size(); i++) { + fd_c_ocr_result->text.data[i].size = ocr_result->text[i].length(); + fd_c_ocr_result->text.data[i].data = + new char[ocr_result->text[i].length() + 1]; + strncpy(fd_c_ocr_result->text.data[i].data, ocr_result->text[i].c_str(), + ocr_result->text[i].length()); + } + + // copy rec_scores + fd_c_ocr_result->rec_scores.size = ocr_result->rec_scores.size(); + fd_c_ocr_result->rec_scores.data = + new float[fd_c_ocr_result->rec_scores.size]; + memcpy(fd_c_ocr_result->rec_scores.data, ocr_result->rec_scores.data(), + sizeof(float) * fd_c_ocr_result->rec_scores.size); + // copy cls_scores + fd_c_ocr_result->cls_scores.size = ocr_result->cls_scores.size(); + fd_c_ocr_result->cls_scores.data = + new float[fd_c_ocr_result->cls_scores.size]; + memcpy(fd_c_ocr_result->cls_scores.data, ocr_result->cls_scores.data(), + sizeof(float) * fd_c_ocr_result->cls_scores.size); + // copy cls_labels + fd_c_ocr_result->cls_labels.size = ocr_result->cls_labels.size(); + fd_c_ocr_result->cls_labels.data = + new int32_t[fd_c_ocr_result->cls_labels.size]; + memcpy(fd_c_ocr_result->cls_labels.data, ocr_result->cls_labels.data(), + sizeof(int32_t) * fd_c_ocr_result->cls_labels.size); + // copy type + fd_c_ocr_result->type = static_cast(ocr_result->type); + return fd_c_ocr_result; +} + +FD_C_Bool FD_C_PPOCRv2WrapperBatchPredict( + FD_C_PPOCRv2Wrapper* fd_c_ppocrv2_wrapper, FD_C_OneDimMat imgs, + FD_C_OneDimOCRResult* results) { + std::vector imgs_vec; + std::vector results_out; + for (int i = 0; i < imgs.size; i++) { + imgs_vec.push_back(*(reinterpret_cast(imgs.data[i]))); + } + auto& model = CHECK_AND_CONVERT_FD_TYPE(PPOCRv2Wrapper, fd_c_ppocrv2_wrapper); + bool successful = model->BatchPredict(imgs_vec, &results_out); + if (successful) { + // copy results back to FD_C_OneDimOCRResult + results->size = results_out.size(); + results->data = new FD_C_OCRResult[results->size]; + for (int i = 0; i < results_out.size(); i++) { + results->data[i] = *FD_C_OCRResultToC(&results_out[i]); + } + } + return successful; +} + +// PPOCRv3 + +FD_C_PPOCRv3Wrapper* FD_C_CreatePPOCRv3Wrapper( + FD_C_DBDetectorWrapper* fd_c_det_model_wrapper, + FD_C_ClassifierWrapper* fd_c_cls_model_wrapper, + FD_C_RecognizerWrapper* fd_c_rec_model_wrapper) { + FD_C_PPOCRv3Wrapper* fd_c_ppocrv3_wrapper = new FD_C_PPOCRv3Wrapper(); + auto& det_model = + CHECK_AND_CONVERT_FD_TYPE(DBDetectorWrapper, fd_c_det_model_wrapper); + auto& cls_model = + CHECK_AND_CONVERT_FD_TYPE(ClassifierWrapper, fd_c_cls_model_wrapper); + auto& rec_model = + CHECK_AND_CONVERT_FD_TYPE(RecognizerWrapper, fd_c_rec_model_wrapper); + fd_c_ppocrv3_wrapper->ppocrv3_model = + std::unique_ptr( + new fastdeploy::pipeline::PPOCRv3(det_model.get(), cls_model.get(), + rec_model.get())); + return fd_c_ppocrv3_wrapper; +} + +PIPELINE_DECLARE_AND_IMPLEMENT_DESTROY_WRAPPER_FUNCTION(PPOCRv3, + fd_c_ppocrv3_wrapper) + +FD_C_Bool FD_C_PPOCRv3WrapperPredict(FD_C_PPOCRv3Wrapper* fd_c_ppocrv3_wrapper, + FD_C_Mat img, + FD_C_OCRResult* fd_c_ocr_result) { + cv::Mat* im = reinterpret_cast(img); + auto& model = CHECK_AND_CONVERT_FD_TYPE(PPOCRv3Wrapper, fd_c_ppocrv3_wrapper); + FD_C_OCRResultWrapper* fd_c_ocr_result_wrapper = + FD_C_CreateOCRResultWrapper(); + auto& ocr_result = + CHECK_AND_CONVERT_FD_TYPE(OCRResultWrapper, fd_c_ocr_result_wrapper); + + bool successful = model->Predict(im, ocr_result.get()); + if (successful) { + FD_C_OCRResult* res = FD_C_OCRResultWrapperGetData(fd_c_ocr_result_wrapper); + *fd_c_ocr_result = *res; + } + return successful; +} + +PIPELINE_DECLARE_AND_IMPLEMENT_INITIALIZED_FUNCTION(PPOCRv3, + fd_c_ppocrv3_wrapper) + +FD_C_Bool FD_C_PPOCRv3WrapperBatchPredict( + FD_C_PPOCRv3Wrapper* fd_c_ppocrv3_wrapper, FD_C_OneDimMat imgs, + FD_C_OneDimOCRResult* results) { + std::vector imgs_vec; + std::vector results_out; + for (int i = 0; i < imgs.size; i++) { + imgs_vec.push_back(*(reinterpret_cast(imgs.data[i]))); + } + auto& model = CHECK_AND_CONVERT_FD_TYPE(PPOCRv3Wrapper, fd_c_ppocrv3_wrapper); + bool successful = model->BatchPredict(imgs_vec, &results_out); + if (successful) { + // copy results back to FD_C_OneDimOCRResult + results->size = results_out.size(); + results->data = new FD_C_OCRResult[results->size]; + for (int i = 0; i < results_out.size(); i++) { + results->data[i] = *FD_C_OCRResultToC(&results_out[i]); + } + } + return successful; +} + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/c_api/fastdeploy_capi/vision/ocr/ppocr/model.h b/c_api/fastdeploy_capi/vision/ocr/ppocr/model.h new file mode 100644 index 000000000..ea32c4645 --- /dev/null +++ b/c_api/fastdeploy_capi/vision/ocr/ppocr/model.h @@ -0,0 +1,348 @@ +// Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include "fastdeploy_capi/fd_common.h" +#include "fastdeploy_capi/fd_type.h" +#include "fastdeploy_capi/runtime_option.h" +#include "fastdeploy_capi/vision/result.h" +#include "fastdeploy_capi/vision/ocr/ppocr/base_define.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// Recognizer + +typedef struct FD_C_RecognizerWrapper FD_C_RecognizerWrapper; + +/** \brief Create a new FD_C_RecognizerWrapper object + * + * \param[in] model_file Path of model file, e.g ./ch_PP-OCRv3_rec_infer/model.pdmodel. + * \param[in] params_file Path of parameter file, e.g ./ch_PP-OCRv3_rec_infer/model.pdiparams, if the model format is ONNX, this parameter will be ignored. + * \param[in] label_path Path of label file used by OCR recognition model. e.g ./ppocr_keys_v1.txt + * \param[in] custom_option RuntimeOption for inference, the default will use cpu, and choose the backend defined in `valid_cpu_backends`. + * \param[in] model_format Model format of the loaded model, default is Paddle format. + * + * \return Return a pointer to FD_C_RecognizerWrapper object + */ + +FASTDEPLOY_CAPI_EXPORT extern __fd_give FD_C_RecognizerWrapper* +FD_C_CreateRecognizerWrapper( + const char* model_file, const char* params_file, const char* label_path, + FD_C_RuntimeOptionWrapper* fd_c_runtime_option_wrapper, + const FD_C_ModelFormat model_format); + +/** \brief Destroy a FD_C_RecognizerWrapper object + * + * \param[in] fd_c_recognizer_wrapper pointer to FD_C_RecognizerWrapper object + */ + +OCR_DECLARE_DESTROY_WRAPPER_FUNCTION(Recognizer, fd_c_recognizer_wrapper); + +/** \brief Predict the ocr result for an input image + * + * \param[in] fd_c_recognizer_wrapper pointer to FD_C_RecognizerWrapper object + * \param[in] img The input image data, comes from cv::imread(), is a 3-D array with layout HWC, BGR format. + * \param[in] text The text result of rec model will be written into this parameter. + * \param[in] rec_score The sccore result of rec model will be written into this parameter. + * \return true if the prediction is successed, otherwise false. + */ + +FASTDEPLOY_CAPI_EXPORT extern FD_C_Bool FD_C_RecognizerWrapperPredict( + __fd_keep FD_C_RecognizerWrapper* fd_c_recognizer_wrapper, FD_C_Mat img, + FD_C_Cstr* text, float* rec_score); + +/** \brief Check if the model is initialized successfully + * + * \param[in] fd_c_recognizer_wrapper pointer to FD_C_RecognizerWrapper object + * + * \return Return a bool of value true if initialized successfully + */ + +OCR_DECLARE_INITIALIZED_FUNCTION(Recognizer, fd_c_recognizer_wrapper); + +/** \brief Predict the ocr results for a batch of input images + * + * \param[in] fd_c_recognizer_wrapper pointer to FD_C_RecognizerWrapper object + * \param[in] imgs The list of input image data, comes from cv::imread(), is a 3-D array with layout HWC, BGR format. + * \param[in] texts The list of text results of rec model will be written into this vector. + * \param[in] rec_scores The list of sccore result of rec model will be written into this vector. + * + * \return true if the prediction successed, otherwise false + */ + +FASTDEPLOY_CAPI_EXPORT extern FD_C_Bool FD_C_RecognizerWrapperBatchPredict( + __fd_keep FD_C_RecognizerWrapper* fd_c_recognizer_wrapper, FD_C_OneDimMat imgs, + FD_C_OneDimArrayCstr* texts, FD_C_OneDimArrayFloat* rec_scores); + +FASTDEPLOY_CAPI_EXPORT extern FD_C_Bool FD_C_RecognizerWrapperBatchPredictWithIndex( + __fd_keep FD_C_RecognizerWrapper* fd_c_recognizer_wrapper, FD_C_OneDimMat imgs, + FD_C_OneDimArrayCstr* texts, FD_C_OneDimArrayFloat* rec_scores, + size_t start_index, size_t end_index, + FD_C_OneDimArrayInt32 indices); + + +// Classifier + +typedef struct FD_C_ClassifierWrapper FD_C_ClassifierWrapper; + +/** \brief Create a new FD_C_ClassifierWrapper object + * + * \param[in] model_file Path of model file, e.g ./ch_ppocr_mobile_v2.0_cls_infer/model.pdmodel. + * \param[in] params_file Path of parameter file, e.g ./ch_ppocr_mobile_v2.0_cls_infer/model.pdiparams, if the model format is ONNX, this parameter will be ignored. + * \param[in] fd_c_runtime_option_wrapper RuntimeOption for inference, the default will use cpu, and choose the backend defined in `valid_cpu_backends`. + * \param[in] model_format Model format of the loaded model, default is Paddle format. + * + * \return Return a pointer to FD_C_ClassifierWrapper object + */ + +FASTDEPLOY_CAPI_EXPORT extern __fd_give FD_C_ClassifierWrapper* +FD_C_CreateClassifierWrapper( + const char* model_file, const char* params_file, + FD_C_RuntimeOptionWrapper* fd_c_runtime_option_wrapper, + const FD_C_ModelFormat model_format); + +/** \brief Destroy a FD_C_ClassifierWrapper object + * + * \param[in] fd_c_classifier_wrapper pointer to FD_C_ClassifierWrapper object + */ + +OCR_DECLARE_DESTROY_WRAPPER_FUNCTION(Classifier, fd_c_classifier_wrapper); + +/** \brief Predict the input image and get OCR classification model cls_result. + * + * \param[in] fd_c_classifier_wrapper pointer to FD_C_ClassifierWrapper object + * \param[in] img The input image data, comes from cv::imread(), is a 3-D array with layout HWC, BGR format. + * \param[in] cls_label The label result of cls model will be written in to this param. + * \param[in] cls_score The score result of cls model will be written in to this param. + * \return true if the prediction is successed, otherwise false. + */ + +FASTDEPLOY_CAPI_EXPORT extern FD_C_Bool FD_C_ClassifierWrapperPredict( + __fd_keep FD_C_ClassifierWrapper* fd_c_classifier_wrapper, FD_C_Mat img, + int32_t* cls_label, float* cls_score); + +/** \brief Check if the model is initialized successfully + * + * \param[in] fd_c_classifier_wrapper pointer to FD_C_ClassifierWrapper object + * + * \return Return a bool of value true if initialized successfully + */ + +OCR_DECLARE_INITIALIZED_FUNCTION(Classifier, fd_c_classifier_wrapper); + +/** \brief BatchPredict the input image and get OCR classification model cls_result. + * + * \param[in] fd_c_classifier_wrapper pointer to FD_C_ClassifierWrapper object + * \param[in] imgs The list of input image data, comes from cv::imread(), is a 3-D array with layout HWC, BGR format. + * \param[in] cls_labels The label results of cls model will be written in to this vector. + * \param[in] cls_scores The score results of cls model will be written in to this vector. + * \return true if the prediction is successed, otherwise false. + */ + +FASTDEPLOY_CAPI_EXPORT extern FD_C_Bool FD_C_ClassifierWrapperBatchPredict( + __fd_keep FD_C_ClassifierWrapper* fd_c_classifier_wrapper, FD_C_OneDimMat imgs, + FD_C_OneDimArrayInt32* cls_labels, FD_C_OneDimArrayFloat* cls_scores); + +FASTDEPLOY_CAPI_EXPORT extern FD_C_Bool FD_C_ClassifierWrapperBatchPredictWithIndex( + __fd_keep FD_C_ClassifierWrapper* fd_c_classifier_wrapper, FD_C_OneDimMat imgs, + FD_C_OneDimArrayInt32* cls_labels, FD_C_OneDimArrayFloat* cls_scores, + size_t start_index, size_t end_index); + + +// DBDetector + +typedef struct FD_C_DBDetectorWrapper FD_C_DBDetectorWrapper; + +/** \brief Create a new FD_C_DBDetectorWrapper object + * + * \param[in] model_file Path of model file, e.g ./ch_PP-OCRv3_det_infer/model.pdmodel. + * \param[in] params_file Path of parameter file, e.g ./ch_PP-OCRv3_det_infer/model.pdiparams, if the model format is ONNX, this parameter will be ignored. + * \param[in] custom_option RuntimeOption for inference, the default will use cpu, and choose the backend defined in `valid_cpu_backends`. + * \param[in] model_format Model format of the loaded model, default is Paddle format. + * + * \return Return a pointer to FD_C_DBDetectorWrapper object + */ + +FASTDEPLOY_CAPI_EXPORT extern __fd_give FD_C_DBDetectorWrapper* +FD_C_CreateDBDetectorWrapper( + const char* model_file, const char* params_file, + FD_C_RuntimeOptionWrapper* fd_c_runtime_option_wrapper, + const FD_C_ModelFormat model_format); + +/** \brief Destroy a FD_C_DBDetectorWrapper object + * + * \param[in] fd_c_dbdetector_wrapper pointer to FD_C_DBDetectorWrapper object + */ + +OCR_DECLARE_DESTROY_WRAPPER_FUNCTION(DBDetector, fd_c_dbdetector_wrapper); + +/** \brief Predict the input image and get OCR detection model result. + * + * \param[in] fd_c_dbdetector_wrapper pointer to FD_C_DBDetectorWrapper object + * \param[in] img The input image data, comes from cv::imread(), is a 3-D array with layout HWC, BGR format. + * \param[in] boxes_result The output of OCR detection model result will be writen to this structure. + * \return true if the prediction is successed, otherwise false. + */ + +FASTDEPLOY_CAPI_EXPORT extern FD_C_Bool FD_C_DBDetectorWrapperPredict( + __fd_keep FD_C_DBDetectorWrapper* fd_c_dbdetector_wrapper, FD_C_Mat img, + FD_C_TwoDimArrayInt32* boxes_result); + +/** \brief Check if the model is initialized successfully + * + * \param[in] fd_c_dbdetector_wrapper pointer to FD_C_DBDetectorWrapper object + * + * \return Return a bool of value true if initialized successfully + */ + +OCR_DECLARE_INITIALIZED_FUNCTION(DBDetector, fd_c_dbdetector_wrapper); + +/** \brief BatchPredict the input image and get OCR detection model result. + * + * \param[in] fd_c_dbdetector_wrapper pointer to FD_C_DBDetectorWrapper object + * \param[in] imgs The list input of image data, comes from cv::imread(), is a 3-D array with layout HWC, BGR format. + * \param[in] det_results The output of OCR detection model result will be writen to this structure. + * + * \return true if the prediction is successed, otherwise false. + */ + +FASTDEPLOY_CAPI_EXPORT extern FD_C_Bool FD_C_DBDetectorWrapperBatchPredict( + __fd_keep FD_C_DBDetectorWrapper* fd_c_dbdetector_wrapper, FD_C_OneDimMat imgs, + FD_C_ThreeDimArrayInt32* det_results); + + +// PPOCRv2 + + +typedef struct FD_C_PPOCRv2Wrapper FD_C_PPOCRv2Wrapper; + +/** \brief Set up the detection model path, classification model path and recognition model path respectively. + * + * \param[in] det_model Path of detection model, e.g ./ch_PP-OCRv2_det_infer + * \param[in] cls_model Path of classification model, e.g ./ch_ppocr_mobile_v2.0_cls_infer + * \param[in] rec_model Path of recognition model, e.g ./ch_PP-OCRv2_rec_infer + */ + +FASTDEPLOY_CAPI_EXPORT extern __fd_give FD_C_PPOCRv2Wrapper* +FD_C_CreatePPOCRv2Wrapper( + FD_C_DBDetectorWrapper* det_model, + FD_C_ClassifierWrapper* cls_model, + FD_C_RecognizerWrapper* rec_model); + +/** \brief Destroy a FD_C_PPOCRv2Wrapper object + * + * \param[in] fd_c_ppocrv2_wrapper pointer to FD_C_PPOCRv2Wrapper object + */ + +OCR_DECLARE_DESTROY_WRAPPER_FUNCTION(PPOCRv2, fd_c_ppocrv2_wrapper); + +/** \brief Predict the input image and get OCR result. + * + * \param[in] fd_c_ppocrv2_wrapper pointer to FD_C_PPOCRv2Wrapper object + * \param[in] img The input image data, comes from cv::imread(), is a 3-D array with layout HWC, BGR format. + * \param[in] result The output OCR result will be writen to this structure. + * \return true if the prediction successed, otherwise false. + */ + +FASTDEPLOY_CAPI_EXPORT extern FD_C_Bool FD_C_PPOCRv2WrapperPredict( + __fd_keep FD_C_PPOCRv2Wrapper* fd_c_ppocrv2_wrapper, FD_C_Mat img, + FD_C_OCRResult* result); + +/** \brief Check if the model is initialized successfully + * + * \param[in] fd_c_ppocrv2_wrapper pointer to FD_C_PPOCRv2Wrapper object + * + * \return Return a bool of value true if initialized successfully + */ + +OCR_DECLARE_INITIALIZED_FUNCTION(PPOCRv2, fd_c_ppocrv2_wrapper); + +/** \brief BatchPredict the input image and get OCR result. + * + * \param[in] fd_c_ppocrv2_wrapper pointer to FD_C_PPOCRv2Wrapper object + * \param[in] imgs The list of input image data, comes from cv::imread(), is a 3-D array with layout HWC, BGR format. + * \param[in] batch_result The output list of OCR result will be writen to this structure. + * \return true if the prediction successed, otherwise false. + */ + +FASTDEPLOY_CAPI_EXPORT extern FD_C_Bool FD_C_PPOCRv2WrapperBatchPredict( + __fd_keep FD_C_PPOCRv2Wrapper* fd_c_ppocrv2_wrapper, FD_C_OneDimMat imgs, + FD_C_OneDimOCRResult* batch_result); + + + +// PPOCRv3 + +typedef struct FD_C_PPOCRv3Wrapper FD_C_PPOCRv3Wrapper; + +/** \brief Set up the detection model path, classification model path and recognition model path respectively. + * + * \param[in] det_model Path of detection model, e.g ./ch_PP-OCRv2_det_infer + * \param[in] cls_model Path of classification model, e.g ./ch_ppocr_mobile_v2.0_cls_infer + * \param[in] rec_model Path of recognition model, e.g ./ch_PP-OCRv2_rec_infer + */ + +FASTDEPLOY_CAPI_EXPORT extern __fd_give FD_C_PPOCRv3Wrapper* +FD_C_CreatePPOCRv3Wrapper( + FD_C_DBDetectorWrapper* det_model, + FD_C_ClassifierWrapper* cls_model, + FD_C_RecognizerWrapper* rec_model); + +/** \brief Destroy a FD_C_PPOCRv3Wrapper object + * + * \param[in] fd_c_ppocrv3_wrapper pointer to FD_C_PPOCRv3Wrapper object + */ + +OCR_DECLARE_DESTROY_WRAPPER_FUNCTION(PPOCRv3, fd_c_ppocrv3_wrapper); + +/** \brief Predict the input image and get OCR result. + * + * \param[in] fd_c_ppocrv3_wrapper pointer to FD_C_PPOCRv3Wrapper object + * \param[in] img The input image data, comes from cv::imread(), is a 3-D array with layout HWC, BGR format. + * \param[in] result The output OCR result will be writen to this structure. + * \return true if the prediction successed, otherwise false. + */ + +FASTDEPLOY_CAPI_EXPORT extern FD_C_Bool FD_C_PPOCRv3WrapperPredict( + __fd_keep FD_C_PPOCRv3Wrapper* fd_c_ppocrv3_wrapper, FD_C_Mat img, + FD_C_OCRResult* result); + +/** \brief Check if the model is initialized successfully + * + * \param[in] fd_c_ppocrv3_wrapper pointer to FD_C_PPOCRv3Wrapper object + * + * \return Return a bool of value true if initialized successfully + */ + +OCR_DECLARE_INITIALIZED_FUNCTION(PPOCRv3, fd_c_ppocrv3_wrapper); + +/** \brief BatchPredict the input image and get OCR result. + * + * \param[in] fd_c_ppocrv3_wrapper pointer to FD_C_PPOCRv3Wrapper object + * \param[in] imgs The list of input image data, comes from cv::imread(), is a 3-D array with layout HWC, BGR format. + * \param[in] batch_result The output list of OCR result will be writen to this structure. + * \return true if the prediction successed, otherwise false. + */ + +FASTDEPLOY_CAPI_EXPORT extern FD_C_Bool FD_C_PPOCRv3WrapperBatchPredict( + __fd_keep FD_C_PPOCRv3Wrapper* fd_c_ppocrv3_wrapper, FD_C_OneDimMat imgs, + FD_C_OneDimOCRResult* batch_result); + + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/c_api/fastdeploy_capi/vision/result.cc b/c_api/fastdeploy_capi/vision/result.cc index 175c6b29c..f8dfd5cdf 100644 --- a/c_api/fastdeploy_capi/vision/result.cc +++ b/c_api/fastdeploy_capi/vision/result.cc @@ -258,6 +258,146 @@ char* FD_C_DetectionResultWrapperStr( return cstr; } +// OCR Results + +FD_C_OCRResultWrapper* FD_C_CreateOCRResultWrapper() { + FD_C_OCRResultWrapper* fd_c_ocr_result_wrapper = new FD_C_OCRResultWrapper(); + fd_c_ocr_result_wrapper->ocr_result = + std::unique_ptr( + new fastdeploy::vision::OCRResult()); + return fd_c_ocr_result_wrapper; +} + +void FD_C_DestroyOCRResultWrapper( + __fd_take FD_C_OCRResultWrapper* fd_c_ocr_result_wrapper) { + delete fd_c_ocr_result_wrapper; +} + +void FD_C_DestroyOCRResult(__fd_take FD_C_OCRResult* fd_c_ocr_result) { + if (fd_c_ocr_result == nullptr) return; + // delete boxes + for (size_t i = 0; i < fd_c_ocr_result->boxes.size; i++) { + delete[] fd_c_ocr_result->boxes.data[i].data; + } + delete[] fd_c_ocr_result->boxes.data; + // delete text + for (size_t i = 0; i < fd_c_ocr_result->text.size; i++) { + delete[] fd_c_ocr_result->text.data[i].data; + } + delete[] fd_c_ocr_result->text.data; + // delete rec_scores + delete[] fd_c_ocr_result->rec_scores.data; + // delete cls_scores + delete[] fd_c_ocr_result->cls_scores.data; + // delete cls_labels + delete[] fd_c_ocr_result->cls_labels.data; + delete fd_c_ocr_result; +} + +FD_C_OCRResult* FD_C_OCRResultWrapperGetData( + __fd_keep FD_C_OCRResultWrapper* fd_c_ocr_result_wrapper) { + auto& ocr_result = + CHECK_AND_CONVERT_FD_TYPE(OCRResultWrapper, fd_c_ocr_result_wrapper); + FD_C_OCRResult* fd_c_ocr_result = new FD_C_OCRResult(); + // copy boxes + const int boxes_coordinate_dim = 8; + fd_c_ocr_result->boxes.size = ocr_result->boxes.size(); + fd_c_ocr_result->boxes.data = + new FD_C_OneDimArrayInt32[fd_c_ocr_result->boxes.size]; + for (size_t i = 0; i < ocr_result->boxes.size(); i++) { + fd_c_ocr_result->boxes.data[i].size = boxes_coordinate_dim; + fd_c_ocr_result->boxes.data[i].data = new int[boxes_coordinate_dim]; + for (size_t j = 0; j < boxes_coordinate_dim; j++) { + fd_c_ocr_result->boxes.data[i].data[j] = ocr_result->boxes[i][j]; + } + } + // copy text + fd_c_ocr_result->text.size = ocr_result->text.size(); + fd_c_ocr_result->text.data = new FD_C_Cstr[fd_c_ocr_result->text.size]; + for (size_t i = 0; i < ocr_result->text.size(); i++) { + fd_c_ocr_result->text.data[i].size = ocr_result->text[i].length(); + fd_c_ocr_result->text.data[i].data = + new char[ocr_result->text[i].length() + 1]; + strncpy(fd_c_ocr_result->text.data[i].data, ocr_result->text[i].c_str(), + ocr_result->text[i].length()); + } + + // copy rec_scores + fd_c_ocr_result->rec_scores.size = ocr_result->rec_scores.size(); + fd_c_ocr_result->rec_scores.data = + new float[fd_c_ocr_result->rec_scores.size]; + memcpy(fd_c_ocr_result->rec_scores.data, ocr_result->rec_scores.data(), + sizeof(float) * fd_c_ocr_result->rec_scores.size); + // copy cls_scores + fd_c_ocr_result->cls_scores.size = ocr_result->cls_scores.size(); + fd_c_ocr_result->cls_scores.data = + new float[fd_c_ocr_result->cls_scores.size]; + memcpy(fd_c_ocr_result->cls_scores.data, ocr_result->cls_scores.data(), + sizeof(float) * fd_c_ocr_result->cls_scores.size); + // copy cls_labels + fd_c_ocr_result->cls_labels.size = ocr_result->cls_labels.size(); + fd_c_ocr_result->cls_labels.data = + new int32_t[fd_c_ocr_result->cls_labels.size]; + memcpy(fd_c_ocr_result->cls_labels.data, ocr_result->cls_labels.data(), + sizeof(int32_t) * fd_c_ocr_result->cls_labels.size); + // copy type + fd_c_ocr_result->type = static_cast(ocr_result->type); + return fd_c_ocr_result; +} + +FD_C_OCRResultWrapper* FD_C_CreateOCRResultWrapperFromData( + __fd_keep FD_C_OCRResult* fd_c_ocr_result) { + FD_C_OCRResultWrapper* fd_c_ocr_result_wrapper = + FD_C_CreateOCRResultWrapper(); + auto& ocr_result = + CHECK_AND_CONVERT_FD_TYPE(OCRResultWrapper, fd_c_ocr_result_wrapper); + + // copy boxes + const int boxes_coordinate_dim = 8; + ocr_result->boxes.resize(fd_c_ocr_result->boxes.size); + for (size_t i = 0; i < fd_c_ocr_result->boxes.size; i++) { + for (size_t j = 0; j < boxes_coordinate_dim; j++) { + ocr_result->boxes[i][j] = fd_c_ocr_result->boxes.data[i].data[j]; + } + } + + // copy text + ocr_result->text.resize(fd_c_ocr_result->text.size); + for (size_t i = 0; i < ocr_result->text.size(); i++) { + ocr_result->text[i] = std::string(fd_c_ocr_result->text.data[i].data); + } + + // copy rec_scores + ocr_result->rec_scores.resize(fd_c_ocr_result->rec_scores.size); + memcpy(ocr_result->rec_scores.data(), fd_c_ocr_result->rec_scores.data, + sizeof(float) * fd_c_ocr_result->rec_scores.size); + + // copy cls_scores + ocr_result->cls_scores.resize(fd_c_ocr_result->cls_scores.size); + memcpy(ocr_result->cls_scores.data(), fd_c_ocr_result->cls_scores.data, + sizeof(float) * fd_c_ocr_result->cls_scores.size); + + // copy cls_labels + ocr_result->cls_labels.resize(fd_c_ocr_result->cls_labels.size); + memcpy(ocr_result->cls_labels.data(), fd_c_ocr_result->cls_labels.data, + sizeof(int32_t) * fd_c_ocr_result->cls_labels.size); + + // copy type + ocr_result->type = + static_cast(fd_c_ocr_result->type); + + return fd_c_ocr_result_wrapper; +} + +char* FD_C_OCRResultWrapperStr(FD_C_OCRResultWrapper* fd_c_ocr_result_wrapper) { + auto& ocr_result = + CHECK_AND_CONVERT_FD_TYPE(OCRResultWrapper, fd_c_ocr_result_wrapper); + std::string information = ocr_result->Str(); + char* cstr = new char[information.length() + 1]; + std::strcpy(cstr, information.c_str()); + return cstr; +} + #ifdef __cplusplus } #endif diff --git a/c_api/fastdeploy_capi/vision/result.h b/c_api/fastdeploy_capi/vision/result.h index 40a846af4..7da7d1538 100644 --- a/c_api/fastdeploy_capi/vision/result.h +++ b/c_api/fastdeploy_capi/vision/result.h @@ -19,6 +19,7 @@ typedef struct FD_C_ClassifyResultWrapper FD_C_ClassifyResultWrapper; typedef struct FD_C_DetectionResultWrapper FD_C_DetectionResultWrapper; +typedef struct FD_C_OCRResultWrapper FD_C_OCRResultWrapper; #ifdef __cplusplus extern "C" { @@ -60,6 +61,21 @@ typedef struct FD_C_OneDimDetectionResult { FD_C_DetectionResult* data; } FD_C_OneDimDetectionResult; + +typedef struct FD_C_OCRResult { + FD_C_TwoDimArrayInt32 boxes; + FD_C_OneDimArrayCstr text; + FD_C_OneDimArrayFloat rec_scores; + FD_C_OneDimArrayFloat cls_scores; + FD_C_OneDimArrayInt32 cls_labels; + FD_C_ResultType type; +} FD_C_OCRResult; + +typedef struct FD_C_OneDimOCRResult { + size_t size; + FD_C_OCRResult* data; +} FD_C_OneDimOCRResult; + // Classification Results /** \brief Create a new FD_C_ClassifyResultWrapper object @@ -170,6 +186,63 @@ FASTDEPLOY_CAPI_EXPORT extern __fd_give char* FD_C_DetectionResultWrapperStr( __fd_keep FD_C_DetectionResultWrapper* fd_c_detection_result_wrapper); + +// OCR Results + +/** \brief Create a new FD_C_OCRResultWrapper object + * + * \return Return a pointer to FD_C_OCRResultWrapper object + */ + +FASTDEPLOY_CAPI_EXPORT extern __fd_give FD_C_OCRResultWrapper* +FD_C_CreateOCRResultWrapper(); + +/** \brief Destroy a FD_C_OCRResultWrapper object + * + * \param[in] fd_c_ocr_result_wrapper pointer to FD_C_OCRResultWrapper object + */ + +FASTDEPLOY_CAPI_EXPORT extern void FD_C_DestroyOCRResultWrapper( + __fd_take FD_C_OCRResultWrapper* fd_c_ocr_result_wrapper); + +/** \brief Destroy a FD_C_OCRResult object + * + * \param[in] fd_c_ocr_result pointer to FD_C_OCRResult object + */ + +FASTDEPLOY_CAPI_EXPORT extern void FD_C_DestroyOCRResult( + __fd_take FD_C_OCRResult* fd_c_ocr_result); + +/** \brief Get a FD_C_OCRResult object from FD_C_OCRResultWrapper object + * + * \param[in] fd_c_ocr_result_wrapper pointer to FD_C_OCRResultWrapper object + * \return Return a pointer to FD_C_OCRResult object + */ +FASTDEPLOY_CAPI_EXPORT extern __fd_give FD_C_OCRResult* +FD_C_OCRResultWrapperGetData( + __fd_keep FD_C_OCRResultWrapper* fd_c_ocr_result_wrapper); + +/** \brief Create a new FD_C_OCRResultWrapper object from FD_C_OCRResult object + * + * \param[in] fd_c_ocr_result pointer to FD_C_OCRResult object + * \return Return a pointer to FD_C_OCRResultWrapper object + */ + +FASTDEPLOY_CAPI_EXPORT extern __fd_give FD_C_OCRResultWrapper* +FD_C_CreateOCRResultWrapperFromData( + __fd_keep FD_C_OCRResult* fd_c_ocr_result); + +/** \brief Print OCRResult formated information + * + * \param[in] fd_c_ocr_result_wrapper pointer to FD_C_OCRResultWrapper object + * \return Return a string pointer + */ + +FASTDEPLOY_CAPI_EXPORT extern __fd_give char* +FD_C_OCRResultWrapperStr( + __fd_keep FD_C_OCRResultWrapper* fd_c_ocr_result_wrapper); + + #ifdef __cplusplus } // extern "C" #endif diff --git a/c_api/fastdeploy_capi/vision/visualize.cc b/c_api/fastdeploy_capi/vision/visualize.cc index ffa0b0939..ab138c3a9 100644 --- a/c_api/fastdeploy_capi/vision/visualize.cc +++ b/c_api/fastdeploy_capi/vision/visualize.cc @@ -54,6 +54,48 @@ FD_C_Mat FD_C_VisDetectionWithLabel(FD_C_Mat im, return new cv::Mat(result); } +FD_C_Mat FD_C_VisClassification(FD_C_Mat im, + FD_C_ClassifyResult* fd_c_classify_result, + int top_k, float score_threshold, + float font_size) { + FD_C_ClassifyResultWrapper* fd_c_classify_result_wrapper = + FD_C_CreateClassifyResultWrapperFromData(fd_c_classify_result); + auto& classify_result = CHECK_AND_CONVERT_FD_TYPE( + ClassifyResultWrapper, fd_c_classify_result_wrapper); + cv::Mat result = fastdeploy::vision::VisClassification( + *(reinterpret_cast(im)), *classify_result, top_k, + score_threshold, font_size); + return new cv::Mat(result); +} + +FD_C_Mat FD_C_VisClassificationWithLabel( + FD_C_Mat im, FD_C_ClassifyResult* fd_c_classify_result, + FD_C_OneDimArrayCstr* labels, int top_k, float score_threshold, + float font_size) { + std::vector labels_in; + for (int i = 0; i < labels->size; i++) { + labels_in.emplace_back(labels->data[i].data); + } + FD_C_ClassifyResultWrapper* fd_c_classify_result_wrapper = + FD_C_CreateClassifyResultWrapperFromData(fd_c_classify_result); + auto& classify_result = CHECK_AND_CONVERT_FD_TYPE( + ClassifyResultWrapper, fd_c_classify_result_wrapper); + cv::Mat result = fastdeploy::vision::VisClassification( + *(reinterpret_cast(im)), *classify_result, labels_in, top_k, + score_threshold, font_size); + return new cv::Mat(result); +} + +FD_C_Mat FD_C_VisOcr(FD_C_Mat im, FD_C_OCRResult* fd_c_ocr_result) { + FD_C_OCRResultWrapper* fd_c_ocr_result_wrapper = + FD_C_CreateOCRResultWrapperFromData(fd_c_ocr_result); + auto& ocr_result = + CHECK_AND_CONVERT_FD_TYPE(OCRResultWrapper, fd_c_ocr_result_wrapper); + cv::Mat result = fastdeploy::vision::VisOcr(*(reinterpret_cast(im)), + *ocr_result); + return new cv::Mat(result); +} + #ifdef __cplusplus } #endif diff --git a/c_api/fastdeploy_capi/vision/visualize.h b/c_api/fastdeploy_capi/vision/visualize.h index ca5bfcab3..e30d2939f 100644 --- a/c_api/fastdeploy_capi/vision/visualize.h +++ b/c_api/fastdeploy_capi/vision/visualize.h @@ -53,6 +53,43 @@ FASTDEPLOY_CAPI_EXPORT extern __fd_give FD_C_Mat FD_C_VisDetectionWithLabel( float score_threshold, int line_size, float font_size); +/** \brief Show the visualized results for classification models + * + * \param[in] im the input image data, comes from cv::imread(), is a 3-D array with layout HWC, BGR format + * \param[in] result the result produced by model + * \param[in] top_k the length of return values, e.g., if topk==2, the result will include the 2 most possible class label for input image. + * \param[in] score_threshold threshold for top_k scores, the class will not be shown if the score is less than score_threshold + * \param[in] font_size font size + * \return cv::Mat type stores the visualized results + */ +FASTDEPLOY_CAPI_EXPORT extern __fd_give FD_C_Mat FD_C_VisClassification( + FD_C_Mat im, FD_C_ClassifyResult* result, int top_k, + float score_threshold, float font_size); +/** \brief Show the visualized results with custom labels for classification models + * + * \param[in] im the input image data, comes from cv::imread(), is a 3-D array with layout HWC, BGR format + * \param[in] result the result produced by model + * \param[in] labels custom labels for user, the visualized result will show the corresponding custom labels + * \param[in] top_k the length of return values, e.g., if topk==2, the result will include the 2 most possible class label for input image. + * \param[in] score_threshold threshold for top_k scores, the class will not be shown if the score is less than score_threshold + * \param[in] font_size font size + * \return cv::Mat type stores the visualized results + */ +FASTDEPLOY_CAPI_EXPORT extern __fd_give FD_C_Mat FD_C_VisClassificationWithLabel( + FD_C_Mat im, FD_C_ClassifyResult* result, + FD_C_OneDimArrayCstr* labels, int top_k, + float score_threshold, float font_size); + + +/** \brief Show the visualized results for Ocr models + * + * \param[in] im the input image data, comes from cv::imread(), is a 3-D array with layout HWC, BGR format + * \param[in] result the result produced by model + * \return cv::Mat type stores the visualized results + */ +FASTDEPLOY_CAPI_EXPORT extern __fd_give FD_C_Mat FD_C_VisOcr(FD_C_Mat im, FD_C_OCRResult* ocr_result); + + #ifdef __cplusplus } // extern "C" #endif diff --git a/examples/vision/ocr/PP-OCRv2/c/CMakeLists.txt b/examples/vision/ocr/PP-OCRv2/c/CMakeLists.txt new file mode 100644 index 000000000..b228346da --- /dev/null +++ b/examples/vision/ocr/PP-OCRv2/c/CMakeLists.txt @@ -0,0 +1,13 @@ +PROJECT(infer_demo C) +CMAKE_MINIMUM_REQUIRED (VERSION 3.10) + +# 指定下载解压后的fastdeploy库路径 +option(FASTDEPLOY_INSTALL_DIR "Path of downloaded fastdeploy sdk.") + +include(${FASTDEPLOY_INSTALL_DIR}/FastDeploy.cmake) + +# 添加FastDeploy依赖头文件 +include_directories(${FASTDEPLOY_INCS}) + +add_executable(infer_demo ${PROJECT_SOURCE_DIR}/infer.c) +target_link_libraries(infer_demo ${FASTDEPLOY_LIBS}) diff --git a/examples/vision/ocr/PP-OCRv2/c/infer.c b/examples/vision/ocr/PP-OCRv2/c/infer.c new file mode 100644 index 000000000..d5918bf13 --- /dev/null +++ b/examples/vision/ocr/PP-OCRv2/c/infer.c @@ -0,0 +1,262 @@ +// Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include + +#include "fastdeploy_capi/vision.h" + +#ifdef WIN32 +const char sep = '\\'; +#else +const char sep = '/'; +#endif + +void CpuInfer(const char* det_model_dir, const char* cls_model_dir, + const char* rec_model_dir, const char* rec_label_file, + const char* image_file) { + char det_model_file[100]; + char det_params_file[100]; + + char cls_model_file[100]; + char cls_params_file[100]; + + char rec_model_file[100]; + char rec_params_file[100]; + + int max_size = 99; + snprintf(det_model_file, max_size, "%s%c%s", det_model_dir, sep, + "inference.pdmodel"); + snprintf(det_params_file, max_size, "%s%c%s", det_model_dir, sep, + "inference.pdiparams"); + + snprintf(cls_model_file, max_size, "%s%c%s", cls_model_dir, sep, + "inference.pdmodel"); + snprintf(cls_params_file, max_size, "%s%c%s", cls_model_dir, sep, + "inference.pdiparams"); + + snprintf(rec_model_file, max_size, "%s%c%s", rec_model_dir, sep, + "inference.pdmodel"); + snprintf(rec_params_file, max_size, "%s%c%s", rec_model_dir, sep, + "inference.pdiparams"); + + FD_C_RuntimeOptionWrapper* det_option = FD_C_CreateRuntimeOptionWrapper(); + FD_C_RuntimeOptionWrapper* cls_option = FD_C_CreateRuntimeOptionWrapper(); + FD_C_RuntimeOptionWrapper* rec_option = FD_C_CreateRuntimeOptionWrapper(); + FD_C_RuntimeOptionWrapperUseCpu(det_option); + FD_C_RuntimeOptionWrapperUseCpu(cls_option); + FD_C_RuntimeOptionWrapperUseCpu(rec_option); + + FD_C_DBDetectorWrapper* det_model = FD_C_CreateDBDetectorWrapper( + det_model_file, det_params_file, det_option, PADDLE); + FD_C_ClassifierWrapper* cls_model = FD_C_CreateClassifierWrapper( + cls_model_file, cls_params_file, cls_option, PADDLE); + FD_C_RecognizerWrapper* rec_model = FD_C_CreateRecognizerWrapper( + rec_model_file, rec_params_file, rec_label_file, rec_option, PADDLE); + + FD_C_PPOCRv2Wrapper* ppocr_v2 = + FD_C_CreatePPOCRv2Wrapper(det_model, cls_model, rec_model); + if (!FD_C_PPOCRv2WrapperInitialized(ppocr_v2)) { + printf("Failed to initialize.\n"); + FD_C_DestroyRuntimeOptionWrapper(det_option); + FD_C_DestroyRuntimeOptionWrapper(cls_option); + FD_C_DestroyRuntimeOptionWrapper(rec_option); + FD_C_DestroyClassifierWrapper(cls_model); + FD_C_DestroyDBDetectorWrapper(det_model); + FD_C_DestroyRecognizerWrapper(rec_model); + FD_C_DestroyPPOCRv2Wrapper(ppocr_v2); + return; + } + + FD_C_Mat im = FD_C_Imread(image_file); + + FD_C_OCRResult* result = (FD_C_OCRResult*)malloc(sizeof(FD_C_OCRResult)); + + if (!FD_C_PPOCRv2WrapperPredict(ppocr_v2, im, result)) { + printf("Failed to predict.\n"); + FD_C_DestroyRuntimeOptionWrapper(det_option); + FD_C_DestroyRuntimeOptionWrapper(cls_option); + FD_C_DestroyRuntimeOptionWrapper(rec_option); + FD_C_DestroyClassifierWrapper(cls_model); + FD_C_DestroyDBDetectorWrapper(det_model); + FD_C_DestroyRecognizerWrapper(rec_model); + FD_C_DestroyPPOCRv2Wrapper(ppocr_v2); + FD_C_DestroyMat(im); + free(result); + return; + } + + // print res + // You can directly access fields in FD_C_OCRResult and print it refer to + // OCRResult API Doc Or you can wrap it using + // FD_C_OCRResult_Wrapper, which containes C++ structure + // fastdeploy::vision::OCRResult, and using C API + // FD_C_OCRResultWrapperStr to call + // fastdeploy::vision::OCRResult::Str() in it. For convenience, we choose + // this method to print it. + FD_C_OCRResultWrapper* result_wrapper = + FD_C_CreateOCRResultWrapperFromData(result); + printf("%s", FD_C_OCRResultWrapperStr(result_wrapper)); + FD_C_Mat vis_im = FD_C_VisOcr(im, result); + FD_C_Imwrite("vis_result.jpg", vis_im); + printf("Visualized result saved in ./vis_result.jpg\n"); + + FD_C_DestroyRuntimeOptionWrapper(det_option); + FD_C_DestroyRuntimeOptionWrapper(cls_option); + FD_C_DestroyRuntimeOptionWrapper(rec_option); + FD_C_DestroyClassifierWrapper(cls_model); + FD_C_DestroyDBDetectorWrapper(det_model); + FD_C_DestroyRecognizerWrapper(rec_model); + FD_C_DestroyPPOCRv2Wrapper(ppocr_v2); + FD_C_DestroyOCRResultWrapper(result_wrapper); + FD_C_DestroyOCRResult(result); + FD_C_DestroyMat(im); +} + +void GpuInfer(const char* det_model_dir, const char* cls_model_dir, + const char* rec_model_dir, const char* rec_label_file, + const char* image_file) { + char det_model_file[100]; + char det_params_file[100]; + + char cls_model_file[100]; + char cls_params_file[100]; + + char rec_model_file[100]; + char rec_params_file[100]; + + int max_size = 99; + snprintf(det_model_file, max_size, "%s%c%s", det_model_dir, sep, + "inference.pdmodel"); + snprintf(det_params_file, max_size, "%s%c%s", det_model_dir, sep, + "inference.pdiparams"); + + snprintf(cls_model_file, max_size, "%s%c%s", cls_model_dir, sep, + "inference.pdmodel"); + snprintf(cls_params_file, max_size, "%s%c%s", cls_model_dir, sep, + "inference.pdiparams"); + + snprintf(rec_model_file, max_size, "%s%c%s", rec_model_dir, sep, + "inference.pdmodel"); + snprintf(rec_params_file, max_size, "%s%c%s", rec_model_dir, sep, + "inference.pdiparams"); + + FD_C_RuntimeOptionWrapper* det_option = FD_C_CreateRuntimeOptionWrapper(); + FD_C_RuntimeOptionWrapper* cls_option = FD_C_CreateRuntimeOptionWrapper(); + FD_C_RuntimeOptionWrapper* rec_option = FD_C_CreateRuntimeOptionWrapper(); + FD_C_RuntimeOptionWrapperUseGpu(det_option, 0); + FD_C_RuntimeOptionWrapperUseGpu(cls_option, 0); + FD_C_RuntimeOptionWrapperUseGpu(rec_option, 0); + + FD_C_DBDetectorWrapper* det_model = FD_C_CreateDBDetectorWrapper( + det_model_file, det_params_file, det_option, PADDLE); + FD_C_ClassifierWrapper* cls_model = FD_C_CreateClassifierWrapper( + cls_model_file, cls_params_file, cls_option, PADDLE); + FD_C_RecognizerWrapper* rec_model = FD_C_CreateRecognizerWrapper( + rec_model_file, rec_params_file, rec_label_file, rec_option, PADDLE); + + FD_C_PPOCRv2Wrapper* ppocr_v2 = + FD_C_CreatePPOCRv2Wrapper(det_model, cls_model, rec_model); + if (!FD_C_PPOCRv2WrapperInitialized(ppocr_v2)) { + printf("Failed to initialize.\n"); + FD_C_DestroyRuntimeOptionWrapper(det_option); + FD_C_DestroyRuntimeOptionWrapper(cls_option); + FD_C_DestroyRuntimeOptionWrapper(rec_option); + FD_C_DestroyClassifierWrapper(cls_model); + FD_C_DestroyDBDetectorWrapper(det_model); + FD_C_DestroyRecognizerWrapper(rec_model); + FD_C_DestroyPPOCRv2Wrapper(ppocr_v2); + return; + } + + FD_C_Mat im = FD_C_Imread(image_file); + + FD_C_OCRResult* result = (FD_C_OCRResult*)malloc(sizeof(FD_C_OCRResult)); + + if (!FD_C_PPOCRv2WrapperPredict(ppocr_v2, im, result)) { + printf("Failed to predict.\n"); + FD_C_DestroyRuntimeOptionWrapper(det_option); + FD_C_DestroyRuntimeOptionWrapper(cls_option); + FD_C_DestroyRuntimeOptionWrapper(rec_option); + FD_C_DestroyClassifierWrapper(cls_model); + FD_C_DestroyDBDetectorWrapper(det_model); + FD_C_DestroyRecognizerWrapper(rec_model); + FD_C_DestroyPPOCRv2Wrapper(ppocr_v2); + FD_C_DestroyMat(im); + free(result); + return; + } + + // print res + // You can directly access fields in FD_C_OCRResult and print it refer to + // OCRResult API Doc Or you can wrap it using + // FD_C_OCRResult_Wrapper, which containes C++ structure + // fastdeploy::vision::OCRResult, and using C API + // FD_C_OCRResultWrapperStr to call + // fastdeploy::vision::OCRResult::Str() in it. For convenience, we choose + // this method to print it. + FD_C_OCRResultWrapper* result_wrapper = + FD_C_CreateOCRResultWrapperFromData(result); + printf("%s", FD_C_OCRResultWrapperStr(result_wrapper)); + FD_C_Mat vis_im = FD_C_VisOcr(im, result); + FD_C_Imwrite("vis_result.jpg", vis_im); + printf("Visualized result saved in ./vis_result.jpg\n"); + + FD_C_DestroyRuntimeOptionWrapper(det_option); + FD_C_DestroyRuntimeOptionWrapper(cls_option); + FD_C_DestroyRuntimeOptionWrapper(rec_option); + FD_C_DestroyClassifierWrapper(cls_model); + FD_C_DestroyDBDetectorWrapper(det_model); + FD_C_DestroyRecognizerWrapper(rec_model); + FD_C_DestroyPPOCRv2Wrapper(ppocr_v2); + FD_C_DestroyOCRResultWrapper(result_wrapper); + FD_C_DestroyOCRResult(result); + FD_C_DestroyMat(im); +} +int main(int argc, char* argv[]) { + if (argc < 7) { + printf( + "Usage: infer_demo path/to/det_model path/to/cls_model " + "path/to/rec_model path/to/rec_label_file path/to/image " + "run_option, " + "e.g ./infer_demo ./ch_PP-OCRv2_det_infer " + "./ch_ppocr_mobile_v2.0_cls_infer ./ch_PP-OCRv2_rec_infer " + "./ppocr_keys_v1.txt ./12.jpg 0\n"); + printf( + "The data type of run_option is int, 0: run with cpu; 1: run with gpu" + "\n"); + return -1; + } + + if (atoi(argv[6]) == 0) { + CpuInfer(argv[1], argv[2], argv[3], argv[4], argv[5]); + } else if (atoi(argv[6]) == 1) { + GpuInfer(argv[1], argv[2], argv[3], argv[4], argv[5]); + } + return 0; +} diff --git a/examples/vision/ocr/PP-OCRv3/c/CMakeLists.txt b/examples/vision/ocr/PP-OCRv3/c/CMakeLists.txt new file mode 100644 index 000000000..b228346da --- /dev/null +++ b/examples/vision/ocr/PP-OCRv3/c/CMakeLists.txt @@ -0,0 +1,13 @@ +PROJECT(infer_demo C) +CMAKE_MINIMUM_REQUIRED (VERSION 3.10) + +# 指定下载解压后的fastdeploy库路径 +option(FASTDEPLOY_INSTALL_DIR "Path of downloaded fastdeploy sdk.") + +include(${FASTDEPLOY_INSTALL_DIR}/FastDeploy.cmake) + +# 添加FastDeploy依赖头文件 +include_directories(${FASTDEPLOY_INCS}) + +add_executable(infer_demo ${PROJECT_SOURCE_DIR}/infer.c) +target_link_libraries(infer_demo ${FASTDEPLOY_LIBS}) diff --git a/examples/vision/ocr/PP-OCRv3/c/infer.c b/examples/vision/ocr/PP-OCRv3/c/infer.c new file mode 100644 index 000000000..7c214f220 --- /dev/null +++ b/examples/vision/ocr/PP-OCRv3/c/infer.c @@ -0,0 +1,262 @@ +// Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include + +#include "fastdeploy_capi/vision.h" + +#ifdef WIN32 +const char sep = '\\'; +#else +const char sep = '/'; +#endif + +void CpuInfer(const char* det_model_dir, const char* cls_model_dir, + const char* rec_model_dir, const char* rec_label_file, + const char* image_file) { + char det_model_file[100]; + char det_params_file[100]; + + char cls_model_file[100]; + char cls_params_file[100]; + + char rec_model_file[100]; + char rec_params_file[100]; + + int max_size = 99; + snprintf(det_model_file, max_size, "%s%c%s", det_model_dir, sep, + "inference.pdmodel"); + snprintf(det_params_file, max_size, "%s%c%s", det_model_dir, sep, + "inference.pdiparams"); + + snprintf(cls_model_file, max_size, "%s%c%s", cls_model_dir, sep, + "inference.pdmodel"); + snprintf(cls_params_file, max_size, "%s%c%s", cls_model_dir, sep, + "inference.pdiparams"); + + snprintf(rec_model_file, max_size, "%s%c%s", rec_model_dir, sep, + "inference.pdmodel"); + snprintf(rec_params_file, max_size, "%s%c%s", rec_model_dir, sep, + "inference.pdiparams"); + + FD_C_RuntimeOptionWrapper* det_option = FD_C_CreateRuntimeOptionWrapper(); + FD_C_RuntimeOptionWrapper* cls_option = FD_C_CreateRuntimeOptionWrapper(); + FD_C_RuntimeOptionWrapper* rec_option = FD_C_CreateRuntimeOptionWrapper(); + FD_C_RuntimeOptionWrapperUseCpu(det_option); + FD_C_RuntimeOptionWrapperUseCpu(cls_option); + FD_C_RuntimeOptionWrapperUseCpu(rec_option); + + FD_C_DBDetectorWrapper* det_model = FD_C_CreateDBDetectorWrapper( + det_model_file, det_params_file, det_option, PADDLE); + FD_C_ClassifierWrapper* cls_model = FD_C_CreateClassifierWrapper( + cls_model_file, cls_params_file, cls_option, PADDLE); + FD_C_RecognizerWrapper* rec_model = FD_C_CreateRecognizerWrapper( + rec_model_file, rec_params_file, rec_label_file, rec_option, PADDLE); + + FD_C_PPOCRv3Wrapper* ppocr_v3 = + FD_C_CreatePPOCRv3Wrapper(det_model, cls_model, rec_model); + if (!FD_C_PPOCRv3WrapperInitialized(ppocr_v3)) { + printf("Failed to initialize.\n"); + FD_C_DestroyRuntimeOptionWrapper(det_option); + FD_C_DestroyRuntimeOptionWrapper(cls_option); + FD_C_DestroyRuntimeOptionWrapper(rec_option); + FD_C_DestroyClassifierWrapper(cls_model); + FD_C_DestroyDBDetectorWrapper(det_model); + FD_C_DestroyRecognizerWrapper(rec_model); + FD_C_DestroyPPOCRv3Wrapper(ppocr_v3); + return; + } + + FD_C_Mat im = FD_C_Imread(image_file); + + FD_C_OCRResult* result = (FD_C_OCRResult*)malloc(sizeof(FD_C_OCRResult)); + + if (!FD_C_PPOCRv3WrapperPredict(ppocr_v3, im, result)) { + printf("Failed to predict.\n"); + FD_C_DestroyRuntimeOptionWrapper(det_option); + FD_C_DestroyRuntimeOptionWrapper(cls_option); + FD_C_DestroyRuntimeOptionWrapper(rec_option); + FD_C_DestroyClassifierWrapper(cls_model); + FD_C_DestroyDBDetectorWrapper(det_model); + FD_C_DestroyRecognizerWrapper(rec_model); + FD_C_DestroyPPOCRv3Wrapper(ppocr_v3); + FD_C_DestroyMat(im); + free(result); + return; + } + + // print res + // You can directly access fields in FD_C_OCRResult and print it refer to + // OCRResult API Doc Or you can wrap it using + // FD_C_OCRResult_Wrapper, which containes C++ structure + // fastdeploy::vision::OCRResult, and using C API + // FD_C_OCRResultWrapperStr to call + // fastdeploy::vision::OCRResult::Str() in it. For convenience, we choose + // this method to print it. + FD_C_OCRResultWrapper* result_wrapper = + FD_C_CreateOCRResultWrapperFromData(result); + printf("%s", FD_C_OCRResultWrapperStr(result_wrapper)); + FD_C_Mat vis_im = FD_C_VisOcr(im, result); + FD_C_Imwrite("vis_result.jpg", vis_im); + printf("Visualized result saved in ./vis_result.jpg\n"); + + FD_C_DestroyRuntimeOptionWrapper(det_option); + FD_C_DestroyRuntimeOptionWrapper(cls_option); + FD_C_DestroyRuntimeOptionWrapper(rec_option); + FD_C_DestroyClassifierWrapper(cls_model); + FD_C_DestroyDBDetectorWrapper(det_model); + FD_C_DestroyRecognizerWrapper(rec_model); + FD_C_DestroyPPOCRv3Wrapper(ppocr_v3); + FD_C_DestroyOCRResultWrapper(result_wrapper); + FD_C_DestroyOCRResult(result); + FD_C_DestroyMat(im); +} + +void GpuInfer(const char* det_model_dir, const char* cls_model_dir, + const char* rec_model_dir, const char* rec_label_file, + const char* image_file) { + char det_model_file[100]; + char det_params_file[100]; + + char cls_model_file[100]; + char cls_params_file[100]; + + char rec_model_file[100]; + char rec_params_file[100]; + + int max_size = 99; + snprintf(det_model_file, max_size, "%s%c%s", det_model_dir, sep, + "inference.pdmodel"); + snprintf(det_params_file, max_size, "%s%c%s", det_model_dir, sep, + "inference.pdiparams"); + + snprintf(cls_model_file, max_size, "%s%c%s", cls_model_dir, sep, + "inference.pdmodel"); + snprintf(cls_params_file, max_size, "%s%c%s", cls_model_dir, sep, + "inference.pdiparams"); + + snprintf(rec_model_file, max_size, "%s%c%s", rec_model_dir, sep, + "inference.pdmodel"); + snprintf(rec_params_file, max_size, "%s%c%s", rec_model_dir, sep, + "inference.pdiparams"); + + FD_C_RuntimeOptionWrapper* det_option = FD_C_CreateRuntimeOptionWrapper(); + FD_C_RuntimeOptionWrapper* cls_option = FD_C_CreateRuntimeOptionWrapper(); + FD_C_RuntimeOptionWrapper* rec_option = FD_C_CreateRuntimeOptionWrapper(); + FD_C_RuntimeOptionWrapperUseGpu(det_option, 0); + FD_C_RuntimeOptionWrapperUseGpu(cls_option, 0); + FD_C_RuntimeOptionWrapperUseGpu(rec_option, 0); + + FD_C_DBDetectorWrapper* det_model = FD_C_CreateDBDetectorWrapper( + det_model_file, det_params_file, det_option, PADDLE); + FD_C_ClassifierWrapper* cls_model = FD_C_CreateClassifierWrapper( + cls_model_file, cls_params_file, cls_option, PADDLE); + FD_C_RecognizerWrapper* rec_model = FD_C_CreateRecognizerWrapper( + rec_model_file, rec_params_file, rec_label_file, rec_option, PADDLE); + + FD_C_PPOCRv3Wrapper* ppocr_v3 = + FD_C_CreatePPOCRv3Wrapper(det_model, cls_model, rec_model); + if (!FD_C_PPOCRv3WrapperInitialized(ppocr_v3)) { + printf("Failed to initialize.\n"); + FD_C_DestroyRuntimeOptionWrapper(det_option); + FD_C_DestroyRuntimeOptionWrapper(cls_option); + FD_C_DestroyRuntimeOptionWrapper(rec_option); + FD_C_DestroyClassifierWrapper(cls_model); + FD_C_DestroyDBDetectorWrapper(det_model); + FD_C_DestroyRecognizerWrapper(rec_model); + FD_C_DestroyPPOCRv3Wrapper(ppocr_v3); + return; + } + + FD_C_Mat im = FD_C_Imread(image_file); + + FD_C_OCRResult* result = (FD_C_OCRResult*)malloc(sizeof(FD_C_OCRResult)); + + if (!FD_C_PPOCRv3WrapperPredict(ppocr_v3, im, result)) { + printf("Failed to predict.\n"); + FD_C_DestroyRuntimeOptionWrapper(det_option); + FD_C_DestroyRuntimeOptionWrapper(cls_option); + FD_C_DestroyRuntimeOptionWrapper(rec_option); + FD_C_DestroyClassifierWrapper(cls_model); + FD_C_DestroyDBDetectorWrapper(det_model); + FD_C_DestroyRecognizerWrapper(rec_model); + FD_C_DestroyPPOCRv3Wrapper(ppocr_v3); + FD_C_DestroyMat(im); + free(result); + return; + } + + // print res + // You can directly access fields in FD_C_OCRResult and print it refer to + // OCRResult API Doc Or you can wrap it using + // FD_C_OCRResult_Wrapper, which containes C++ structure + // fastdeploy::vision::OCRResult, and using C API + // FD_C_OCRResultWrapperStr to call + // fastdeploy::vision::OCRResult::Str() in it. For convenience, we choose + // this method to print it. + FD_C_OCRResultWrapper* result_wrapper = + FD_C_CreateOCRResultWrapperFromData(result); + printf("%s", FD_C_OCRResultWrapperStr(result_wrapper)); + FD_C_Mat vis_im = FD_C_VisOcr(im, result); + FD_C_Imwrite("vis_result.jpg", vis_im); + printf("Visualized result saved in ./vis_result.jpg\n"); + + FD_C_DestroyRuntimeOptionWrapper(det_option); + FD_C_DestroyRuntimeOptionWrapper(cls_option); + FD_C_DestroyRuntimeOptionWrapper(rec_option); + FD_C_DestroyClassifierWrapper(cls_model); + FD_C_DestroyDBDetectorWrapper(det_model); + FD_C_DestroyRecognizerWrapper(rec_model); + FD_C_DestroyPPOCRv3Wrapper(ppocr_v3); + FD_C_DestroyOCRResultWrapper(result_wrapper); + FD_C_DestroyOCRResult(result); + FD_C_DestroyMat(im); +} +int main(int argc, char* argv[]) { + if (argc < 7) { + printf( + "Usage: infer_demo path/to/det_model path/to/cls_model " + "path/to/rec_model path/to/rec_label_file path/to/image " + "run_option, " + "e.g ./infer_demo ./ch_PP-OCRv3_det_infer " + "./ch_ppocr_mobile_v2.0_cls_infer ./ch_PP-OCRv3_rec_infer " + "./ppocr_keys_v1.txt ./12.jpg 0\n"); + printf( + "The data type of run_option is int, 0: run with cpu; 1: run with gpu" + "\n"); + return -1; + } + + if (atoi(argv[6]) == 0) { + CpuInfer(argv[1], argv[2], argv[3], argv[4], argv[5]); + } else if (atoi(argv[6]) == 1) { + GpuInfer(argv[1], argv[2], argv[3], argv[4], argv[5]); + } + return 0; +}