diff --git a/README.md b/README.md index fba650a..ff5dc0f 100644 --- a/README.md +++ b/README.md @@ -145,3 +145,4 @@ Flask App: ![Alt](/res/flaskapp.png "Flask App Screenshot") 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();