Skip to content
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

CV Pipeline Integration #73

Merged
merged 82 commits into from
Apr 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
82 commits
Select commit Hold shift + click to select a range
f0b29e5
initial cv pipeline skeleton
atar13 Jan 4, 2024
01b63fc
added cv utilities tests
atar13 Jan 4, 2024
bbb84fe
mock camera implementation
atar13 Jan 5, 2024
94070c4
SearchState
atar13 Jan 5, 2024
dff1aee
unit test mock camera
atar13 Jan 5, 2024
dc4fdd8
cv pipeline integration test
atar13 Jan 5, 2024
952e020
moved pathing unit tests to their own folder
atar13 Jan 5, 2024
691b8ec
linter: allow non-Google library versions
Samir-Rashid Jan 15, 2024
534de34
cv: lint camera orchestrator
Samir-Rashid Jan 15, 2024
7bc51f8
added a localization algorithm
dn820 Feb 7, 2024
8094ac2
added terrain height
dn820 Feb 7, 2024
f227506
update ubuntu version :pray: (#78)
Tyler-Lentz Jan 17, 2024
6280e08
Chore/update ubuntu version (#79)
Tyler-Lentz Jan 17, 2024
a43cb42
Chore/update ubuntu version (#80)
Tyler-Lentz Jan 18, 2024
a7c98dd
Chore/update ubuntu version (#81)
Tyler-Lentz Jan 18, 2024
53b0368
Chore/update ubuntu version (#82)
Tyler-Lentz Jan 18, 2024
e0d4fbd
Chore/update ubuntu version (#83)
Tyler-Lentz Jan 18, 2024
3320b54
Chore/update ubuntu version (#84)
Tyler-Lentz Jan 18, 2024
0d11022
Chore/update ubuntu version (#85)
Tyler-Lentz Jan 18, 2024
a5ba8e9
Chore/update ubuntu version (#86)
Tyler-Lentz Jan 18, 2024
55d2830
Chore/update ubuntu version (#87)
Tyler-Lentz Jan 18, 2024
30202ff
Chore/update ubuntu version (#88)
Tyler-Lentz Jan 18, 2024
97e8514
Chore/update ubuntu version (#89)
Tyler-Lentz Jan 18, 2024
c121c7e
update Dockerfile to install pyenv and use it to build libtorch
atar13 Jan 21, 2024
34220d6
GCS Networking & General OBC Infrastructure (#55)
Tyler-Lentz Jan 22, 2024
498cb4b
reintroduce git submodule clone script
Tyler-Lentz Jan 22, 2024
b8789eb
actions: run docker action on project release
Samir-Rashid Jan 22, 2024
507097b
fix docker github action
Tyler-Lentz Jan 22, 2024
d5c48f8
fix filter frfr this time (#93)
Tyler-Lentz Jan 22, 2024
4f158af
Chore/dockerfile filter (#94)
Tyler-Lentz Jan 22, 2024
a90a08a
Hide ghcr auth instructions (#95)
Samir-Rashid Jan 24, 2024
440fead
added gnuplot to Docker for matplotplus (#97)
atar13 Jan 28, 2024
2417042
QT_QPA_PLATFORM env var for headless mode
atar13 Jan 31, 2024
9ba2e79
docker comments are sus
atar13 Jan 31, 2024
9e12d78
GCS Server: Mission Input (#96)
Tyler-Lentz Feb 5, 2024
dcf444b
cache apt-update instructions in Dockerfile (#109)
atar13 Feb 14, 2024
dff8c3e
add magick++ dependency
atar13 Feb 14, 2024
fd9c6cc
Mavlink Client (#107)
Tyler-Lentz Feb 16, 2024
781b538
cv pipeline integration test
atar13 Jan 5, 2024
d17807e
Add matching constructor code
AchuthKrishna Jan 21, 2024
8f2326b
Add match() implementation
AchuthKrishna Jan 21, 2024
b943852
Parameterize model path
AchuthKrishna Jan 21, 2024
a9ee234
Add changes to get compilation
AchuthKrishna Feb 1, 2024
6cf5fb9
Add fixes to Input
AchuthKrishna Feb 3, 2024
783cb83
Small fix to index
AchuthKrishna Feb 3, 2024
635564b
Fix NaN Error
AchuthKrishna Feb 9, 2024
43e63be
Add comments explaining from_blob
AchuthKrishna Feb 10, 2024
8c8b573
Refactor referenceImages
AchuthKrishna Feb 10, 2024
ce59aad
Clean Comments
AchuthKrishna Feb 10, 2024
6c83eab
missed this during rebase
atar13 Feb 17, 2024
4304cb0
adding cmake deps to get things to compile
atar13 Feb 17, 2024
3f6b44d
update pipeline and matching for protobuf datatypes
atar13 Feb 17, 2024
ed8a44f
Address PR Comments
AchuthKrishna Feb 21, 2024
68939df
Revert error handling, do linting
AchuthKrishna Feb 21, 2024
96f5ec0
Merge pull request #106 from tritonuas/feat/cv-orchestrator-matching
AchuthKrishna Feb 21, 2024
bde6948
gitkeeped models and images folders
atar13 Feb 25, 2024
dc86445
ignore correct images path
atar13 Feb 25, 2024
844746b
make targets to pull model files from google drive
atar13 Feb 26, 2024
690f1f6
split up localization implementations
atar13 Feb 28, 2024
c434527
initial localization unit tests
atar13 Feb 28, 2024
0d479ae
finished integrating segmentation
shijiew555 Mar 1, 2024
8a4bebe
Merge feat/cv-orchestrator into cv-segmentation-integration. Add mode…
shijiew555 Mar 1, 2024
14a8e3d
Merge remote-tracking branch 'origin/feat/cv-orchestrator' into cv-se…
shijiew555 Mar 1, 2024
80a3bff
complete integration test cv_segmentation.cpp
shijiew555 Mar 2, 2024
74b2c9f
fix lint
shijiew555 Mar 3, 2024
a2c143b
fix torchscript error
shijiew555 Mar 3, 2024
d80d340
Merge pull request #123 from tritonuas/cv-segmentation-integration
shijiew555 Mar 4, 2024
e3e663a
Merge remote-tracking branch 'origin/main' into feat/cv-orchestrator
atar13 Mar 29, 2024
0415e87
add imagemagick to cv_pipeline target
atar13 Mar 31, 2024
07304fc
move cv_pipeline to use BottleDropIndex
atar13 Mar 31, 2024
57c47fd
all targets compile
atar13 Apr 1, 2024
f7f8b55
move to use log statements
atar13 Apr 1, 2024
9031648
links to model/image drive files
atar13 Apr 1, 2024
b24ddcf
Merge remote-tracking branch 'origin/main' into feat/cv-orchestrator
atar13 Apr 1, 2024
c2c2a26
forgot )
atar13 Apr 1, 2024
48b7f41
satisfy cpplint gods
atar13 Apr 1, 2024
ab5be02
temporarily removing localization test assert 😳
atar13 Apr 1, 2024
0a6ca2a
fix model downloading make targets
atar13 Apr 2, 2024
e124a4c
automate pulling matching test images
atar13 Apr 2, 2024
7bb880e
remove extra comment block
atar13 Apr 2, 2024
b2ba112
satisfy cpplint gods again
atar13 Apr 2, 2024
5a8ee3e
comments about pulling matching/segmentation models
atar13 Apr 2, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,6 @@
{
"name": "Existing Dockerfile",
"image": "ghcr.io/tritonuas/obcpp:main",
// "build": {
// "dockerfile": "Dockerfile"
// },

"customizations": {
"vscode": {
Expand Down
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ _deps/
Testing/
imgs/

models/*
!models/.gitkeep

tests/integration/images/*
!tests/integration/images/.gitkeep

.vscode/*
!.vscode/c_cpp_properties.json

Expand Down
104 changes: 92 additions & 12 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -117,11 +117,16 @@ target_add_mavsdk(playground)
target_add_matplot(playground)
target_add_protobuf(playground)
target_add_loguru(playground)
# for some reason calling target_add_imagemagick here conflicts with, so we are including/linking without the function call
# target_add_imagemagick(path_plotting)
target_include_directories(playground PRIVATE ${ImageMagick_INCLUDE_DIRS})
target_link_libraries(playground PRIVATE -Wl,--copy-dt-needed-entries ${ImageMagick_LIBRARIES})

# load_torchvision_model
add_executable(load_torchvision_model tests/integration/load_torchvision_model.cpp)
add_executable(load_torchvision_model "tests/integration/load_torchvision_model.cpp")
target_add_torch(load_torchvision_model)
target_add_torchvision(load_torchvision_model)
target_add_loguru(load_torchvision_model)

# mavlink-client
add_executable(mavlink_client ${SOURCES} "tests/integration/mavlink_client.cpp")
Expand All @@ -135,6 +140,58 @@ target_add_httplib(mavlink_client)
target_add_mavsdk(mavlink_client)
target_add_matplot(mavlink_client)
target_add_loguru(mavlink_client)
# for some reason calling target_add_imagemagick here conflicts with, so we are including/linking without the function call
# target_add_imagemagick(path_plotting)
target_include_directories(mavlink_client PRIVATE ${ImageMagick_INCLUDE_DIRS})
target_link_libraries(mavlink_client PRIVATE -Wl,--copy-dt-needed-entries ${ImageMagick_LIBRARIES})

# cv_pipeline
add_executable(cv_pipeline ${SOURCES} "tests/integration/cv_pipeline.cpp")
target_add_json(cv_pipeline)
target_add_matplot(cv_pipeline)
target_add_opencv(cv_pipeline)
target_add_loguru(cv_pipeline)
target_add_httplib(cv_pipeline)
target_add_protobuf(cv_pipeline)
target_add_torch(cv_pipeline)
target_add_torchvision(cv_pipeline)
target_add_mavsdk(cv_pipeline)
target_add_loguru(cv_pipeline)
# for some reason calling target_add_imagemagick here conflicts with, so we are including/linking without the function call
# target_add_imagemagick(path_plotting)
target_include_directories(cv_pipeline PRIVATE ${ImageMagick_INCLUDE_DIRS})
target_link_libraries(cv_pipeline PRIVATE -Wl,--copy-dt-needed-entries ${ImageMagick_LIBRARIES})

# cv_matching
add_executable(cv_matching ${SOURCES} "tests/integration/cv_matching.cpp")
target_add_json(cv_matching)
target_add_matplot(cv_matching)
target_add_opencv(cv_matching)
target_add_torch(cv_matching)
target_add_torchvision(cv_matching)
target_add_loguru(cv_matching)
target_add_httplib(cv_matching)
target_add_mavsdk(cv_matching)
# for some reason calling target_add_imagemagick here conflicts with, so we are including/linking without the function call
# target_add_imagemagick(path_plotting)
target_include_directories(cv_matching PRIVATE ${ImageMagick_INCLUDE_DIRS})
target_link_libraries(cv_matching PRIVATE -Wl,--copy-dt-needed-entries ${ImageMagick_LIBRARIES})


# cv_segmentation
add_executable(cv_segmentation ${SOURCES} "tests/integration/cv_segmentation.cpp")
target_add_json(cv_segmentation)
target_add_matplot(cv_segmentation)
target_add_opencv(cv_segmentation)
target_add_torch(cv_segmentation)
target_add_torchvision(cv_segmentation)
target_add_loguru(cv_segmentation)
target_add_httplib(cv_segmentation)
target_add_mavsdk(cv_segmentation)
# for some reason calling target_add_imagemagick here conflicts with, so we are including/linking without the function call
# target_add_imagemagick(path_plotting)
target_include_directories(cv_segmentation PRIVATE ${ImageMagick_INCLUDE_DIRS})
target_link_libraries(cv_segmentation PRIVATE -Wl,--copy-dt-needed-entries ${ImageMagick_LIBRARIES})

# path_plotting
add_executable(path_plotting ${SOURCES} tests/integration/path_plotting.cpp)
Expand All @@ -154,6 +211,15 @@ target_link_libraries(path_plotting PRIVATE -Wl,--copy-dt-needed-entries ${Image
# airdrop_sockets
add_executable(airdrop_sockets src/network/airdrop_sockets.c tests/integration/airdrop_sockets.c)
target_include_directories(airdrop_sockets PRIVATE ${INCLUDE_DIRECTORY})

add_executable(camera_playground tests/integration/camera_playground.cpp)
target_include_directories(camera_playground PRIVATE ${INCLUDE_DIRECTORY})
target_add_arena(camera_playground)
add_custom_target(
run_camera_playground
${CMAKE_COMMAND}
-E env LD_LIBRARY_s/target_siamese_1.pt
)
# =============================

# =============================
Expand All @@ -163,25 +229,38 @@ add_subdirectory(${DEPS_DIRECTORY}/google-test)
# =============================

# =============================
# Integration tests
add_executable(camera_playground tests/integration/camera_playground.cpp)
target_include_directories(camera_playground PRIVATE ${INCLUDE_DIRECTORY})
target_add_arena(camera_playground)
add_custom_target(
run_camera_playground
${CMAKE_COMMAND}
-E env LD_LIBRARY_s/target_siamese_1.pt
# Pull models
add_custom_target(pull_models
DEPENDS pull_saliency pull_matching pull_segmentation
)

# Saliency model
add_custom_target(pull_saliency
COMMAND gdown 1S1IfXlGs_pCH49DwZmbD-tZA5YH0A1gx -O ${CMAKE_BINARY_DIR}/../models/torchscript_19.pth
)

# Matching model
add_custom_target(pull_matching
COMMAND gdown 1NeFiAfSSLXAZWlehfd0ox7p_jFF4YdrO -O ${CMAKE_BINARY_DIR}/../models/target_siamese_1.pt
)


# Segmentation model
add_custom_target(pull_segmentation
COMMAND gdown https://drive.google.com/file/d/1U2EbfJFzcjVnjTuD6ud-bIf8YOiEassf -O ${CMAKE_BINARY_DIR}/../models/fcn-model_20-epochs_06-01-2023T21-16-02.pth
COMMAND gdown 1U2EbfJFzcjVnjTuD6ud-bIf8YOiEassf -O ${CMAKE_BINARY_DIR}/../models/fcn-model_20-epochs_06-01-2023T21-16-02.pth
)
# =============================

# =============================
# Pull testing images
#

# pull cropped images from fraternal_targets testing folder
add_custom_target(pull_matching_test_images
COMMAND gdown 1opxdXw75jSQZu9s61njE6hjQkfHiKvgp -O ${CMAKE_BINARY_DIR}/../tests/integration/images/test.zip &&
mkdir -p ${CMAKE_BINARY_DIR}/../tests/integration/images/matching_cropped &&
unzip ${CMAKE_BINARY_DIR}/../tests/integration/images/test.zip -d ${CMAKE_BINARY_DIR}/../tests/integration/images/matching_cropped
)

# =============================

# =============================
Expand All @@ -194,7 +273,8 @@ if(CPPLINT)
add_custom_target(lint
COMMAND cpplint
# Do not require licenses, TODO assignment, Google versions of C++ libs
--filter=-legal,-readability/todo,-build/c++11
# also don't check for runtime/references since Google's public style guidelines are behind https://github.com/cpplint/cpplint/issues/148
--filter=-legal,-readability/todo,-build/c++11,-runtime/references
--linelength=100
--recursive
../src
Expand Down
51 changes: 36 additions & 15 deletions include/camera/interface.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,26 @@

#include <string>
#include <vector>
#include <memory>

#include <nlohmann/json.hpp>
#include <opencv2/opencv.hpp>

// class to contain all telemetry that should be tagged with an image.
// In the future this could be in a mavlink file.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is a mavlink file

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking of a mavlink.hpp that would be added by Jasper in his Mavlink Client.

class ImageTelemetry {
public:
ImageTelemetry(double latitude, double longitude, double altitude, double airspeed, double yaw,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could use the GPSCoord type. I like how you made a ImageTelemetry type so it is easy to add/remove fields in the future. I think it is more conventional to make this a struct since everything is public. Also this should have a default initializer {} for all the values.

Copy link
Member Author

@atar13 atar13 Jan 17, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like the idea of removing some of the fields in favor of GPSCoord. I have also changed ImageTelemetry to a struct.

What do you mean by default initializer? Is that the same as the constructor implementation in camera/interface.cpp? https://github.com/tritonuas/obcpp/blob/feat/cv-orchestrator/src/camera/interface.cpp#L3-L11

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that will make sure this all gets zero initialized.

double pitch, double roll);
const double latitude;
const double longitude;
const double altitude;
const double airspeed;
const double yaw;
const double pitch;
const double roll;
};

/*
* FYI: this is class that will standardize image data but
* if all of our cameras have a uniform image output type
Expand All @@ -19,14 +35,17 @@
class ImageData {
private:
const std::string NAME;
const std::string PATHS;
const std::string PATH;
const cv::Mat DATA;
const ImageTelemetry TELEMETRY;

public:
ImageData(std::string NAME, std::string PATH, cv::Mat DATA);
std::string getName();
std::string getPath();
cv::Mat getData();
ImageData(std::string NAME, std::string PATH, cv::Mat DATA, ImageTelemetry TELEMETRY);
ImageData(const ImageData&) = default;
std::string getName() const;
std::string getPath() const;
cv::Mat getData() const;
ImageTelemetry getTelemetry() const;
};

// ? possibly convert most common / important json fields to
Expand All @@ -40,7 +59,7 @@ class CameraConfiguration {

void updateConfig(nlohmann::json newSetting);

void updateConfigField(std::string key, T value);
// void updateConfigField(std::string key, T value);

nlohmann::json getConfig();

Expand All @@ -50,8 +69,8 @@ class CameraConfiguration {
class CameraInterface {
private:
CameraConfiguration config;
ImageData recentPicture; // might need to move it to public
bool doneTakingPicture; // overengineering time
std::unique_ptr<ImageData> recentPicture; // might need to move it to public
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well at least it should be fine if it's private ...because the smart pointer is handling all the scoping memory for us.

// overengineering time

🤔 I cannot give useful advice on the design of this interface ...because I have no idea what kinds of functionality we have been using in the past since '87. I do not want to block based on any minor improvements, so as long as you are happy with this we should forge ahead. That being said, it would be good to reping the people in your comment to get a better set of eyes.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I should have removed that public comment. That was made by Boris in the original interface. And so was the over engineering comment. This PR wasn't supposed to drastically change the camera interface but we've already had a design talk with Boris during the meeting on how to simplify the API.

bool doneTakingPicture; // overengineering time
std::string uploadPath;
// Interpreter interp
// TODO: SERVER CONNECTION HERE ?
Expand All @@ -61,19 +80,21 @@ class CameraInterface {
public:
explicit CameraInterface(CameraConfiguration config);

void connect();
virtual ~CameraInterface() = default;

virtual void connect() = 0;

bool verifyConnection();
virtual bool verifyConnection() = 0;

void takePicture();
virtual void takePicture() = 0;

ImageData getLastPicture();
virtual ImageData getLastPicture() = 0;

bool takePictureForSeconds(int sec);
virtual bool takePictureForSeconds(int sec) = 0;

void startTakingPictures(double intervalSec);
virtual void startTakingPictures(double intervalSec) = 0;

bool isDoneTakingPictures();
virtual bool isDoneTakingPictures() = 0;

CameraConfiguration getConfig();

Expand Down
24 changes: 24 additions & 0 deletions include/camera/mock.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#ifndef INCLUDE_CAMERA_MOCK_HPP_
#define INCLUDE_CAMERA_MOCK_HPP_

#include <memory>

#include "camera/interface.hpp"

class MockCamera : public CameraInterface {
public:
explicit MockCamera(CameraConfiguration config);
~MockCamera() = default;
void connect() override;
bool verifyConnection() override;
void takePicture() override;
ImageData getLastPicture() override;
bool takePictureForSeconds(int sec) override;
void startTakingPictures(double intervalSec) override;
bool isDoneTakingPictures() override;

private:
std::unique_ptr<ImageData> lastPicture;
};

#endif // INCLUDE_CAMERA_MOCK_HPP_
55 changes: 55 additions & 0 deletions include/cv/classification.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#ifndef INCLUDE_CV_CLASSIFICATION_HPP_
#define INCLUDE_CV_CLASSIFICATION_HPP_

#include <string>
#include <opencv2/opencv.hpp>

struct ClassificationResults {
// TODO: replace with protobuf structs instead of strings
std::string shape;
std::string shapeColor;
std::string character;
std::string characterColor;
};

// Classification is responsible for predicting characteristics about
// ground comptition targets. These characterisitcs include shape type,
// alphanumeric character type, shape color, and alphanumeric character color.
// Currently, the shape and character classifiers are implemented using a
// Convolutional Neural Network (CNN).
// The color classifier is implented using a K-nearest neigbors model (KNN)
// The implementation of the models themselves can be found here:
// https://github.com/tritonuas/taxonomy-101
// In this class we will take the pretrained models and use them to make
// inferences.
class Classification {
public:
// classify takes a cropped image of the target (saliency output) and
// two binary masks to represent which region of pixels correspond to
// shape and character respectivel (output of segmentation). Using this
// data, the shape type, character type, shape color and character color
// will be predicted.
ClassificationResults classify(cv::Mat croppedImage, cv::Mat shapeMask, cv::Mat characterMask);

private:
// classifyShape takes a cropped image of the target (output of saliency)
// and a binary mask (output of segmentation). The binary mask should
// represent which region of pixels correspond to the shape region of
// the target.
std::string classifyShape(cv::Mat croppedImage, cv::Mat shapeMask);

// classifyShape takes a cropped image of the target (output of saliency)
// and a binary mask (output of segmentation). The binary mask should
// represent which region of pixels correspond to the character region of
// the target.
std::string classifyCharacter(cv::Mat croppedImage, cv::Mat characterMask);

// classify the primary color of a region described by a binary mask.
// This can be used for finding both shape and character color since
// we will use the same algorithm to detect the primary color in
// whatever region the mask describes. All that changes is the mask
// that's passed in.
std::string classifyColor(cv::Mat croppedImage, cv::Mat mask);
};

#endif // INCLUDE_CV_CLASSIFICATION_HPP_
Loading