diff --git a/README.md b/README.md
index fba650a..ff5dc0f 100644
--- a/README.md
+++ b/README.md
@@ -145,3 +145,4 @@ Flask App: 
Information for how data is sent to and from the Orin on NetworkTables is stored on the following Google Doc https://docs.google.com/document/d/1zhl0dlSLXOld302rhOQrhItLp2thuDD308Gv3yvkHMY/edit?usp=sharing
+If you are an M-A Student looking for access to the build server, please fill out the form https://docs.google.com/document/d/14MWXYbr9kazaDxuQmgdHVRad1crJv6h6GJaEA4p0HTE/edit?usp=sharing
\ No newline at end of file
diff --git a/app/templates/index.html b/app/templates/index.html
index 4902600..cc0e493 100644
--- a/app/templates/index.html
+++ b/app/templates/index.html
@@ -143,8 +143,12 @@
AprilTag Detection with Controls and Pose Data
-
-
+
+
+
+
+
+
@@ -212,8 +216,11 @@ Pose Data:
};
});
- document.getElementById('rotate-image').onchange = function() {
- sendControl('rotate', this.checked);
+ document.getElementById('rotate-image-vertically').onchange = function() {
+ sendControl('flipVertical', this.checked);
+ };
+ document.getElementById('rotate-image-horizontally').onchange = function() {
+ sendControl('flipHorizontal', this.checked);
};
// Initial state
diff --git a/src/ws_server.cu b/src/ws_server.cu
index 12cbd4f..e03ab5d 100644
--- a/src/ws_server.cu
+++ b/src/ws_server.cu
@@ -42,8 +42,10 @@ using json = nlohmann::json;
DEFINE_int32(camera_idx, 0, "Camera index");
DEFINE_string(cal_file, "", "path name to calibration file");
-DEFINE_bool(rotate_img, true,
+DEFINE_bool(rotate_vertical, false,
"Rotates image by 180 degrees prior to detecting apriltags");
+DEFINE_bool(rotate_horizontal, false,
+ "Rotates image by 90 degrees prior to detecting apriltags");
enum ExposureMode { AUTO = 0, MANUAL = 1 };
@@ -78,8 +80,12 @@ class AprilTagHandler : public seasocks::WebSocket::Handler {
exposure_mode_ = j["value"].get();
settings_changed_ = true;
}
- if (j["type"] == "rotate") {
- gui_rotate_img_ = j["value"].get();
+ if (j["type"] == "flipVertical") {
+ flipVertical_ = j["value"].get();
+ settings_changed_ = true;
+ }
+ if(j["type"] == "flipHorizontal"){
+ flipHorizontal_ = j["value"].get();
settings_changed_ = true;
}
@@ -165,20 +171,20 @@ class AprilTagHandler : public seasocks::WebSocket::Handler {
return true;
}
-
- // TODO: Implement a faster version of this method!
- void rotateImage(cv::Mat* bgr_img, const float angle) {
- cv::Point2f center((bgr_img->cols - 1) / 2.0, (bgr_img->rows - 1) / 2.0);
- cv::Mat matRotation = cv::getRotationMatrix2D(center, angle, 1.0);
- cv::Mat rotatedImage;
- cv::warpAffine(*bgr_img, rotatedImage, matRotation, bgr_img->size());
- *bgr_img = rotatedImage.clone();
+//Flipcode -1 = both directions
+ void flipVertical(const cv::Mat& bgr_img, cv::Mat* output_img){
+ cv::flip(bgr_img, *output_img, 0);
+ }
+ void flipHorizontal(const cv::Mat& bgr_img, cv::Mat* output_img){
+ cv::flip(bgr_img, *output_img, 1);
+ }
+ void flipBoth(const cv::Mat& bgr_img, cv::Mat* output_img){
+ cv::flip(bgr_img, *output_img, -1);
}
-
void startReadAndSendThread(const int camera_idx, const std::string& cal_file,
- const bool rotate_img) {
+ const bool rotate_vertical, const bool rotate_horizontal) {
read_thread_ = std::thread(&AprilTagHandler::readAndSend, this, camera_idx,
- cal_file, rotate_img);
+ cal_file, rotate_vertical, rotate_horizontal);
}
void joinReadAndSendThread() {
@@ -205,7 +211,7 @@ class AprilTagHandler : public seasocks::WebSocket::Handler {
}
void readAndSend(const int camera_idx, const std::string& cal_file,
- const bool rotate_img) {
+ const bool rotate_vertical, const bool rotate_horizontal) {
std::cout << "Enabling video capture" << std::endl;
bool camera_started = false;
cv::VideoCapture cap;
@@ -286,7 +292,8 @@ class AprilTagHandler : public seasocks::WebSocket::Handler {
// Set the value of the gui rotate image variable to the value
// that is passed in on the command line. The user can change it
// later on from the gui.
- gui_rotate_img_ = rotate_img;
+ flipVertical_ = rotate_vertical;
+ flipHorizontal_ = rotate_horizontal;
int frame_counter = 0;
cv::Mat bgr_img, yuyv_img;
@@ -310,9 +317,20 @@ class AprilTagHandler : public seasocks::WebSocket::Handler {
frame_counter++;
auto overallstart = std::chrono::high_resolution_clock::now();
- if (gui_rotate_img_) {
- rotateImage(&bgr_img, 180.0);
+ //Let's check the time this takes, can always combine to one call if both are true later.
+ //Best case scenario is we don't place the camera wrong so we do not need this method at all.
+ if(flipVertical_ && flipHorizontal_){
+ flipBoth(bgr_img.clone(), &bgr_img);
+ } else {
+ // if (flipVertical_) {
+ // flipVertical(bgr_img.clone(), &bgr_img);
+ // }
+ // if (flipHorizontal_) {
+ // flipHorizontal(bgr_img.clone(), &bgr_img);
+ // }
}
+
+
cv::cvtColor(bgr_img, yuyv_img, cv::COLOR_BGR2YUV_YUYV);
auto gpudetectstart = std::chrono::high_resolution_clock::now();
detector.Detect(yuyv_img.data);
@@ -422,7 +440,8 @@ class AprilTagHandler : public seasocks::WebSocket::Handler {
std::atomic exposure_{50};
std::atomic exposure_mode_{0};
std::atomic settings_changed_{false};
- std::atomic gui_rotate_img_{false};
+ std::atomic flipVertical_{false};
+ std::atomic flipHorizontal_{false};
std::thread read_thread_;
};
@@ -452,7 +471,7 @@ int main(int argc, char* argv[]) {
handler
->startReadAndSendThread(FLAGS_camera_idx, FLAGS_cal_file,
- FLAGS_rotate_img);
+ FLAGS_rotate_vertical, FLAGS_rotate_horizontal);
server->serve("", 8080);
handler->stop();
handler->joinReadAndSendThread();