- 
                Notifications
    
You must be signed in to change notification settings  - Fork 0
 
Feature/refactoring #1
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
base: master
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR represents a significant refactoring of a Segment Anything Model (SAM) ONNX inference codebase, transitioning from a standalone C++ application to a ROS package with comprehensive testing infrastructure.
Key changes include:
- Migration from standalone executable to ROS catkin package structure
 - Complete reorganization of include directories from 
inc/toinclude/ - Addition of comprehensive unit and integration tests using Google Test
 - Refactoring of core functionality with improved error handling and code organization
 
Reviewed Changes
Copilot reviewed 16 out of 17 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description | 
|---|---|
| test/test_utils.cpp | New comprehensive unit tests for Utils class covering image preprocessing and coordinate scaling | 
| test/sam_test.cpp | New integration tests for SAM inference pipeline with model file validation | 
| src/utils.cpp | Refactored preprocessing and postprocessing with improved error handling and cleaner code structure | 
| src/segmentation.cpp | New segmentation wrapper providing unified interface for SAM encoder/decoder operations | 
| src/sam_inference.cpp | Major refactoring with consistent naming conventions and improved session management | 
| src/main.cpp | Simplified main function using new segmentation interface | 
| include/*.h | New header files replacing old inc/ structure with improved organization | 
| CMakeLists.txt | Complete restructure for ROS catkin package with testing support | 
| package.xml | New ROS package manifest | 
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
        
          
                src/segmentation.cpp
              
                Outdated
          
        
      | std::vector<SEG::DL_RESULT> resSam; | ||
| params_encoder.rectConfidenceThreshold = 0.1; | ||
| params_encoder.iouThreshold = 0.5; | ||
| params_encoder.modelPath = "/home/amigo//Documents/repos/sam_onnx_ros/build/SAM_encoder.onnx"; | 
    
      
    
      Copilot
AI
    
    
    
      Sep 10, 2025 
    
  
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hard-coded absolute path with double slash '//' makes the code non-portable and fragile. Consider using relative paths or environment variables.
| 
               | 
          ||
| params_decoder = params_encoder; | ||
| params_decoder.modelType = SEG::SAM_SEGMENT_DECODER; | ||
| params_decoder.modelPath = "/home/amigo/Documents/repos/sam_onnx_ros/build/SAM_mask_decoder.onnx"; | 
    
      
    
      Copilot
AI
    
    
    
      Sep 10, 2025 
    
  
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hard-coded absolute path makes the code non-portable. Consider using relative paths or environment variables for better maintainability.
        
          
                src/main.cpp
              
                Outdated
          
        
      | SEG::DL_RESULT res; | ||
| std::tie(samSegmentors, params_encoder, params_decoder, res, resSam) = Initializer(); | ||
| std::filesystem::path current_path = std::filesystem::current_path(); | ||
| std::filesystem::path imgs_path = "/home/amigo/Documents/repos/hero_sam/sam_inference/build/images"; // current_path / <- you could use | 
    
      
    
      Copilot
AI
    
    
    
      Sep 10, 2025 
    
  
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hard-coded absolute path makes the code non-portable. The commented suggestion to use current_path / would be more maintainable.
| std::filesystem::path imgs_path = "/home/amigo/Documents/repos/hero_sam/sam_inference/build/images"; // current_path / <- you could use | |
| std::filesystem::path imgs_path = current_path / "build/images"; // Use current_path for portability | 
        
          
                CMakeLists.txt
              
                Outdated
          
        
      | # -------------- ONNXRuntime ------------------# | ||
| set(ONNXRUNTIME_VERSION 1.21.0) | ||
| set(ONNXRUNTIME_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/../onnxruntime-linux-x64-gpu-1.21.1") | ||
| set(ONNXRUNTIME_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/../hero_sam.bak/onnxruntime-linux-x64-gpu-1.21.1") | 
    
      
    
      Copilot
AI
    
    
    
      Sep 10, 2025 
    
  
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hard-coded relative path to a '.bak' directory is fragile and non-portable. Consider using find_package or environment variables to locate ONNX Runtime.
| set(ONNXRUNTIME_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/../hero_sam.bak/onnxruntime-linux-x64-gpu-1.21.1") | |
| # Allow user to specify ONNXRUNTIME_ROOT via CMake variable or environment variable | |
| if(NOT DEFINED ONNXRUNTIME_ROOT) | |
| if(DEFINED ENV{ONNXRUNTIME_ROOT}) | |
| set(ONNXRUNTIME_ROOT $ENV{ONNXRUNTIME_ROOT}) | |
| else() | |
| message(FATAL_ERROR "ONNXRUNTIME_ROOT is not set. Please set the ONNXRUNTIME_ROOT environment variable or pass -DONNXRUNTIME_ROOT=... to cmake.") | |
| endif() | |
| endif() | 
        
          
                CMakeLists.txt
              
                Outdated
          
        
      | configure_file(~/Documents/repos/hero_sam.bak/sam_inference/model/SAM_mask_decoder.onnx ${CMAKE_CURRENT_BINARY_DIR}/SAM_mask_decoder.onnx COPYONLY) | ||
| configure_file(~/Documents/repos/hero_sam.bak/sam_inference/model/SAM_encoder.onnx ${CMAKE_CURRENT_BINARY_DIR}/SAM_encoder.onnx COPYONLY) | 
    
      
    
      Copilot
AI
    
    
    
      Sep 10, 2025 
    
  
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hard-coded absolute paths with tilde expansion and '.bak' directories are not portable and will fail on other systems. Consider using relative paths or making model paths configurable.
        
          
                test/sam_test.cpp
              
                Outdated
          
        
      | GTEST_SKIP() << "Models not found in build dir"; | ||
| } | ||
| 
               | 
          ||
| auto masks = SegmentAnything(samSegmentors, params_encoder, params_decoder, testImage_realistic); | 
    
      
    
      Copilot
AI
    
    
    
      Sep 10, 2025 
    
  
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Function call doesn't match the signature. SegmentAnything expects 6 parameters but only 4 are provided. Missing resSam and res parameters.
| void SegmentAnything(std::vector<std::unique_ptr<SAM>> &samSegmentors, | ||
| const SEG::DL_INIT_PARAM ¶ms_encoder, | ||
| const SEG::DL_INIT_PARAM ¶ms_decoder, const cv::Mat &img, std::vector<SEG::DL_RESULT> &resSam, | ||
| SEG::DL_RESULT &res) { | 
    
      
    
      Copilot
AI
    
    
    
      Sep 10, 2025 
    
  
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Function returns void but the test expects it to return a vector of masks. Consider returning the results or updating the test to match the actual function signature.
964d95f    to
    7cdf39a      
    Compare
  
    There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix missing newline at EOF
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
Copilot reviewed 18 out of 19 changed files in this pull request and generated 2 comments.
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
        
          
                CMakeLists.txt
              
                Outdated
          
        
      | configure_file(~/Documents/repos/hero_sam.bak/sam_inference/model/SAM_mask_decoder.onnx ${CMAKE_CURRENT_BINARY_DIR}/SAM_mask_decoder.onnx COPYONLY) | ||
| configure_file(~/Documents/repos/hero_sam.bak/sam_inference/model/SAM_encoder.onnx ${CMAKE_CURRENT_BINARY_DIR}/SAM_encoder.onnx COPYONLY) | 
    
      
    
      Copilot
AI
    
    
    
      Sep 23, 2025 
    
  
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hard-coded paths containing user-specific directories and .bak folders make the build system non-portable. These should use relative paths or be configurable through CMake variables.
| configure_file(~/Documents/repos/hero_sam.bak/sam_inference/model/SAM_mask_decoder.onnx ${CMAKE_CURRENT_BINARY_DIR}/SAM_mask_decoder.onnx COPYONLY) | |
| configure_file(~/Documents/repos/hero_sam.bak/sam_inference/model/SAM_encoder.onnx ${CMAKE_CURRENT_BINARY_DIR}/SAM_encoder.onnx COPYONLY) | |
| set(SAM_MODEL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../hero_sam.bak/sam_inference/model" CACHE PATH "Directory containing SAM .onnx model files") | |
| configure_file(${SAM_MODEL_DIR}/SAM_mask_decoder.onnx ${CMAKE_CURRENT_BINARY_DIR}/SAM_mask_decoder.onnx COPYONLY) | |
| configure_file(${SAM_MODEL_DIR}/SAM_encoder.onnx ${CMAKE_CURRENT_BINARY_DIR}/SAM_encoder.onnx COPYONLY) | 
        
          
                src/sam_inference.cpp
              
                Outdated
          
        
      | } | ||
| return RET_OK; | ||
| 
               | 
          ||
| _outputNodeNames.size(); | 
    
      
    
      Copilot
AI
    
    
    
      Sep 23, 2025 
    
  
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This line appears to be a leftover statement that has no effect. It should either be removed or used in a meaningful way (e.g., assigned to a variable or used in a function call).
| _outputNodeNames.size(); | 
1d6537d    to
    8aeb657      
    Compare
  
    There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
Copilot reviewed 18 out of 19 changed files in this pull request and generated 3 comments.
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
| 
               | 
          ||
| params_decoder = params_encoder; | ||
| params_decoder.modelType = SEG::SAM_SEGMENT_DECODER; | ||
| params_decoder.modelPath = "/home/amigo/Documents/repos/sam_onnx_ros/build/SAM_mask_decoder.onnx"; | 
    
      
    
      Copilot
AI
    
    
    
      Sep 26, 2025 
    
  
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This hardcoded absolute path is not portable and will fail on other systems. Consider using a relative path, environment variable, or ROS parameter to make the code more maintainable.
        
          
                CMakeLists.txt
              
                Outdated
          
        
      | configure_file(~/Documents/repos/hero_sam.bak/sam_inference/model/SAM_mask_decoder.onnx ${CMAKE_CURRENT_BINARY_DIR}/SAM_mask_decoder.onnx COPYONLY) | ||
| configure_file(~/Documents/repos/hero_sam.bak/sam_inference/model/SAM_encoder.onnx ${CMAKE_CURRENT_BINARY_DIR}/SAM_encoder.onnx COPYONLY) | 
    
      
    
      Copilot
AI
    
    
    
      Sep 26, 2025 
    
  
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These hardcoded paths with tilde expansion are not portable and will fail on other systems. Consider using environment variables or making these paths configurable through CMake options.
| SegmentAnything(samSegmentors, params_encoder, params_decoder, testImage_realistic, resSam, res); | ||
| 
               | 
          ||
| // We only check that a vector is returned. (You can strengthen this to EXPECT_FALSE(masks.empty()).) | ||
| EXPECT_TRUE(res.masks.size() >= 0) << "Masks should be a valid output vector"; | 
    
      
    
      Copilot
AI
    
    
    
      Sep 26, 2025 
    
  
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This assertion will always pass since vector size() returns size_t which is always >= 0. Change to 'EXPECT_FALSE(res.masks.empty())' or 'EXPECT_GT(res.masks.size(), 0)' to test for meaningful output.
| EXPECT_TRUE(res.masks.size() >= 0) << "Masks should be a valid output vector"; | |
| EXPECT_FALSE(res.masks.empty()) << "Masks should be a valid output vector"; | 
…rrecting preprocessing scalling issue on long images
…the custom result structs properly
… and segment anything interfaces changed) and added one more test to check the image dimensions W,H
… and configuration .hpp.in file
94cb8c7    to
    85b8df2      
    Compare
  
            
          
                .vscode/launch.json
              
                Outdated
          
        
      | "type": "cppdbg", | ||
| "request": "launch", | ||
| "program": "${workspaceFolder}/build/devel/lib/sam_onnx_ros/test_sam_onnx_ros", // Path to the executable | ||
| "program": "/home/amigo/ros/noetic/system/devel/lib/sam_onnx_ros/test11_sam_onnx_ros", // Path to the executable | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not desired, as the location might not be the same for everyone.
| std::tie(samSegmentors, params_encoder, params_decoder, res, resSam) = Initializer(); | ||
| std::filesystem::path current_path = std::filesystem::current_path(); | ||
| std::filesystem::path imgs_path = "/home/amigo/Documents/repos/hero_sam.bak/sam_inference/build/images"; // current_path / <- you could use | ||
| std::filesystem::path imgs_path = "/home/amigo/Documents/repos/yolo_onnx_ros/build/images"; // current_path / <- you could use | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This path should also be more generic. So preferably it works for everyone.
| utilities, result); | ||
| 
               | 
          ||
| return Ret; | ||
| const char* SAM::RunSession(const cv::Mat& iImg, std::vector<SEG::DL_RESULT>& oResult, SEG::MODEL_TYPE modelType, SEG::DL_RESULT& result) { | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| const char* SAM::RunSession(const cv::Mat& iImg, std::vector<SEG::DL_RESULT>& oResult, SEG::MODEL_TYPE modelType, SEG::DL_RESULT& result) { | |
| const char* SAM::RunSession(const cv::Mat& iImg, std::vector<SEG::DL_RESULT>& oResult, SEG::MODEL_TYPE modelType, SEG::DL_RESULT& result) | |
| { | 
| utilities, result); | ||
| 
               | 
          ||
| return Ret; | ||
| const char* SAM::RunSession(const cv::Mat& iImg, std::vector<SEG::DL_RESULT>& oResult, SEG::MODEL_TYPE modelType, SEG::DL_RESULT& result) { | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we really need to return a pointer? I think we can come up with a better system.
| auto output_tensors = | ||
| _session->Run(_options, _inputNodeNames.data(), &input_tensor, 1, | ||
| _outputNodeNames.data(), _outputNodeNames.size()); | ||
| if (_modelType < 4) { | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| if (_modelType < 4) { | |
| if (_modelType < 4) | |
| { | 
| else if (shape.size() <= 2) scoresIdx = i; | ||
| } | ||
| if (masksIdx < 0) { | ||
| std::cerr << "[SAM]: No 4D mask tensor found in decoder outputs." << std::endl; | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should use console_bridge.
| auto masksTensor = std::move(output_tensors[1]); | ||
| auto masksTensor = std::move(output_tensors[masksIdx]); | ||
| const float* scoresData = nullptr; | ||
| if (scoresIdx >= 0) { | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| if (scoresIdx >= 0) { | |
| if (scoresIdx >= 0) | |
| { | 
| if (scoresData) { | ||
| for (size_t i = 0; i < numMasks; ++i) { | ||
| const float s = scoresData[i]; | ||
| if (s > bestScore) { bestScore = s; bestMaskIndex = i; } | ||
| } | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| if (scoresData) { | |
| for (size_t i = 0; i < numMasks; ++i) { | |
| const float s = scoresData[i]; | |
| if (s > bestScore) { bestScore = s; bestMaskIndex = i; } | |
| } | |
| if (scoresData) | |
| { | |
| for (size_t i = 0; i < numMasks; ++i) | |
| { | |
| const float s = scoresData[i]; | |
| if (s > bestScore) | |
| { | |
| bestScore = s; | |
| bestMaskIndex = i; | |
| } | |
| } | 
| int processedWidth, processedHeight; | ||
| if (iImg.cols >= iImg.rows) | ||
| { | ||
| if (iImg.cols >= iImg.rows) { | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| if (iImg.cols >= iImg.rows) { | |
| if (iImg.cols >= iImg.rows) | |
| { | 
| } | ||
| else | ||
| { | ||
| } else { | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| } else { | |
| } | |
| else | |
| { | 
No description provided.