-
Notifications
You must be signed in to change notification settings - Fork 19
Refactor - Implement Classification #304
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
sovrasov
merged 22 commits into
open-edge-platform:feature/cpp_refactoring
from
RHeckerIntel:rhecker/model_api_refactor_classification
Jun 17, 2025
Merged
Changes from 20 commits
Commits
Show all changes
22 commits
Select commit
Hold shift + click to select a range
b5d22be
Remove cpp implementation
RHeckerIntel b3bef98
Move in code from POC
RHeckerIntel cea8b00
Satisfy pre-commit checks
RHeckerIntel b8ee06c
Remove precommit tests for cpp
RHeckerIntel 7cbc2c7
Attempt to fix serving_api tests
RHeckerIntel ba9141d
Use old InputParser for test_accuracy
RHeckerIntel 45704ca
Remove async from public api side
RHeckerIntel ea6ef0d
Add and update license to 2025
RHeckerIntel d46033b
Remove empty line between template and class
RHeckerIntel 4403a2e
Start implementing classification model
RHeckerIntel cd15933
Implement multilabel post processing
RHeckerIntel b6815d6
Implement hierarchical and resolvers
RHeckerIntel e37c88e
Enable classification in accuracy tests
RHeckerIntel 9ebc505
Remove rogue cout
RHeckerIntel 9a20f0e
Implement classification serialization WIP
RHeckerIntel 9384335
Merge branch 'feature/cpp_refactoring' into rhecker/model_api_refacto…
RHeckerIntel 616c271
Fix classification serialization
RHeckerIntel 7738d8d
Working serialization for instance and semantic segmentation
RHeckerIntel 68cadc1
Attempt openvino 2025.1 for failing test
RHeckerIntel 58c7110
Add specific implementation for get_from_any_map for bool
RHeckerIntel 61e53f5
Remove input shape as input for the tasks
RHeckerIntel f00afa4
Satisfy clang
RHeckerIntel File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,95 @@ | ||
| /* | ||
| * Copyright (C) 2020-2025 Intel Corporation | ||
| * SPDX-License-Identifier: Apache-2.0 | ||
| */ | ||
|
|
||
| #pragma once | ||
|
|
||
| #include <opencv2/opencv.hpp> | ||
| #include <openvino/openvino.hpp> | ||
|
|
||
| #include "adapters/inference_adapter.h" | ||
| #include "tasks/classification/resolvers.h" | ||
| #include "tasks/results.h" | ||
| #include "utils/config.h" | ||
| #include "utils/vision_pipeline.h" | ||
|
|
||
| class Classification { | ||
| public: | ||
| std::shared_ptr<InferenceAdapter> adapter; | ||
| VisionPipeline<ClassificationResult> pipeline; | ||
|
|
||
| Classification(std::shared_ptr<InferenceAdapter> adapter, cv::Size input_shape) | ||
| : adapter(adapter), | ||
| input_shape(input_shape) { | ||
| pipeline = VisionPipeline<ClassificationResult>( | ||
| adapter, | ||
| [&](cv::Mat image) { | ||
| return preprocess(image); | ||
| }, | ||
| [&](InferenceResult result) { | ||
| return postprocess(result); | ||
| }); | ||
|
|
||
| auto config = adapter->getModelConfig(); | ||
| labels = utils::get_from_any_maps("labels", config, {}, labels); | ||
|
|
||
| topk = utils::get_from_any_maps("topk", config, {}, topk); | ||
| multilabel = utils::get_from_any_maps("multilabel", config, {}, multilabel); | ||
| output_raw_scores = utils::get_from_any_maps("output_raw_scores", config, {}, output_raw_scores); | ||
| confidence_threshold = utils::get_from_any_maps("confidence_threshold", config, {}, confidence_threshold); | ||
| hierarchical = utils::get_from_any_maps("hierarchical", config, {}, hierarchical); | ||
| hierarchical_config = utils::get_from_any_maps("hierarchical_config", config, {}, hierarchical_config); | ||
| hierarchical_postproc = utils::get_from_any_maps("hierarchical_postproc", config, {}, hierarchical_postproc); | ||
| if (hierarchical) { | ||
| if (hierarchical_config.empty()) { | ||
| throw std::runtime_error("Error: empty hierarchical classification config"); | ||
| } | ||
| hierarchical_info = HierarchicalConfig(hierarchical_config); | ||
| if (hierarchical_postproc == "probabilistic") { | ||
| resolver = std::make_unique<ProbabilisticLabelsResolver>(hierarchical_info); | ||
| } else if (hierarchical_postproc == "greedy") { | ||
| resolver = std::make_unique<GreedyLabelsResolver>(hierarchical_info); | ||
| } else { | ||
| throw std::runtime_error("Wrong hierarchical labels postprocessing type"); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| static cv::Size serialize(std::shared_ptr<ov::Model>& ov_model); | ||
| static Classification load(const std::string& model_path); | ||
|
|
||
| ClassificationResult infer(cv::Mat image); | ||
| std::vector<ClassificationResult> inferBatch(std::vector<cv::Mat> image); | ||
|
|
||
| std::map<std::string, ov::Tensor> preprocess(cv::Mat); | ||
| ClassificationResult postprocess(InferenceResult& infResult); | ||
|
|
||
| bool postprocess_semantic_masks = true; | ||
|
|
||
| private: | ||
| ClassificationResult get_multilabel_predictions(InferenceResult& infResult, bool add_raw_scores); | ||
| ClassificationResult get_multiclass_predictions(InferenceResult& infResult, bool add_raw_scores); | ||
| ClassificationResult get_hierarchical_predictions(InferenceResult& infResult, bool add_raw_scores); | ||
|
|
||
| ov::Tensor reorder_saliency_maps(const ov::Tensor& source_maps); | ||
|
|
||
| // multiclass serialization step | ||
| static void addOrFindSoftmaxAndTopkOutputs(std::shared_ptr<ov::Model>& model, size_t topk, bool add_raw_scores); | ||
|
|
||
| private: | ||
| cv::Size input_shape; | ||
| std::vector<std::string> labels; | ||
| float confidence_threshold = 0.5f; | ||
|
|
||
| bool multilabel = false; | ||
| bool hierarchical = false; | ||
| bool output_raw_scores = false; | ||
|
|
||
| // hierarchical | ||
| size_t topk = 1; | ||
| std::string hierarchical_config; | ||
| std::string hierarchical_postproc = "greedy"; | ||
| HierarchicalConfig hierarchical_info; | ||
| std::unique_ptr<GreedyLabelsResolver> resolver; | ||
| }; | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,74 @@ | ||
| /* | ||
| * Copyright (C) 2020-2025 Intel Corporation | ||
| * SPDX-License-Identifier: Apache-2.0 | ||
| */ | ||
| #include <map> | ||
| #include <string> | ||
| #include <unordered_map> | ||
| #include <vector> | ||
|
|
||
| struct HierarchicalConfig { | ||
| std::map<std::string, int> label_to_idx; | ||
| std::vector<std::pair<std::string, std::string>> label_tree_edges; | ||
| std::vector<std::vector<std::string>> all_groups; | ||
| std::map<size_t, std::pair<size_t, size_t>> head_idx_to_logits_range; | ||
| std::map<size_t, std::string> logit_idx_to_label; | ||
| size_t num_multiclass_heads; | ||
| size_t num_multilabel_heads; | ||
| size_t num_single_label_classes; | ||
|
|
||
| HierarchicalConfig() = default; | ||
| HierarchicalConfig(const std::string&); | ||
| }; | ||
|
|
||
| class SimpleLabelsGraph { | ||
| public: | ||
| SimpleLabelsGraph() = default; | ||
| SimpleLabelsGraph(const std::vector<std::string>& vertices_); | ||
| void add_edge(const std::string& parent, const std::string& child); | ||
| std::vector<std::string> get_children(const std::string& label) const; | ||
| std::string get_parent(const std::string& label) const; | ||
| std::vector<std::string> get_ancestors(const std::string& label) const; | ||
| std::vector<std::string> get_labels_in_topological_order(); | ||
|
|
||
| protected: | ||
| std::vector<std::string> vertices; | ||
| std::unordered_map<std::string, std::vector<std::string>> adj; | ||
| std::unordered_map<std::string, std::string> parents_map; | ||
| bool t_sort_cache_valid = false; | ||
| std::vector<std::string> topological_order_cache; | ||
|
|
||
| std::vector<std::string> topological_sort(); | ||
| }; | ||
|
|
||
| class GreedyLabelsResolver { | ||
| public: | ||
| GreedyLabelsResolver() = default; | ||
| GreedyLabelsResolver(const HierarchicalConfig&); | ||
|
|
||
| virtual std::map<std::string, float> resolve_labels(const std::vector<std::reference_wrapper<std::string>>& labels, | ||
| const std::vector<float>& scores); | ||
|
|
||
| protected: | ||
| std::map<std::string, int> label_to_idx; | ||
| std::vector<std::pair<std::string, std::string>> label_relations; | ||
| std::vector<std::vector<std::string>> label_groups; | ||
|
|
||
| std::string get_parent(const std::string& label); | ||
| std::vector<std::string> get_predecessors(const std::string& label, const std::vector<std::string>& candidates); | ||
| }; | ||
|
|
||
| class ProbabilisticLabelsResolver : public GreedyLabelsResolver { | ||
| public: | ||
| ProbabilisticLabelsResolver() = default; | ||
| ProbabilisticLabelsResolver(const HierarchicalConfig&); | ||
|
|
||
| virtual std::map<std::string, float> resolve_labels(const std::vector<std::reference_wrapper<std::string>>& labels, | ||
| const std::vector<float>& scores); | ||
| std::unordered_map<std::string, float> add_missing_ancestors(const std::unordered_map<std::string, float>&) const; | ||
| std::map<std::string, float> resolve_exclusive_labels(const std::unordered_map<std::string, float>&) const; | ||
| void suppress_descendant_output(std::map<std::string, float>&); | ||
|
|
||
| protected: | ||
| SimpleLabelsGraph label_tree; | ||
| }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.