| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| #include "result.h" |
|
|
| #include <fstream> |
| #include <string> |
|
|
| #include "src/utils/utility.h" |
| #include "third_party/nlohmann/json.hpp" |
|
|
| using json = nlohmann::json; |
| void TopkResult::SaveToImg(const std::string &save_path) { |
| cv::Mat img = predictor_result_.input_image.clone(); |
|
|
| std::ostringstream oss; |
| oss << predictor_result_.label_names[0] << " " << std::fixed |
| << std::setprecision(2) << predictor_result_.scores[0]; |
| std::string label_str = oss.str(); |
|
|
| int imgWidth = img.cols; |
| int minFont = std::max(12, imgWidth * 2 / 100); |
| int maxFont = std::max(18, imgWidth * 5 / 100); |
| int baseline = 0; |
| int fontFace = 0; |
| double fontScale = getAdaptiveFontScale( |
| label_str, imgWidth, imgWidth, minFont, maxFont, 2, baseline, fontFace); |
|
|
| cv::Size textSize = |
| cv::getTextSize(label_str, fontFace, fontScale, 2, &baseline); |
|
|
| int rect_left = 3, rect_top = 3; |
| int rect_right = rect_left + textSize.width + 6; |
| int rect_bottom = rect_top + textSize.height + 6; |
| cv::Scalar bgColor(0, 0, 255); |
| cv::rectangle(img, cv::Point(rect_left, rect_top), |
| cv::Point(rect_right, rect_bottom), bgColor, cv::FILLED); |
|
|
| int text_x = rect_left + 3; |
| int text_y = rect_top + textSize.height + 2; |
| cv::Scalar fontColor(255, 255, 255); |
| cv::putText(img, label_str, cv::Point(text_x, text_y), fontFace, fontScale, |
| fontColor, 2, cv::LINE_AA); |
| absl::StatusOr<std::string> full_path; |
| if (predictor_result_.input_path.empty()) { |
| auto now = std::chrono::system_clock::now(); |
| auto now_time = std::chrono::system_clock::to_time_t(now); |
| std::stringstream ss; |
| ss << "output_" << std::put_time(std::localtime(&now_time), "%Y%m%d_%H%M%S") |
| << ".jpg"; |
| std::string timestamp_filename = ss.str(); |
| INFOW("Input path is empty, will use %s instead!", |
| timestamp_filename.c_str()); |
| predictor_result_.input_path = timestamp_filename; |
| full_path = |
| Utility::SmartCreateDirectoryForImage(save_path, timestamp_filename); |
| } else { |
| full_path = Utility::SmartCreateDirectoryForImage( |
| save_path, predictor_result_.input_path); |
| } |
| if (!full_path.ok()) { |
| INFOE(full_path.status().ToString().c_str()); |
| exit(-1); |
| } |
| bool success = cv::imwrite(full_path.value(), img); |
| if (!success) { |
| INFOE("Failed to write the image %s ", full_path.value().c_str()); |
| exit(-1); |
| } |
| } |
|
|
| void TopkResult::Print() const { |
| std::cout << "{\n \"res\": {" << std::endl; |
|
|
| std::cout << " \"input_path\": {" << predictor_result_.input_path << "}," |
| << std::endl; |
| std::cout << " \"class_ids\": {" << predictor_result_.class_ids[0] << "}," |
| << std::endl; |
| std::cout << " \"scores\": {" << predictor_result_.scores[0] << "}," |
| << std::endl; |
| std::cout << " \"label_names\": {" << predictor_result_.label_names[0] |
| << "}," << std::endl; |
| std::cout << "}" << std::endl; |
| } |
|
|
| void TopkResult::SaveToJson(const std::string &save_path) const { |
| nlohmann::ordered_json j; |
|
|
| j["input_path"] = predictor_result_.input_path; |
| j["page_index"] = nullptr; |
|
|
| json class_ids = json::array(); |
| for (const auto &item : predictor_result_.class_ids) { |
| class_ids.push_back(item); |
| } |
| json scores = json::array(); |
| for (const auto &item : predictor_result_.scores) { |
| scores.push_back(item); |
| } |
| json label_names = json::array(); |
| for (const auto &item : predictor_result_.label_names) { |
| label_names.push_back(item); |
| } |
|
|
| j["class_ids"] = class_ids; |
| j["scores"] = scores; |
| j["label_names"] = label_names; |
|
|
| auto full_path = Utility::SmartCreateDirectoryForJson( |
| save_path, predictor_result_.input_path); |
| if (!full_path.ok()) { |
| INFOE(full_path.status().ToString().c_str()); |
| exit(-1); |
| } |
| std::ofstream file(full_path.value()); |
| if (file.is_open()) { |
| file << j.dump(4); |
| file.close(); |
| } else { |
| INFOE("Could not open file for writing: %s", save_path.c_str()); |
| exit(-1); |
| } |
| } |
|
|
| int TopkResult::getAdaptiveFontScale(const std::string &text, int imgWidth, |
| int maxWidth, int minFont, int maxFont, |
| int thickness, int &outBaseline, |
| int &outFontFace) { |
| int fontFace = cv::FONT_HERSHEY_SIMPLEX; |
| double fontScale = 1.0; |
| int baseline = 0; |
| int bestFontSize = minFont; |
|
|
| for (int fontSize = maxFont; fontSize >= minFont; --fontSize) { |
| fontScale = fontSize / 20.0; |
| int base; |
| cv::Size textSize = |
| cv::getTextSize(text, fontFace, fontScale, thickness, &base); |
| if (textSize.width <= maxWidth) { |
| bestFontSize = fontSize; |
| outBaseline = base; |
| outFontFace = fontFace; |
| return fontScale; |
| } |
| } |
| outBaseline = 0; |
| outFontFace = fontFace; |
| return minFont / 20.0; |
| } |
|
|