blob: 68cc5b2607f0fef517319415925e8511e3c0f5b6 [file] [log] [blame]
Filip Kujawa3004f202023-02-12 16:41:40 -08001#include "y2023/vision/game_pieces.h"
2
Filip Kujawab72ca2d2023-02-26 17:38:54 -08003#include <ctime>
4
Filip Kujawa3004f202023-02-12 16:41:40 -08005#include "aos/events/event_loop.h"
6#include "aos/events/shm_event_loop.h"
7#include "frc971/vision/vision_generated.h"
Filip Kujawa8c76e5d2023-04-08 16:20:27 -07008#include "y2023/vision/yolov5.h"
9#include <chrono>
Filip Kujawa3004f202023-02-12 16:41:40 -080010
Filip Kujawab72ca2d2023-02-26 17:38:54 -080011// The best_x and best_y are pixel (x, y) cordinates. The 'best'
12// game piece is picked on proximity to the specified cordinates.
13// The cordinate should represent where we want to intake a game piece.
14// (0, 360) was chosen without any testing, just a cordinate that
15// seemed reasonable.
16
17DEFINE_uint32(
18 best_x, 0,
19 "The 'best' game piece is picked based on how close it is to this x value");
20
21DEFINE_uint32(
22 best_y, 360,
23 "The 'best' game piece is picked based on how close it is to this y value");
24
Filip Kujawa3004f202023-02-12 16:41:40 -080025namespace y2023 {
26namespace vision {
27GamePiecesDetector::GamePiecesDetector(aos::EventLoop *event_loop)
Filip Kujawab72ca2d2023-02-26 17:38:54 -080028 : game_pieces_sender_(event_loop->MakeSender<GamePieces>("/camera")) {
Filip Kujawa8c76e5d2023-04-08 16:20:27 -070029 LOG(INFO) << "Before load model in constr";
30
31 model = MakeYOLOV5();
32 model->LoadModel("edgetpu_model.tflite");
33
34 LOG(INFO) << "After load model in constr";
Filip Kujawa3004f202023-02-12 16:41:40 -080035 event_loop->MakeWatcher("/camera", [this](const CameraImage &camera_image) {
36 this->ProcessImage(camera_image);
37 });
38}
39
40void GamePiecesDetector::ProcessImage(const CameraImage &image) {
Filip Kujawa8c76e5d2023-04-08 16:20:27 -070041 auto start = std::chrono::high_resolution_clock::now();
42 LOG(INFO) << reinterpret_cast<const void*>(image.data()->data());
43 cv::Mat image_color_mat(cv::Size(image.cols(), image.rows()), CV_8UC2,
44 (void *)image.data()->data());
45 std::vector<Detection> detections;
46 cv::Mat image_mat(cv::Size(image.cols(), image.rows()), CV_8UC3);
47 LOG(INFO) << reinterpret_cast<void*>(image_mat.ptr());
48 cv::cvtColor(image_color_mat, image_mat, cv::COLOR_YUV2BGR_YUYV);
49 LOG(INFO) << reinterpret_cast<void*>(image_mat.ptr());
Filip Kujawa3004f202023-02-12 16:41:40 -080050
Filip Kujawa8c76e5d2023-04-08 16:20:27 -070051 detections = model->ProcessImage(image_mat);
52 LOG(INFO) << reinterpret_cast<void*>(image_mat.ptr());
53 LOG(INFO) << reinterpret_cast<void*>(image_color_mat.ptr());
54
55 auto stop = std::chrono::high_resolution_clock::now();
56 LOG(INFO) << "INFERENCE TIME " << std::chrono::duration_cast<std::chrono::milliseconds>(stop - start).count();
Filip Kujawab72ca2d2023-02-26 17:38:54 -080057
Filip Kujawa3004f202023-02-12 16:41:40 -080058 auto builder = game_pieces_sender_.MakeBuilder();
59
Filip Kujawab72ca2d2023-02-26 17:38:54 -080060 std::vector<flatbuffers::Offset<GamePiece>> game_pieces_offsets;
Filip Kujawa3004f202023-02-12 16:41:40 -080061
Filip Kujawab72ca2d2023-02-26 17:38:54 -080062 float lowest_distance = std::numeric_limits<float>::max();
63 int best_distance_index = 0;
64 srand(time(0));
65
Filip Kujawa8c76e5d2023-04-08 16:20:27 -070066 for (size_t i = 0; i < detections.size(); i++) {
Filip Kujawab72ca2d2023-02-26 17:38:54 -080067 auto box_builder = builder.MakeBuilder<Box>();
Filip Kujawa8c76e5d2023-04-08 16:20:27 -070068 box_builder.add_h(detections[i].box.height);
69 box_builder.add_w(detections[i].box.width);
70 box_builder.add_x(detections[i].box.x);
71 box_builder.add_y(detections[i].box.y);
Filip Kujawab72ca2d2023-02-26 17:38:54 -080072 auto box_offset = box_builder.Finish();
73
74 auto game_piece_builder = builder.MakeBuilder<GamePiece>();
Filip Kujawa8c76e5d2023-04-08 16:20:27 -070075 switch (detections[i].class_id) {
76 case 0:
77 game_piece_builder.add_piece_class(Class::CONE_DOWN);
78 break;
79 case 1:
80 game_piece_builder.add_piece_class(Class::CONE_UP);
81 break;
82 case 2:
83 game_piece_builder.add_piece_class(Class::CUBE);
84 break;
85 default:
86 game_piece_builder.add_piece_class(Class::CONE_DOWN);
87 }
Filip Kujawab72ca2d2023-02-26 17:38:54 -080088 game_piece_builder.add_box(box_offset);
Filip Kujawa8c76e5d2023-04-08 16:20:27 -070089 game_piece_builder.add_confidence(detections[i].confidence);
Filip Kujawab72ca2d2023-02-26 17:38:54 -080090 auto game_piece = game_piece_builder.Finish();
91 game_pieces_offsets.push_back(game_piece);
92
93 // Center x and y values.
94 // Inference returns the top left corner of the bounding box
95 // but we want the center of the box for this.
96
Filip Kujawa8c76e5d2023-04-08 16:20:27 -070097 const int center_x = detections[i].box.x + detections[i].box.width / 2;
98 const int center_y = detections[i].box.y + detections[i].box.height / 2;
Filip Kujawab72ca2d2023-02-26 17:38:54 -080099
100 // Find difference between target x, y and the x, y
101 // of the bounding box using Euclidean distance.
102
103 const int dx = FLAGS_best_x - center_x;
104 const int dy = FLAGS_best_y - center_y;
105 const float distance = std::sqrt(dx * dx + dy * dy);
106
107 if (distance < lowest_distance) {
108 lowest_distance = distance;
109 best_distance_index = i;
110 }
111 };
Filip Kujawa3004f202023-02-12 16:41:40 -0800112
Filip Kujawa8c76e5d2023-04-08 16:20:27 -0700113 auto game_pieces_vector = builder.fbb()->CreateVector(game_pieces_offsets);
Filip Kujawa3004f202023-02-12 16:41:40 -0800114
115 auto game_pieces_builder = builder.MakeBuilder<GamePieces>();
116 game_pieces_builder.add_game_pieces(game_pieces_vector);
Filip Kujawab72ca2d2023-02-26 17:38:54 -0800117 game_pieces_builder.add_best_piece(best_distance_index);
Filip Kujawa3004f202023-02-12 16:41:40 -0800118
119 builder.CheckOk(builder.Send(game_pieces_builder.Finish()));
120}
121
122} // namespace vision
Filip Kujawa8c76e5d2023-04-08 16:20:27 -0700123} // namespace y2023