Visual Vibration Tracking 0.2
Загрузка...
Поиск...
Не найдено
vibration_detector.cpp
1#include "VVT-V2\vibration_detector.h"
2
3VibrationDetector::VibrationDetector(std::string input_file_name, std::string output_file_name, std::string window_name) :
4 input_file_name_{ input_file_name },
5 output_file_name_{ output_file_name },
6 window_name_{ window_name },
7 warping_figure_selecting_{ false },
8 colored_point_mode_{ COLORING_BASED_ON_FREQUENCY },
9 sensivity_in_percents_{ 1 },
10 roi_selecting_{ false },
11 point_id_{ 0 },
12 current_mode_{ DEFAULT },
13 fullscreen_{ false }
14{
15 roi_selected_ = false;
16 lk_win_size_ = 40;
17 level_amount_ = 1;
18
20
22
24}
25
26VibrationDetector::~VibrationDetector()
27{
28 delete frame_handler;
30 while (!vec_lonely_point_handlers_.empty())
31 {
32 delete(*(std::begin(vec_lonely_point_handlers_)));
33 // удаляем первую точку (первую в векторе и по сути первую по номеру)
35 }
36}
37
39{
40 for (int i = 0; i < l_click_queue_.size(); i++)
41 {
43 }
44 for (int i = 0; i < c_point_queue_.size(); i++)
45 {
47 }
48 for (int i = 0; i < delete_queue_.size(); i++)
49 {
51 }
52 l_click_queue_.clear();
53 c_point_queue_.clear();
54 delete_queue_.clear();
55}
56
57void VibrationDetector::CreateNewPoint(Point2f mouse_coordinates)
58{
59 LonelyPointHandler* point_handler_ = new LonelyPointHandler(mouse_coordinates, fps_, point_id_++, res_mp_, output_csv_file_name_);
60 vec_lonely_point_handlers_.push_back(point_handler_);
61}
62
63void VibrationDetector::LeftClickHandler(Point2f mouse_coordinates)
64{
65 // если вектор пустой - просто добавляем новую точку
67 {
68 bool flag_colored_interacted_ = false;
69 for (int i = 0; i < vec_colored_point_handlers_.size(); i++)
70 {
72 {
73 vec_colored_point_handlers_[i]->SetHistogramFlag(true);
74 flag_colored_interacted_ = true;
75 }
76 }
77 if (flag_colored_interacted_ == false)
78 CreateNewPoint(mouse_coordinates);
79 }
80 else
81 {
82 // проходим по всему вектору точек
83 bool flag_lonely_interacted_ = false;
84 bool flag_colored_interacted_ = false;
85 for (int i = 0; i < vec_lonely_point_handlers_.size(); i++)
86 {
87 // если произошло пересечение с мышкой, то новую точку не добавляем
89 {
90 vec_lonely_point_handlers_[i]->SetHistogramFlag(true);
91 //vec_lonely_point_handlers_[i]->SetHistogramWindowProperty(WND_PROP_TOPMOST, true);
92 flag_lonely_interacted_ = true;
93 }
94 }
95 for (int i = 0; i < vec_colored_point_handlers_.size(); i++)
96 {
98 {
99 vec_colored_point_handlers_[i]->SetHistogramFlag(true);
100 flag_colored_interacted_ = true;
101 }
102 }
103 if (flag_lonely_interacted_ == false && flag_colored_interacted_ == false)
104 CreateNewPoint(mouse_coordinates);
105 }
106}
107
108void VibrationDetector::CreateNewColoredPoint(Point2f mouse_coordinates)
109{
110 ColoredPointHandler* point_handler_ = new ColoredPointHandler(mouse_coordinates, fps_, point_id_++, res_mp_, output_csv_file_name_);
111 vec_colored_point_handlers_.push_back(point_handler_);
112}
113
114void VibrationDetector::DeletePoints(Point2i mouse_coordinates)
115{
116 // создаем вектор ID (номеров) для точек, которые удалим
117 std::vector<int> lon_point_ids_to_be_deleted_;
118 std::vector<int> col_point_ids_to_be_deleted_;
119
120 // проходим по всему вектору точек
121 for (int i = 0; i < vec_lonely_point_handlers_.size(); i++)
122 {
123 // если произошло пересечение с мышкой, вносим ID (номер) точки в "вектор точек на удаление" или уровень доверия" точки стал слишком маленький, так же удаляем точку
125 {
126 lon_point_ids_to_be_deleted_.push_back(i);
127 }
128 }
129 for (int i = 0; i < vec_colored_point_handlers_.size(); i++)
130 {
131 // если произошло пересечение с мышкой, вносим ID (номер) точки в "вектор точек на удаление" или уровень доверия" точки стал слишком маленький, так же удаляем точку
133 {
134 col_point_ids_to_be_deleted_.push_back(i);
135 }
136 }
137 std::cout << "DEBUG: deleting " << lon_point_ids_to_be_deleted_.size() + col_point_ids_to_be_deleted_.size() << " point" << std::endl;
138
139 // проходимся по вектору точек на удаление
140 while (!lon_point_ids_to_be_deleted_.empty())
141 {
142 delete(*(std::begin(vec_lonely_point_handlers_) + lon_point_ids_to_be_deleted_[0]));
143 // удаляем первую точку (первую в векторе и по сути первую по номеру)
144 vec_lonely_point_handlers_.erase(std::begin(vec_lonely_point_handlers_) + lon_point_ids_to_be_deleted_[0]);
145 // удаляем номер только что удалённой точки из вектора
146 lon_point_ids_to_be_deleted_.erase(std::begin(lon_point_ids_to_be_deleted_));
147 // меняем номера других точек в списке, если там ещё что-то есть
148 for (int i = 0; i < lon_point_ids_to_be_deleted_.size(); i++)
149 {
150 // уменьшаем номер оставшихся в очереди на удаление точек на один, тк номера в vec_point_handlers сместились на один вниз (влево и тп, как удобнее для понимания :))
151 lon_point_ids_to_be_deleted_[i] = lon_point_ids_to_be_deleted_[i] - 1;
152 }
153 }
154
155 while (!col_point_ids_to_be_deleted_.empty())
156 {
157 delete(*(std::begin(vec_colored_point_handlers_) + col_point_ids_to_be_deleted_[0]));
158 // удаляем первую точку (первую в векторе и по сути первую по номеру)
159 vec_colored_point_handlers_.erase(std::begin(vec_colored_point_handlers_) + col_point_ids_to_be_deleted_[0]);
160 // удаляем номер только что удалённой точки из вектора
161 col_point_ids_to_be_deleted_.erase(std::begin(col_point_ids_to_be_deleted_));
162 // меняем номера других точек в списке, если там ещё что-то есть
163 for (int i = 0; i < col_point_ids_to_be_deleted_.size(); i++)
164 {
165 // уменьшаем номер оставшихся в очереди на удаление точек на один, тк номера в vec_point_handlers сместились на один вниз (влево и тп, как удобнее для понимания :))
166 col_point_ids_to_be_deleted_[i] = col_point_ids_to_be_deleted_[i] - 1;
167 }
168 }
169
170 if (vec_lonely_point_handlers_.empty())
171 {
174 }
175}
176
178{
179 // Проходимся по вектору хэндлеров
180 while (!vec_colored_point_handlers_.empty())
181 {
182 delete(*(std::begin(vec_colored_point_handlers_)));
183 // удаляем первую точку (первую в векторе и по сути первую по номеру)
185 }
186
187 if (vec_lonely_point_handlers_.empty())
188 {
191 }
192}
193
195{
196 for (int i = 0; i < vec_lonely_point_handlers_.size(); i++)
197 {
198 if (vec_lonely_point_handlers_[i]->GetCurrentConfidenceLevel() < 0.0)
199 {
200 delete(*(std::begin(vec_lonely_point_handlers_) + i));
201 // удаляем первую точку (первую в векторе и по сути первую по номеру)
203 }
204 }
205 for (int i = 0; i < vec_colored_point_handlers_.size(); i++)
206 {
207 if ((vec_colored_point_handlers_[i]->GetCurrentConfidenceLevel() < 0.0))
208 {
209 delete(*(std::begin(vec_colored_point_handlers_) + i));
210 // удаляем первую точку (первую в векторе и по сути первую по номеру)
212 }
213 }
214}
215
216// callback function for determining the event click on mouse
217void VibrationDetector::OnMouse(int event, int x, int y, int flags, void* userdata)
218{
219 VibrationDetector* d = static_cast<VibrationDetector*>(userdata);
220 d->DetectEvent(event, x, y, flags);
221}
222
223// "helper" function for implementing callback function as a method of C++ class
224void VibrationDetector::DetectEvent(int event, int x, int y, int flags)
225{
226 switch (current_mode_)
227 {
228 case DEFAULT:
229 {
230 DefaultModeHandler(event, x, y);
231 break;
232 }
233 case SELECTINGROI:
234 {
235 RoiSelectionModeHandler(event, x, y);
236 break;
237 }
238 case PAUSE:
239 {
240 break;
241 }
242 }
243}
244
245void VibrationDetector::DefaultModeHandler(int event, int x, int y)
246{
247 switch (event)
248 {
249 case EVENT_LBUTTONDOWN:
250 {
251 // Проверяем флаги выделения ROI и фигуры для варпа
252 if (!roi_selecting_)
253 {
254 l_click_queue_.push_back(Point2i(x, y));
255 }
256 break;
257 }
258 case EVENT_RBUTTONDOWN:
259 {
261 delete_queue_.push_back(Point2i(x, y));
262 break;
263 }
264 case EVENT_MOUSEMOVE:
265 {
266 // Координаты последнего перемещения мыши
269 }
270 }
271}
273{
274 switch (event)
275 {
276 case EVENT_LBUTTONDOWN:
277 {
278 // Удаляем старые "цветные" точки
280 // Делаем флаг для выделения ROI активным
281 roi_selecting_ = true;
282 // Сохраняем координаты клика как одну из границ ROI
283 tl_click_coords_.x = x;
284 tl_click_coords_.y = y;
285 break;
286 }
287 case EVENT_LBUTTONUP:
288 {
289 if (roi_selecting_)
290 {
291 // Отключаем флаг для выделения ROI
292 roi_selecting_ = false;
293 roi_selected_ = true;
294 // Сохраняем последние позиции
297 }
298 break;
299 }
300 case EVENT_MOUSEMOVE:
301 {
302 // Координаты последнего перемещения мыши
305 break;
306 }
307 }
308}
309
310Mat VibrationDetector::MakeWarpedFrame(Mat frame, std::vector<Point2i> warping_figure)
311{
312 int coeff = 1;
313
314 Point2f src[4] = { warping_figure[0], warping_figure[1], warping_figure[2], warping_figure[3] };
315
316 for (int i = 0; i < 4; i++)
317 {
318 src[i].x = src[i].x * coeff;
319 src[i].y = src[i].y * coeff;
320 warping_figure[i].x = warping_figure[i].x * coeff;
321 warping_figure[i].y = warping_figure[i].y * coeff;
322 }
323
324 /*float w =
325 sqrt((warping_figure[2].x - warping_figure[3].x) * (warping_figure[2].x - warping_figure[3].x)
326 +
327 (warping_figure[2].y - warping_figure[3].y) * (warping_figure[2].y - warping_figure[3].y)) * 2 / 3;*/
328 float h =
329 sqrt((warping_figure[1].x - warping_figure[3].x) * (warping_figure[1].x - warping_figure[3].x)
330 +
331 (warping_figure[1].y - warping_figure[3].y) * (warping_figure[1].y - warping_figure[3].y));
332 float w = h * 2 / 3;
333
334 Point2f dst[4] = { {0.0f,0.0f},{w,0.0f},{0.0f,h},{w,h} };
335
336 Mat matrix = getPerspectiveTransform(src, dst);
337 warpPerspective(frame, frame, matrix, Point(w, h));
338
339 return frame;
340}
341
343{
344 // Находим и удаляем точки с низким параметром confidence
346
347 std::vector<Point2f> PrevPts;
348 std::vector<Point2f> NextPts;
349 std::vector<uchar> status;
350 std::vector<float> error;
351
352 // "Достаем" из lonely point handler'ов последние найденные точки, чтобы использовать их в качестве "начальных" значений для calcOpticalFlowPyrLK()
353 for (int i = 0; i < vec_lonely_point_handlers_.size(); i++)
354 {
355 PrevPts.push_back(vec_lonely_point_handlers_[i]->GetLastFoundCoordinates());
356 }
357 // "Достаем" из colored point handler'ов последние найденные точки, чтобы использовать их в качестве "начальных" значений для calcOpticalFlowPyrLK()
358 for (int i = 0; i < vec_colored_point_handlers_.size(); i++)
359 {
360
361 PrevPts.push_back(vec_colored_point_handlers_[i]->GetLastFoundCoordinates());
362 }
363
364 if ((!vec_lonely_point_handlers_.empty()) || (!vec_colored_point_handlers_.empty()))
365 // вызов Lucas-Kanade алгоритма
366 calcOpticalFlowPyrLK(
369 PrevPts,
370 NextPts,
371 status,
372 error,
375 TermCriteria(
376 TermCriteria::MAX_ITER | TermCriteria::EPS,
377 500,
378 0.001
379 ),
380 OPTFLOW_LK_GET_MIN_EIGENVALS
381 );
382
383 // проверяем равны ли размеры векторов хэндлеров точек и найденных точек на картинке
384 if (NextPts.size() != (vec_lonely_point_handlers_.size() + vec_colored_point_handlers_.size()))
385 {
386 std::cout << "DEBUG: ERROR - NextPts size doesnt match vec_point_handlers_ size" << std::endl;
387 }
388
389 std::vector<double> point_amplitudes;
390
391 // Закидываем найденные значения обратно в point handler'ы
392 // Сначала проходимся по lonely хэндлерам
393 for (int i = 0; i < vec_lonely_point_handlers_.size(); i++)
394 {
395 vec_lonely_point_handlers_[i]->AddNewPointPosition(NextPts[i]);
396 vec_lonely_point_handlers_[i]->AddNewPointTime(frame_time_);
397 // Вызов БПФ (FFT)
398 vec_lonely_point_handlers_[i]->ExecuteFFT();
399 // Вычисляем амплитуду
400 vec_lonely_point_handlers_[i]->CalculateAmplitude();
401 double ampl_x = vec_lonely_point_handlers_[i]->GetCurrentAmplitude().x, ampl_y = vec_lonely_point_handlers_[i]->GetCurrentAmplitude().y;
402 point_amplitudes.push_back(sqrt(ampl_x * ampl_x + ampl_y * ampl_y));
403 }
404 // После проходимся по colored хэндлерам
405 //
406 // Небольшое пояснение:
407 // В контейнере NextPts содержатся одновременно lonely и colored точки (причём именно в таком порядке). По сути они делят NextPts на две части - левую (lonely) и правую (colored)
408 // Поэтому, добавляя в хэндлер цветных точек новые координаты, надо идти по NextPts, учитывая возможное (если таковые были добавлены) наличие lonely точек в левой части
409 // Для этого индекс у NextPts = индекс вектора с хэндлерами colored точек + размер вектора с хэндлерами lonely точек (i + vec_lonely_point_handlers_.size())
410 for (int i = 0; i < vec_colored_point_handlers_.size(); i++)
411 {
412 vec_colored_point_handlers_[i]->AddNewPointPosition(NextPts[i + vec_lonely_point_handlers_.size()]);
413 vec_colored_point_handlers_[i]->AddNewPointTime(frame_time_);
414 // Вызов БПФ (FFT)
415 vec_colored_point_handlers_[i]->ExecuteFFT();
416 // Вычисляем амплитуду
417 vec_colored_point_handlers_[i]->CalculateAmplitude();
418 double ampl_x = vec_colored_point_handlers_[i]->GetCurrentAmplitude().x, ampl_y = vec_colored_point_handlers_[i]->GetCurrentAmplitude().y;
419 point_amplitudes.push_back(sqrt(ampl_x * ampl_x + ampl_y * ampl_y));
420 }
421
423 {
424 int max_idx = HelperFunctions::FindGlobalMaxIdx(point_amplitudes);
425 int min_idx = HelperFunctions::FindGlobalMinIdx(point_amplitudes);
426
427 VibratingPoint::extremum_amplitude_.first = point_amplitudes[max_idx];
428 VibratingPoint::extremum_amplitude_.second = *(std::min_element(point_amplitudes.begin(), point_amplitudes.end()));
429 }
430}
431
432std::vector<Point2f> VibrationDetector::FindGoodFeatures(Mat frame, Rect roi)
433{
434 std::vector<Point2f> good_features;
435 // Если изображение не черно-белое
436 if (frame.channels() > 2)
437 cvtColor(frame, frame, COLOR_BGR2GRAY);
438
439 // Устанавливаем ROI на нашем изображении
440 Mat frame_with_roi = frame(roi);
441 goodFeaturesToTrack(frame_with_roi, good_features, 1000, 0.1, 20, noArray(), 3);
442
443 // Перевод в координаты изначального изображения
444 for (int i = 0; i < good_features.size(); i++)
445 {
446 good_features[i].x = good_features[i].x + roi.tl().x;
447 good_features[i].y = good_features[i].y + roi.tl().y;
448 }
449
450 ContourHandler contour_handler(frame, &roi);
451 std::vector<Point2f> features_to_be_append = contour_handler.GetContinousContours();
452
453 auto itt = features_to_be_append.begin();
454 int count = 0;
455 while (itt != features_to_be_append.end())
456 {
457 good_features.push_back(*itt);
458 itt++;
459 count++;
460 }
461
462 return good_features;
463}
464
466{
467 // Рассматриваем вариант, при котором выбран ROI для цветных (colored) точек
468 if (roi_selected_)
469 {
470 // Перемещение изображение на переднем плане на X единиц (px)
471 int x_translation = frame.cols - grad_scale_.cols;
472 // Перемещение изображение на переднем плане на Y единиц (px)
473 int y_translation = frame.rows - grad_scale_.rows;
474 // Вектор этого перемещения
475 Point2i translation_vector = Point2i(x_translation, y_translation);
476 // Вставляем градиент на кадр
477 frame = frame_handler->PutFrameOverFrame(grad_scale_, frame, translation_vector);
478 }
479 // Масштабируем кадр для вывода на экран и добавляем на него подсказки для пользователя
480 frame.copyTo(frame_to_be_shown_);
482 // Выводим кадр на экран
484}
485
486// DEBUG
488{
489
490 for (int i = 0; i < vec_lonely_point_handlers_.size(); i++)
491 {
492 // DEBUG
493 Rect debug_lk_win_size = Rect(
494 Point2i(vec_lonely_point_handlers_[i]->GetLastFoundCoordinates().x - lk_win_size_, vec_lonely_point_handlers_[i]->GetLastFoundCoordinates().y - lk_win_size_),
495 Point2i(vec_lonely_point_handlers_[i]->GetLastFoundCoordinates().x + lk_win_size_, vec_lonely_point_handlers_[i]->GetLastFoundCoordinates().y + lk_win_size_)
496 );
497 rectangle(frame, debug_lk_win_size, Scalar(0, 0, 255), 1);
498 }
499}
500
502{
507
508 // reading the first frame of sequence so we can convert it to gray color space
511
514
515 // Генерируем шкалу
517
518 // conditions of exit
519 running_ = true;
520 int current_num_of_frame = 0;
521 int amount_of_frames = frame_handler->GetAmountOfFrames();
522
523 // устанавливаем callback handler на основное окно
524 setMouseCallback(frame_handler->GetMainWindowName(), OnMouse, (void*)this);
525
526 while ((current_num_of_frame < amount_of_frames - 1) && running_ == true)
527 {
528 current_num_of_frame = frame_handler->GetCurrentPosOfFrame();
529
530 // reading next frame and converting it to gray color space
532
534 if (!warping_figure_.empty())
535 {
537 }
538
540
541 // Трекинг и вычисление частоты вибрации
543
544 TrackAndCalc();
545
546 // Рисование точек, треков и данных (вибрации, амплитуды и т.п.)
547 for (int i = 0; i < vec_lonely_point_handlers_.size(); i++)
548 {
549 vec_lonely_point_handlers_[i]->VibratingPoint::IsInteracted(last_mouse_position_);
551 }
552 for (int i = 0; i < vec_colored_point_handlers_.size(); i++)
553 {
554 // Обновляем максимальную амплитуду
555 vec_colored_point_handlers_[i]->VibratingPoint::IsInteracted(last_mouse_position_);
558 }
559
560 // обслуживаем и очищаем очереди на создание и удаление точек
562
564
565 // Записываем изначальный кадр
567
568 // Обновляем предыдущий кадр
570
571 // 20 - задержка в мс
572 int code = waitKey(20);
573 switch (code)
574 {
575 // Пауза
576 // Клавиши - пробел (ASCII code)
577 case 32:
578 {
579 current_mode_ = PAUSE;
580
582
583 waitKey(0);
584 current_mode_ = DEFAULT;
585 break;
586 }
587 case 'c':
588 {
589 Mat unchanged_frame = current_tracking_frame_;
591
592 warping_figure_.clear();
594
596 {
597 for (int i = 0; i < warping_figure_.size(); i++)
598 {
599 circle(unchanged_frame, warping_figure_[i], 10, Scalar(255, 207, 64), 2);
600 }
601
602 if (warping_figure_.size() == 4)
604
605 frame_handler->ShowFrame(unchanged_frame, fullscreen_);
606 waitKey(20);
607 }
608 break;
609 }
610 // Изменение чувствительности (VibratingPoint::sensivity_ -> влияет на VibratingPoint::confidence_level_)
611 // Клавиши - "A" или "a" (ASCII code)
612 // A - for adjust
613 case 65:
614 case 97:
615 {
616 current_mode_ = PAUSE;
617
619
620 namedWindow("Sensivity Window", WINDOW_FULLSCREEN);
621 createTrackbar("Sensivity", "Sensivity Window", &sensivity_in_percents_, 100, NULL);
622
623 waitKey(0);
624
625 destroyWindow("Sensivity Window");
626
627 for (int i = 0; i < vec_lonely_point_handlers_.size(); i++)
628 {
629 vec_lonely_point_handlers_[i]->SetSensivity(2.0 / static_cast<double>(10 * sensivity_in_percents_));\
630 }
631 for (int i = 0; i < vec_colored_point_handlers_.size(); i++)
632 {
633 vec_colored_point_handlers_[i]->SetSensivity(2.0 / static_cast<double>(10 * sensivity_in_percents_));
634 }
635
636 current_mode_ = DEFAULT;
637 break;
638 }
639 // Фуллскрин.
640 // Клавиши - "F" или "f" (ASCII code)
641 case 102:
642 case 70:
643 {
644 // Проверка на флаг полноэкранного режима. Если он изначально был false, меняем на true, и наоборот в противном случае
645 if (!fullscreen_)
646 {
647 fullscreen_ = true;
648 }
649 else
650 {
651 fullscreen_ = false;
652 }
653 break;
654 }
655 // Изменение режима подсветки точек при активном регионе интереса (ROI)
656 // Клавиши - "M" или "m" (ASCII code)
657 case 77:
658 case 109:
659 {
660 // Перебираем режимы по порядку
661 if (colored_point_mode_ == 2)
663 else
665
667 break;
668 }
669 // Выделение региона интереса (ROI)
670 // Клавиши - "R" или "r" (ASCII code)
671 case 82:
672 case 114:
673 {
674 // Обновляем текущий режим
675 current_mode_ = SELECTINGROI;
676 // Регион интереса
677 Rect roi;
678 // Сбрасываеи флаг выделенного региона интереса
679 roi_selected_ = false;
680 // Флаг выхода из режима
681 bool wanna_quit = false;
682
683 while (!roi_selected_ && !wanna_quit)
684 {
685 // создаю копию current_tracking_frame_
686 Mat frame = current_tracking_frame_.clone();
687
688 // Пока происходит выделение региона интереса (в нашем случае пока не была отпущена ЛКМ), отрисовываем прямоугольник
689 if (roi_selecting_)
690 {
692 rectangle(frame, roi, Scalar(0, 255, 0), 1 * (1 / res_mp_));
693 }
694
695 DrawAndOutput(frame);
696
697 switch (waitKey(20))
698 {
699 // R for reset
700 case 'r':
701 {
702 wanna_quit = true;
703 // Удаляем старые "цветные" точки
705 break;
706 }
707 // Esc
708 case 27:
709 {
710 wanna_quit = true;
711 break;
712 }
713 }
714 }
715 // ROI может быть пустым после выхода из цикла выше кейсом в свитче
716 if (!roi.empty())
718
719 current_mode_ = DEFAULT;
720 break;
721 }
722 case 'q':
723 {
724 running_ = false;
725 std::cout << frame_handler->GetInputCapStatus() << std::endl;
726 break;
727 }
728 }
729 }
730}
Дочерний (от VibratingPoint) класс. Предназначен для помещения множества цветных точек на кадр и отсл...
Класс для создания объектов-обработчиков контуров.
std::vector< Point2f > GetContinousContours()
Возвращает найденные контура в виде { contour_1, contour_2, ... , contour_n }.
Класс для чтения и сохранения кадров видео, а также различной их обработки
Definition: frame_handler.h:29
int GetAmountOfFrames()
Возвращает общее количество кадров
String GetMainWindowName()
Возвращает название главного окна, в которое выводятся кадры
Mat AddTips(Mat frame, int mode)
Добавляет (отрисовывает) подсказки для пользователя на кадр
bool GetInputCapStatus()
Возвращает текущий статус input_cap.
void ShowFrame(Mat frame, bool fullscreen)
Выводит в главное окно принимаемое изображение
Mat GetCurrentFrame()
Возвращает последний прочитанный на данный момент кадр
void ReadNextFrame()
Считывает следующий кадр видео
void WriteFrame(Mat frame)
Записывает кадр с помощью output_cap.
Mat MakeGrayFrame(Mat frame_to_be_grayed)
Возвращает серый кадр с блюром
double GetCurrentTimeOfFrame()
Возвращает текущее время кадра (таймкод в мс)
int GetInputFps()
Возвращает FPS считываемого видео
int GetCurrentPosOfFrame()
Возвращает текущее положение кадра относительно первого
Mat PutFrameOverFrame(Mat foreground_frame, Mat background_frame, Point2i translation_vector)
Накладывает изображение (переднний план) на другое изображение (задний план)
Mat GenerateGradScale(int left_limit, int right_limit, int colored_point_mode)
Генерирует шкалу с градиентом и подписями. Ширина шкалы - ширина исходного видео. Высота регулируется...
float GetTextResizeFactor()
Возвращает коэффициент масштабирования
Дочерний (от VibratingPoint) класс. Предназначен для помещения точки на кадр и отслеживания её вибрац...
bool IsInteracted(Point2i coordinates)
Проверяет точку на наличие взаимодействия с ней (если курсор попал в область взаимодействия точки Vib...
static std::pair< double, double > extremum_amplitude_
Максимум и минимум амплитуды среди всех VibratingPoint объектов-наследников
Класс для создания объектов-детекторов вибрации
Mat next_img_gray_
Следующий (или текущий после "предыдущего" - смотря как удобнее для понимания) кадр видео в грейскейл...
void CreateNewPoint(Point2f mouse_coordinates)
Создаем "обычную" точку
void DefaultModeHandler(int event, int x, int y)
Обычный режим
std::vector< Point2i > delete_queue_
Очередь на удаление точек
int level_amount_
Количество слоев пирамиды изображений в алгоритме Л-К
void RoiSelectionModeHandler(int event, int x, int y)
Режим выделения региона интереса
static void OnMouse(int event, int x, int y, int flags, void *userdata)
callback functions for detecting the click
bool warping_figure_selecting_
Флаг, показывающий, происходит ли в данный момент выделение фигуры (эта возможность отключена временн...
Mat prev_img_gray_
Предыдущий кадр видео в грейскейл и с небольшим блюром (FrameHandler::MakeGrayFrame())
Mat current_tracking_frame_
Текущий Mat-instance только что найденного кадра из видео
Mat grad_scale_
Изображение цветной шкалы внизу экрана
int sensivity_in_percents_
Чувствительность при трекинге вибрации
std::vector< Point2f > c_point_queue_
Очередь на создание "цветных" точек
bool fullscreen_
Флаг для полноэкранного режима
double frame_time_
Текущее время кадра в мс (таймкод)
std::vector< LonelyPointHandler * > vec_lonely_point_handlers_
Вектор обработчиков "одиноких" точек
VibrationDetector(std::string input_file_name, std::string output_file_name, std::string window_name)
Конструктор класса
std::vector< Point2i > l_click_queue_
Очередь на создание "обычных" точек
FrameHandler * frame_handler
Фреймпроцессор
std::vector< Point2f > FindGoodFeatures(Mat frame, Rect roi)
Находит подходящие для трекинга точки на изображении
float res_mp_
Коэффициент автоскейла размеров окна в зависимости от разрешения исходного видео
std::string input_file_name_
Имя (путь) входного видео
Point last_mouse_position_
Последняя позиция курсора в главном окне
void DeletePoints(Point2i mouse_coordinates)
Удаляем объект "обычную" точку
void CreateNewColoredPoint(Point2f mouse_coordinates)
Обработчик "цветных" точек
int fps_
ФПС входного видео (две ширины полосы частот вибрации, которые можно отследить)
void DetectEvent(int event, int x, int y, int flags)
callback functions for detecting the click
std::string output_file_name_
Имя (путь) видео, в котором будет результат детектинга
void TrackAndCalc()
Трекает точки алгоритмом Лукаса-Канаде и вызывает БПФ
std::vector< Point > warping_figure_
Координаты фигуры для исправления перспективы
void LeftClickHandler(Point2f mouse_coordinates)
Обработчик левых кликов
bool roi_selecting_
Флаг, показывающий происходит ли в данный момент выделение ROI.
void DeleteColoredPoints()
Удаляем объекты "цветная" точка
bool running_
Флаг запущенного основного алгоритма
void FindAndDeleteUncofidentPoints()
Удаляет "цветные" и "обычные" точки, если уровень доверия к нми слишком низкий
int lk_win_size_
Размер окна для алгоритма Лукаса-Канаде
Mat frame_to_be_shown_
Mat-instance, который будет показан в окне
int current_mode_
Основной режим работы (enum main_mode)
void DrawAndOutput(Mat &frame)
Масштабирует, рисует и выводит на экран обработанный кадр с точками
void DrawDebugLkWinRectangle(Mat &frame)
Рисует точки и выводит данные
std::vector< ColoredPointHandler * > vec_colored_point_handlers_
Вектор обработчиков "цветных" точек
std::string output_csv_file_name_
Имя (путь) файла для хранения метаданных
Mat MakeWarpedFrame(Mat frame, std::vector< Point2i > warping_figure)
Удаляет перспективные искажения
void ExecuteVibrationDetection()
Выполняет детекцию вибрации
Point2i tl_click_coords_
Координаты первой точки прямоугольник (top left, bottom left, top right, bottom right - смотря "в как...
void ServeTheQueues()
Обслуживает очереди на удаление и создание. Необходимо для того, чтобы не нарушить нумерацию точек во...
int point_id_
Псевдо-id (порядковывй номер точки)
int colored_point_mode_
Текущий режим подсветки точек при выбранном регионе интереса (по амплитуде/по частоте)
bool roi_selected_
Флаг, показывающий был ли выделен ROI или нет
std::string GenerateCsvFilename(std::string additional_text="")
Генерирует имя CSV файла для сохранения метаданных
Definition: helper.cpp:3
int FindGlobalMinIdx(std::vector< T > src)
Возвращает индекс самого маленького элемента вектора src.
Definition: helper.h:149
int FindGlobalMaxIdx(std::vector< T > src)
Возвращает индекс самого большого элемента вектора src.
Definition: helper.h:127