Skip to main content
Glama
utility.cc19.5 kB
// Copyright (c) 2025 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 "utility.h" #include <dirent.h> #include <sys/stat.h> #include <regex> #include "ilogger.h" absl::Status Utility::FileExists(const std::string &path) { struct stat st; if (stat(path.c_str(), &st) == 0) { return absl::OkStatus(); } else { return absl::NotFoundError("File is not exist:" + path); } } absl::StatusOr<std::map<std::string, std::pair<std::string, std::string>>> Utility::GetModelPaths(const std::string &model_dir, const std::string &model_file_prefix) { std::map<std::string, std::pair<std::string, std::string>> model_paths; std::string model_path; std::string json_path = model_dir + PATH_SEPARATOR + model_file_prefix + ".json"; std::string pdmodel_path = model_dir + PATH_SEPARATOR + model_file_prefix + ".pdmodel"; std::string params_path = model_dir + PATH_SEPARATOR + model_file_prefix + ".pdiparams"; if (FileExists(json_path).ok()) { model_path = json_path; } else if (FileExists(pdmodel_path).ok()) { model_path = pdmodel_path; } else { return absl::NotFoundError(FileExists(json_path).ToString() + " and " + FileExists(pdmodel_path).ToString()); } if (model_path.empty()) { return absl::NotFoundError( "No PaddlePaddle model file (.json or .pdmodel) found!"); } if (FileExists(params_path).ok()) { model_paths["paddle"] = std::make_pair(model_path, params_path); } else { return absl::NotFoundError( "No PaddlePaddle params file (.pdiparams) found!"); } return model_paths; } absl::StatusOr<std::string> Utility::FindModelPath(const std::string &model_dir, const std::string &model_name) { char last_char = model_dir.back(); std::string model_path; if (last_char == PATH_SEPARATOR) model_path = model_dir + model_name; else model_path = model_dir + PATH_SEPARATOR + model_name; auto status = FileExists(model_path); if (!status.ok()) { return status; } return model_path; } absl::StatusOr<std::string> Utility::GetDefaultConfig(std::string pipeline_name) { std::string current_path = __FILE__; for (int i = 0; i < 2; i++) { size_t pos = current_path.find_last_of(PATH_SEPARATOR); if (pos == std::string::npos) { return absl::NotFoundError("Could not find pipeline config yaml :" + pipeline_name); } current_path = current_path.substr(0, pos); } std::string config_path_yaml = current_path + PATH_SEPARATOR + "configs" + PATH_SEPARATOR + pipeline_name + ".yaml"; std::string config_path_yml = current_path + PATH_SEPARATOR + "configs" + PATH_SEPARATOR + pipeline_name + ".yml"; if (FileExists(config_path_yaml).ok()) { return config_path_yaml; } else if (FileExists(config_path_yml).ok()) { return config_path_yml; } return absl::NotFoundError("Could not find pipeline config yaml :" + pipeline_name); } absl::StatusOr<std::string> Utility::GetConfigPaths(const std::string &model_dir, const std::string &model_file_prefix) { std::string config_path = ""; std::string config_path_find = model_dir + PATH_SEPARATOR + model_file_prefix + ".yml"; if (FileExists(config_path_find).ok()) { config_path = config_path_find; } else { return FileExists(config_path_find); } return config_path; }; bool Utility::IsMkldnnAvailable() { #ifdef _WIN32 SYSTEM_INFO si; GetSystemInfo(&si); char cpuBrand[0x40] = {0}; int cpuInfo[4] = {0}; __cpuid(cpuInfo, 0x80000002); memcpy(cpuBrand, cpuInfo, sizeof(cpuInfo)); __cpuid(cpuInfo, 0x80000003); memcpy(cpuBrand + 16, cpuInfo, sizeof(cpuInfo)); __cpuid(cpuInfo, 0x80000004); memcpy(cpuBrand + 32, cpuInfo, sizeof(cpuInfo)); std::string brandStr(cpuBrand); if (brandStr.find("Intel") != std::string::npos) { return true; } return false; #else std::ifstream cpuinfo("/proc/cpuinfo"); std::string line; while (std::getline(cpuinfo, line)) { if (line.find("vendor_id") != std::string::npos) { auto pos = line.find(":"); if (pos != std::string::npos) { if (line.substr(pos + 2).find("Intel") != std::string::npos) { return true; } } } } return false; #endif }; void Utility::PrintShape(const cv::Mat &img) { for (int i = 0; i < img.dims; i++) { std::cout << img.size[i] << " "; } std::cout << std::endl; } absl::Status Utility::MyCreateDirectory(const std::string &path) { #ifdef _WIN32 int ret = _mkdir(path.c_str()); #else int ret = mkdir(path.c_str(), 0755); #endif if (ret == 0) { return absl::OkStatus(); } if (errno == EEXIST) { return absl::OkStatus(); } return absl::ErrnoToStatus(errno, "Failed to create directory: " + path); } absl::Status Utility::MyCreatePath(const std::string &path) { std::vector<std::string> paths; std::string tmp; for (size_t i = 0; i < path.size(); ++i) { tmp += path[i]; if (path[i] == PATH_SEPARATOR) { paths.push_back(tmp); } } if (!tmp.empty() && tmp.back() != PATH_SEPARATOR) paths.push_back(tmp); std::string current; for (size_t i = 0; i < paths.size(); ++i) { current += paths[i]; absl::Status status = MyCreateDirectory(current); if (!status.ok()) { return status; } } return absl::OkStatus(); } absl::Status Utility::MyCreateFile(const std::string &filepath) { std::ifstream infile(filepath.c_str()); if (infile.good()) { return absl::OkStatus(); } std::ofstream outfile(filepath.c_str(), std::ios::out | std::ios::trunc); if (!outfile.is_open()) { return absl::InternalError("Failed to create file: " + filepath); } outfile.close(); return absl::OkStatus(); } absl::StatusOr<std::vector<cv::Mat>> Utility::SplitBatch(const cv::Mat &batch) { if (batch.dims < 1) { return absl::InvalidArgumentError( "Input batch must have at least 1 dimension."); } if (batch.type() != CV_32F) { return absl::InvalidArgumentError( "Input batch must have CV_32F element type."); } std::vector<cv::Mat> split_mats; int batch_size = batch.size[0]; std::vector<cv::Range> myranges(batch.dims); for (int i = 0; i < batch_size; ++i) { myranges[0] = cv::Range(i, i + 1); for (int d = 1; d < batch.dims; ++d) myranges[d] = cv::Range::all(); cv::Mat sub_mat = batch(&myranges[0]); split_mats.push_back(sub_mat); } return split_mats; } std::string Utility::GetFileExtension(const std::string &file_path) { size_t pos = file_path.find_last_of('.'); if (pos == std::string::npos || pos == file_path.length() - 1) { return ""; } return file_path.substr(pos + 1); } std::string Utility::ToLower(const std::string &str) { std::string result = str; std::transform(result.begin(), result.end(), result.begin(), ::tolower); return result; } bool Utility::IsDirectory(const std::string &path) { struct stat path_stat; if (stat(path.c_str(), &path_stat) != 0) { return false; } return S_ISDIR(path_stat.st_mode); } void Utility::GetFilesRecursive(const std::string &dir_path, std::vector<std::string> &file_list) { DIR *dir = opendir(dir_path.c_str()); if (dir == NULL) { return; } struct dirent *entry; while ((entry = readdir(dir)) != NULL) { std::string name = entry->d_name; if (name == "." || name == "..") { continue; } std::string full_path = ""; if (dir_path.back() == PATH_SEPARATOR) { full_path = dir_path + name; } else { full_path = dir_path + PATH_SEPARATOR + name; } if (Utility::IsDirectory(full_path)) { Utility::GetFilesRecursive(full_path, file_list); } else if (IsImageFile(full_path)) { file_list.push_back(full_path); } } closedir(dir); } bool Utility::IsImageFile(const std::string &file_path) { std::string extension = GetFileExtension(file_path); std::string lower_ext = ToLower(extension); return kImgSuffixes.find(lower_ext) != kImgSuffixes.end(); } absl::StatusOr<cv::Mat> Utility::MyLoadImage(const std::string &file_path) { cv::Mat image = cv::imread(file_path, cv::IMREAD_COLOR); if (image.empty()) { return absl::InvalidArgumentError("Failed to load image: " + file_path); } return image; } int Utility::MakeDir(const std::string &path) { #ifdef _WIN32 return _mkdir(path.c_str()); #else return mkdir(path.c_str(), 0755); // Linux/macOS 权限 755 #endif } absl::Status Utility::CreateDirectoryRecursive(const std::string &path) { if (path.empty()) { return absl::InvalidArgumentError("Path cannot be empty"); } size_t pos = 0; std::string dir = path; #ifdef _WIN32 #define ACCESS _access #define F_OK 0 #else #define ACCESS access #endif while (pos < dir.size()) { pos = dir.find_first_of(PATH_SEPARATOR, pos + 1); std::string subdir = (pos == std::string::npos) ? dir : dir.substr(0, pos); if (!subdir.empty() && ACCESS(subdir.c_str(), F_OK) != 0) { if (MakeDir(subdir) != 0) { return absl::InternalError("Failed to create directory: " + subdir); } } if (pos == std::string::npos) { break; } } return absl::OkStatus(); } absl::Status Utility::CreateDirectoryForFile(const std::string &filePath) { size_t found = filePath.find_last_of(PATH_SEPARATOR); if (found != std::string::npos) { std::string dirPath = filePath.substr(0, found); if (!CreateDirectoryRecursive(dirPath).ok()) { return absl::InternalError("Failed to create file: " + filePath); ; } } return absl::OkStatus(); } absl::StatusOr<std::string> Utility::SmartCreateDirectoryForImage(std::string save_path, const std::string &input_path, const std::string &suffix) { size_t pos = save_path.find_last_of("/\\"); std::string lastPart = save_path.substr(pos + 1); if (lastPart.find(".") == std::string::npos) { save_path += PATH_SEPARATOR; } std::string full_path = save_path; auto status = CreateDirectoryForFile(save_path); if (!status.ok()) { return status; } if (Utility::IsDirectory(save_path)) { auto file_path = input_path; size_t pos = file_path.find_last_of("/\\"); std::string file_name = (pos == std::string::npos) ? file_path : file_path.substr(pos + 1); size_t dot_pos = file_name.find_last_of('.'); if (dot_pos == std::string::npos) { file_name = file_name + suffix; } else { file_name.insert(dot_pos, suffix); } if (save_path.back() != PATH_SEPARATOR) { full_path += PATH_SEPARATOR; } full_path += file_name; } return full_path; } absl::StatusOr<std::string> Utility::SmartCreateDirectoryForJson(const std::string &save_path, const std::string &input_path, const std::string &suffix) { auto full_path = SmartCreateDirectoryForImage(save_path, input_path, suffix); if (!full_path.ok()) { return full_path.status(); } size_t pos = full_path.value().rfind('.'); if (pos != std::string::npos) { full_path.value().replace(pos, std::string::npos, ".json"); } return full_path.value(); } absl::StatusOr<int> Utility::StringToInt(std::string s) { std::regex pattern("(\\d+)"); std::smatch match; if (std::regex_search(s, match, pattern)) { int value = std::stoi(match[1]); return value; } else { return absl::NotFoundError("Could not find int !"); } } bool Utility::StringToBool(const std::string &str) { std::string result = str; std::transform(result.begin(), result.end(), result.begin(), ::tolower); assert(result == "true" || result == "false"); if (result == "true") { return true; } else { return false; } } std::string Utility::VecToString(const std::vector<int> &input) { std::string result; for (auto it = input.begin(); it != input.end(); ++it) { if (it != input.begin()) result += ","; result += std::to_string(*it); } return result; } absl::StatusOr<std::tuple<std::string, std::string, std::string>> Utility::GetOcrModelInfo(std::string lang, std::string ppocr_version) { // Font constants const static std::string PINGFANG_FONT = "PingFang-SC-Regular.ttf"; const static std::string SIMFANG_FONT = "simfang.ttf"; const static std::string LATIN_FONT = "latin.ttf"; const static std::string KOREAN_FONT = "korean.ttf"; const static std::string ARABIC_FONT = "arabic.ttf"; const static std::string CYRILLIC_FONT = "cyrillic.ttf"; const static std::string KANNADA_FONT = "kannada.ttf"; const static std::string TELUGU_FONT = "telugu.ttf"; const static std::string TAMIL_FONT = "tamil.ttf"; const static std::string DEVANAGARI_FONT = "devanagari.ttf"; // Supported PP-OCR versions const static std::unordered_set<std::string> SUPPORT_PPOCR_VERSION = { "PP-OCRv5", "PP-OCRv4", "PP-OCRv3"}; // Language sets const static std::unordered_set<std::string> LATIN_LANGS = { "af", "az", "bs", "cs", "cy", "da", "de", "es", "et", "fr", "ga", "hr", "hu", "id", "is", "it", "ku", "la", "lt", "lv", "mi", "ms", "mt", "nl", "no", "oc", "pi", "pl", "pt", "ro", "rs_latin", "sk", "sl", "sq", "sv", "sw", "tl", "tr", "uz", "vi", "french", "german"}; const static std::unordered_set<std::string> ARABIC_LANGS = {"ar", "fa", "ug", "ur"}; const static std::unordered_set<std::string> ESLAV_LANGS = {"ru", "be", "uk"}; const static std::unordered_set<std::string> CYRILLIC_LANGS = { "ru", "rs_cyrillic", "be", "bg", "uk", "mn", "abq", "ady", "kbd", "ava", "dar", "inh", "che", "lbe", "lez", "tab"}; const static std::unordered_set<std::string> DEVANAGARI_LANGS = { "hi", "mr", "ne", "bh", "mai", "ang", "bho", "mah", "sck", "new", "gom", "sa", "bgc"}; const static std::unordered_set<std::string> SPECIFIC_LANGS = { "ch", "en", "korean", "japan", "chinese_cht", "te", "ka", "ta"}; // Validate input parameters if (!ppocr_version.empty() && SUPPORT_PPOCR_VERSION.count(ppocr_version) == 0) { return absl::InvalidArgumentError("Unsupported ppocr_version: " + ppocr_version); } if (lang.empty()) lang = "ch"; // Create combined supported languages set const static std::unordered_set<std::string> supported_langs = []() { std::unordered_set<std::string> s; s.insert(LATIN_LANGS.begin(), LATIN_LANGS.end()); s.insert(ARABIC_LANGS.begin(), ARABIC_LANGS.end()); s.insert(ESLAV_LANGS.begin(), ESLAV_LANGS.end()); s.insert(CYRILLIC_LANGS.begin(), CYRILLIC_LANGS.end()); s.insert(DEVANAGARI_LANGS.begin(), DEVANAGARI_LANGS.end()); s.insert(SPECIFIC_LANGS.begin(), SPECIFIC_LANGS.end()); s.insert("ch"); return s; }(); if (supported_langs.count(lang) == 0) { return absl::InvalidArgumentError("Unsupported lang: " + lang); } // Determine default ppocr_version if not specified if (ppocr_version.empty()) { std::unordered_set<std::string> v5_langs = {"ch", "chinese_cht", "en", "japan", "korean"}; v5_langs.insert(LATIN_LANGS.begin(), LATIN_LANGS.end()); v5_langs.insert(ESLAV_LANGS.begin(), ESLAV_LANGS.end()); if (v5_langs.count(lang)) { ppocr_version = "PP-OCRv5"; } else { std::unordered_set<std::string> v3_langs = LATIN_LANGS; v3_langs.insert(ARABIC_LANGS.begin(), ARABIC_LANGS.end()); v3_langs.insert(CYRILLIC_LANGS.begin(), CYRILLIC_LANGS.end()); v3_langs.insert(DEVANAGARI_LANGS.begin(), DEVANAGARI_LANGS.end()); v3_langs.insert(SPECIFIC_LANGS.begin(), SPECIFIC_LANGS.end()); if (v3_langs.count(lang)) { ppocr_version = "PP-OCRv3"; } else { return absl::InvalidArgumentError( "Invalid lang and ocr_version combination!"); } } } // Initialize return values std::string det_model_name; std::string rec_model_name; std::string font_name = SIMFANG_FONT; // Default font // Model and font selection logic if (ppocr_version == "PP-OCRv5") { det_model_name = "PP-OCRv5_server_det"; std::string rec_lang; if (lang == "ch" || lang == "chinese_cht" || lang == "en" || lang == "japan") { rec_model_name = "PP-OCRv5_server_rec"; font_name = SIMFANG_FONT; } else if (LATIN_LANGS.count(lang)) { rec_lang = "latin"; font_name = LATIN_FONT; } else if (ESLAV_LANGS.count(lang)) { rec_lang = "eslav"; font_name = CYRILLIC_FONT; } else if (lang == "korean") { rec_lang = "korean"; font_name = KOREAN_FONT; } if (!rec_lang.empty()) { rec_model_name = rec_lang + "_PP-OCRv5_mobile_rec"; } } else if (ppocr_version == "PP-OCRv4") { if (lang == "ch") { det_model_name = "PP-OCRv4_mobile_det"; rec_model_name = "PP-OCRv4_mobile_rec"; font_name = SIMFANG_FONT; } else if (lang == "en") { det_model_name = "PP-OCRv4_mobile_det"; rec_model_name = "en_PP-OCRv4_mobile_rec"; font_name = SIMFANG_FONT; } else { return absl::InvalidArgumentError( "PP-OCRv4 only support ch and en languages!"); } } else { // PP-OCRv3 det_model_name = "PP-OCRv3_mobile_det"; std::string rec_lang; if (LATIN_LANGS.count(lang)) { rec_lang = "latin"; font_name = LATIN_FONT; } else if (ARABIC_LANGS.count(lang)) { rec_lang = "arabic"; font_name = ARABIC_FONT; } else if (CYRILLIC_LANGS.count(lang)) { rec_lang = "cyrillic"; font_name = CYRILLIC_FONT; } else if (DEVANAGARI_LANGS.count(lang)) { rec_lang = "devanagari"; font_name = DEVANAGARI_FONT; } else if (SPECIFIC_LANGS.count(lang)) { rec_lang = lang; if (lang == "ka") { font_name = KANNADA_FONT; } else if (lang == "te") { font_name = TELUGU_FONT; } else if (lang == "ta") { font_name = TAMIL_FONT; } else if (lang == "ch") { font_name = SIMFANG_FONT; } } if (rec_lang == "ch") { rec_model_name = "PP-OCRv3_mobile_rec"; } else if (!rec_lang.empty()) { rec_model_name = rec_lang + "_PP-OCRv3_mobile_rec"; } } if (rec_model_name.empty()) { return absl::InvalidArgumentError( "Invalid lang and ocr_version combination!"); } return std::make_tuple(det_model_name, rec_model_name, font_name); } const std::set<std::string> Utility::kImgSuffixes = {"jpg", "png", "jpeg", "bmp"};

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/PaddlePaddle/PaddleOCR'

If you have feedback or need assistance with the MCP directory API, please join our Discord server