OTVision 0.6.5__tar.gz → 0.6.7__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (320) hide show
  1. {otvision-0.6.5 → otvision-0.6.7}/.github/workflows/release-testpypi.yml +24 -1
  2. {otvision-0.6.5 → otvision-0.6.7}/.pre-commit-config.yaml +1 -2
  3. {otvision-0.6.5 → otvision-0.6.7}/OTVision/application/detect/detected_frame_factory.py +1 -0
  4. {otvision-0.6.5 → otvision-0.6.7}/OTVision/detect/otdet_file_writer.py +1 -1
  5. {otvision-0.6.5 → otvision-0.6.7}/OTVision/detect/rtsp_input_source.py +52 -28
  6. {otvision-0.6.5 → otvision-0.6.7}/OTVision/detect/timestamper.py +1 -0
  7. {otvision-0.6.5 → otvision-0.6.7}/OTVision/detect/video_input_source.py +7 -4
  8. {otvision-0.6.5 → otvision-0.6.7}/OTVision/domain/frame.py +6 -0
  9. {otvision-0.6.5 → otvision-0.6.7}/OTVision/track/parser/chunk_parser_plugins.py +1 -0
  10. {otvision-0.6.5 → otvision-0.6.7}/OTVision/track/tracker/tracker_plugin_iou.py +1 -0
  11. {otvision-0.6.5 → otvision-0.6.7}/OTVision/version.py +1 -1
  12. {otvision-0.6.5 → otvision-0.6.7}/PKG-INFO +1 -2
  13. {otvision-0.6.5 → otvision-0.6.7}/requirements.txt +0 -1
  14. {otvision-0.6.5 → otvision-0.6.7}/tests/application/detect/test_detected_frame_factory.py +2 -0
  15. {otvision-0.6.5 → otvision-0.6.7}/tests/application/detect/test_timestamper.py +2 -0
  16. {otvision-0.6.5 → otvision-0.6.7}/tests/detect/test_detected_frame_buffer.py +3 -0
  17. otvision-0.6.5/tests/detect/test_odet.py → otvision-0.6.7/tests/detect/test_otdet.py +2 -0
  18. otvision-0.6.7/tests/detect/test_rtsp_input_source.py +282 -0
  19. {otvision-0.6.5 → otvision-0.6.7}/tests/detect/test_video_input_source.py +5 -2
  20. {otvision-0.6.5 → otvision-0.6.7}/tests/detect/yolo_test.py +3 -1
  21. {otvision-0.6.5 → otvision-0.6.7}/tests/track/helper/data_builder.py +3 -0
  22. {otvision-0.6.5 → otvision-0.6.7}/tests/track/test_frame_chunk.py +1 -0
  23. {otvision-0.6.5 → otvision-0.6.7}/tests/track/test_tracking_data_structures.py +2 -0
  24. otvision-0.6.5/tests/detect/test_rtsp_input_source.py +0 -160
  25. {otvision-0.6.5 → otvision-0.6.7}/.editorconfig +0 -0
  26. {otvision-0.6.5 → otvision-0.6.7}/.flake8 +0 -0
  27. {otvision-0.6.5 → otvision-0.6.7}/.github/dependabot.yml +0 -0
  28. {otvision-0.6.5 → otvision-0.6.7}/.github/workflows/build-nightly.yml +0 -0
  29. {otvision-0.6.5 → otvision-0.6.7}/.github/workflows/build-release.yml +0 -0
  30. {otvision-0.6.5 → otvision-0.6.7}/.github/workflows/linter.yml +0 -0
  31. {otvision-0.6.5 → otvision-0.6.7}/.github/workflows/release-pypi.yml +0 -0
  32. {otvision-0.6.5 → otvision-0.6.7}/.github/workflows/test.yml +0 -0
  33. {otvision-0.6.5 → otvision-0.6.7}/.gitignore +0 -0
  34. {otvision-0.6.5 → otvision-0.6.7}/.vscode/launch.json +0 -0
  35. {otvision-0.6.5 → otvision-0.6.7}/.vscode/scripts/build_debug_env.cmd +0 -0
  36. {otvision-0.6.5 → otvision-0.6.7}/.vscode/scripts/build_debug_env.sh +0 -0
  37. {otvision-0.6.5 → otvision-0.6.7}/.vscode/scripts/teardown_debug_env.cmd +0 -0
  38. {otvision-0.6.5 → otvision-0.6.7}/.vscode/scripts/teardown_debug_env.sh +0 -0
  39. {otvision-0.6.5 → otvision-0.6.7}/.vscode/settings.json +0 -0
  40. {otvision-0.6.5 → otvision-0.6.7}/.vscode/tasks.json +0 -0
  41. {otvision-0.6.5 → otvision-0.6.7}/.yamllint.yaml +0 -0
  42. {otvision-0.6.5 → otvision-0.6.7}/LICENSE +0 -0
  43. {otvision-0.6.5 → otvision-0.6.7}/OTVision/__init__.py +0 -0
  44. {otvision-0.6.5 → otvision-0.6.7}/OTVision/abstraction/__init__.py +0 -0
  45. {otvision-0.6.5 → otvision-0.6.7}/OTVision/abstraction/defaults.py +0 -0
  46. {otvision-0.6.5 → otvision-0.6.7}/OTVision/abstraction/observer.py +0 -0
  47. {otvision-0.6.5 → otvision-0.6.7}/OTVision/abstraction/pipes_and_filter.py +0 -0
  48. {otvision-0.6.5 → otvision-0.6.7}/OTVision/application/__init__.py +0 -0
  49. {otvision-0.6.5 → otvision-0.6.7}/OTVision/application/buffer.py +0 -0
  50. {otvision-0.6.5 → otvision-0.6.7}/OTVision/application/config.py +0 -0
  51. {otvision-0.6.5 → otvision-0.6.7}/OTVision/application/config_parser.py +0 -0
  52. {otvision-0.6.5 → otvision-0.6.7}/OTVision/application/configure_logger.py +0 -0
  53. {otvision-0.6.5 → otvision-0.6.7}/OTVision/application/detect/__init__.py +0 -0
  54. {otvision-0.6.5 → otvision-0.6.7}/OTVision/application/detect/current_object_detector.py +0 -0
  55. {otvision-0.6.5 → otvision-0.6.7}/OTVision/application/detect/current_object_detector_metadata.py +0 -0
  56. {otvision-0.6.5 → otvision-0.6.7}/OTVision/application/detect/detected_frame_producer.py +0 -0
  57. {otvision-0.6.5 → otvision-0.6.7}/OTVision/application/detect/detection_file_save_path_provider.py +0 -0
  58. {otvision-0.6.5 → otvision-0.6.7}/OTVision/application/detect/factory.py +0 -0
  59. {otvision-0.6.5 → otvision-0.6.7}/OTVision/application/detect/get_detect_cli_args.py +0 -0
  60. {otvision-0.6.5 → otvision-0.6.7}/OTVision/application/detect/timestamper.py +0 -0
  61. {otvision-0.6.5 → otvision-0.6.7}/OTVision/application/detect/update_detect_config_with_cli_args.py +0 -0
  62. {otvision-0.6.5 → otvision-0.6.7}/OTVision/application/frame_count_provider.py +0 -0
  63. {otvision-0.6.5 → otvision-0.6.7}/OTVision/application/get_config.py +0 -0
  64. {otvision-0.6.5 → otvision-0.6.7}/OTVision/application/get_current_config.py +0 -0
  65. {otvision-0.6.5 → otvision-0.6.7}/OTVision/application/track/__init__.py +0 -0
  66. {otvision-0.6.5 → otvision-0.6.7}/OTVision/application/track/get_track_cli_args.py +0 -0
  67. {otvision-0.6.5 → otvision-0.6.7}/OTVision/application/track/update_current_track_config.py +0 -0
  68. {otvision-0.6.5 → otvision-0.6.7}/OTVision/application/track/update_track_config_with_cli_args.py +0 -0
  69. {otvision-0.6.5 → otvision-0.6.7}/OTVision/application/update_current_config.py +0 -0
  70. {otvision-0.6.5 → otvision-0.6.7}/OTVision/config.py +0 -0
  71. {otvision-0.6.5 → otvision-0.6.7}/OTVision/convert/__init__.py +0 -0
  72. {otvision-0.6.5 → otvision-0.6.7}/OTVision/convert/convert.py +0 -0
  73. {otvision-0.6.5 → otvision-0.6.7}/OTVision/dataformat.py +0 -0
  74. {otvision-0.6.5 → otvision-0.6.7}/OTVision/detect/__init__.py +0 -0
  75. {otvision-0.6.5 → otvision-0.6.7}/OTVision/detect/builder.py +0 -0
  76. {otvision-0.6.5 → otvision-0.6.7}/OTVision/detect/cli.py +0 -0
  77. {otvision-0.6.5 → otvision-0.6.7}/OTVision/detect/detect.py +0 -0
  78. {otvision-0.6.5 → otvision-0.6.7}/OTVision/detect/detected_frame_buffer.py +0 -0
  79. {otvision-0.6.5 → otvision-0.6.7}/OTVision/detect/file_based_detect_builder.py +0 -0
  80. {otvision-0.6.5 → otvision-0.6.7}/OTVision/detect/otdet.py +0 -0
  81. {otvision-0.6.5 → otvision-0.6.7}/OTVision/detect/plugin_av/__init__.py +0 -0
  82. {otvision-0.6.5 → otvision-0.6.7}/OTVision/detect/plugin_av/rotate_frame.py +0 -0
  83. {otvision-0.6.5 → otvision-0.6.7}/OTVision/detect/pyav_frame_count_provider.py +0 -0
  84. {otvision-0.6.5 → otvision-0.6.7}/OTVision/detect/rtsp_based_detect_builder.py +0 -0
  85. {otvision-0.6.5 → otvision-0.6.7}/OTVision/detect/yolo.py +0 -0
  86. {otvision-0.6.5 → otvision-0.6.7}/OTVision/domain/__init__.py +0 -0
  87. {otvision-0.6.5 → otvision-0.6.7}/OTVision/domain/cli.py +0 -0
  88. {otvision-0.6.5 → otvision-0.6.7}/OTVision/domain/current_config.py +0 -0
  89. {otvision-0.6.5 → otvision-0.6.7}/OTVision/domain/detect_producer_consumer.py +0 -0
  90. {otvision-0.6.5 → otvision-0.6.7}/OTVision/domain/detection.py +0 -0
  91. {otvision-0.6.5 → otvision-0.6.7}/OTVision/domain/input_source_detect.py +0 -0
  92. {otvision-0.6.5 → otvision-0.6.7}/OTVision/domain/object_detection.py +0 -0
  93. {otvision-0.6.5 → otvision-0.6.7}/OTVision/domain/serialization.py +0 -0
  94. {otvision-0.6.5 → otvision-0.6.7}/OTVision/domain/time.py +0 -0
  95. {otvision-0.6.5 → otvision-0.6.7}/OTVision/helpers/__init__.py +0 -0
  96. {otvision-0.6.5 → otvision-0.6.7}/OTVision/helpers/date.py +0 -0
  97. {otvision-0.6.5 → otvision-0.6.7}/OTVision/helpers/files.py +0 -0
  98. {otvision-0.6.5 → otvision-0.6.7}/OTVision/helpers/formats.py +0 -0
  99. {otvision-0.6.5 → otvision-0.6.7}/OTVision/helpers/input_types.py +0 -0
  100. {otvision-0.6.5 → otvision-0.6.7}/OTVision/helpers/log.py +0 -0
  101. {otvision-0.6.5 → otvision-0.6.7}/OTVision/helpers/machine.py +0 -0
  102. {otvision-0.6.5 → otvision-0.6.7}/OTVision/helpers/video.py +0 -0
  103. {otvision-0.6.5 → otvision-0.6.7}/OTVision/plugin/__init__.py +0 -0
  104. {otvision-0.6.5 → otvision-0.6.7}/OTVision/plugin/yaml_serialization.py +0 -0
  105. {otvision-0.6.5 → otvision-0.6.7}/OTVision/track/__init__.py +0 -0
  106. {otvision-0.6.5 → otvision-0.6.7}/OTVision/track/builder.py +0 -0
  107. {otvision-0.6.5 → otvision-0.6.7}/OTVision/track/cli.py +0 -0
  108. {otvision-0.6.5 → otvision-0.6.7}/OTVision/track/exporter/__init__.py +0 -0
  109. {otvision-0.6.5 → otvision-0.6.7}/OTVision/track/exporter/filebased_exporter.py +0 -0
  110. {otvision-0.6.5 → otvision-0.6.7}/OTVision/track/id_generator.py +0 -0
  111. {otvision-0.6.5 → otvision-0.6.7}/OTVision/track/model/__init__.py +0 -0
  112. {otvision-0.6.5 → otvision-0.6.7}/OTVision/track/model/filebased/__init__.py +0 -0
  113. {otvision-0.6.5 → otvision-0.6.7}/OTVision/track/model/filebased/frame_chunk.py +0 -0
  114. {otvision-0.6.5 → otvision-0.6.7}/OTVision/track/model/filebased/frame_group.py +0 -0
  115. {otvision-0.6.5 → otvision-0.6.7}/OTVision/track/model/track_exporter.py +0 -0
  116. {otvision-0.6.5 → otvision-0.6.7}/OTVision/track/model/tracking_interfaces.py +0 -0
  117. {otvision-0.6.5 → otvision-0.6.7}/OTVision/track/parser/__init__.py +0 -0
  118. {otvision-0.6.5 → otvision-0.6.7}/OTVision/track/parser/frame_group_parser_plugins.py +0 -0
  119. {otvision-0.6.5 → otvision-0.6.7}/OTVision/track/track.py +0 -0
  120. {otvision-0.6.5 → otvision-0.6.7}/OTVision/track/tracker/__init__.py +0 -0
  121. {otvision-0.6.5 → otvision-0.6.7}/OTVision/track/tracker/filebased_tracking.py +0 -0
  122. {otvision-0.6.5 → otvision-0.6.7}/OTVision/transform/__init__.py +0 -0
  123. {otvision-0.6.5 → otvision-0.6.7}/OTVision/transform/get_homography.py +0 -0
  124. {otvision-0.6.5 → otvision-0.6.7}/OTVision/transform/reference_points_picker.py +0 -0
  125. {otvision-0.6.5 → otvision-0.6.7}/OTVision/transform/transform.py +0 -0
  126. {otvision-0.6.5 → otvision-0.6.7}/OTVision/view/__init__.py +0 -0
  127. {otvision-0.6.5 → otvision-0.6.7}/OTVision/view/helpers/OTC.ico +0 -0
  128. {otvision-0.6.5 → otvision-0.6.7}/OTVision/view/view.py +0 -0
  129. {otvision-0.6.5 → otvision-0.6.7}/OTVision/view/view_convert.py +0 -0
  130. {otvision-0.6.5 → otvision-0.6.7}/OTVision/view/view_detect.py +0 -0
  131. {otvision-0.6.5 → otvision-0.6.7}/OTVision/view/view_helpers.py +0 -0
  132. {otvision-0.6.5 → otvision-0.6.7}/OTVision/view/view_track.py +0 -0
  133. {otvision-0.6.5 → otvision-0.6.7}/OTVision/view/view_transform.py +0 -0
  134. {otvision-0.6.5 → otvision-0.6.7}/OTVision.bat +0 -0
  135. {otvision-0.6.5 → otvision-0.6.7}/README.md +0 -0
  136. {otvision-0.6.5 → otvision-0.6.7}/clean-up-repository.sh +0 -0
  137. {otvision-0.6.5 → otvision-0.6.7}/config.yml +0 -0
  138. {otvision-0.6.5 → otvision-0.6.7}/convert.py +0 -0
  139. {otvision-0.6.5 → otvision-0.6.7}/detect.py +0 -0
  140. {otvision-0.6.5 → otvision-0.6.7}/export_models.py +0 -0
  141. {otvision-0.6.5 → otvision-0.6.7}/install.cmd +0 -0
  142. {otvision-0.6.5 → otvision-0.6.7}/install.sh +0 -0
  143. {otvision-0.6.5 → otvision-0.6.7}/install_dev.cmd +0 -0
  144. {otvision-0.6.5 → otvision-0.6.7}/install_dev.sh +0 -0
  145. {otvision-0.6.5 → otvision-0.6.7}/pyproject.toml +0 -0
  146. {otvision-0.6.5 → otvision-0.6.7}/reference_points_picker.py +0 -0
  147. {otvision-0.6.5 → otvision-0.6.7}/requirements-dev.txt +0 -0
  148. {otvision-0.6.5 → otvision-0.6.7}/tests/__init__.py +0 -0
  149. {otvision-0.6.5 → otvision-0.6.7}/tests/abstraction/__init__.py +0 -0
  150. {otvision-0.6.5 → otvision-0.6.7}/tests/abstraction/test_defaults.py +0 -0
  151. {otvision-0.6.5 → otvision-0.6.7}/tests/abstraction/test_observer.py +0 -0
  152. {otvision-0.6.5 → otvision-0.6.7}/tests/application/__init__.py +0 -0
  153. {otvision-0.6.5 → otvision-0.6.7}/tests/application/detect/__init__.py +0 -0
  154. {otvision-0.6.5 → otvision-0.6.7}/tests/application/detect/test_current_object_detector.py +0 -0
  155. {otvision-0.6.5 → otvision-0.6.7}/tests/application/detect/test_detected_frame_producer.py +0 -0
  156. {otvision-0.6.5 → otvision-0.6.7}/tests/application/detect/test_detection_file_save_path_provider.py +0 -0
  157. {otvision-0.6.5 → otvision-0.6.7}/tests/application/detect/test_get_detect_cli_args.py +0 -0
  158. {otvision-0.6.5 → otvision-0.6.7}/tests/application/detect/test_update_detect_config_with_cli_args.py +0 -0
  159. {otvision-0.6.5 → otvision-0.6.7}/tests/application/test_buffer.py +0 -0
  160. {otvision-0.6.5 → otvision-0.6.7}/tests/application/test_get_config.py +0 -0
  161. {otvision-0.6.5 → otvision-0.6.7}/tests/application/track/__init__.py +0 -0
  162. {otvision-0.6.5 → otvision-0.6.7}/tests/application/track/test_get_track_cli_args.py +0 -0
  163. {otvision-0.6.5 → otvision-0.6.7}/tests/application/track/test_update_current_track_config.py +0 -0
  164. {otvision-0.6.5 → otvision-0.6.7}/tests/application/track/test_update_track_config_with_cli_args.py +0 -0
  165. {otvision-0.6.5 → otvision-0.6.7}/tests/cli/custom_cli_test_config.yaml +0 -0
  166. {otvision-0.6.5 → otvision-0.6.7}/tests/cli/test_convert_cli.py +0 -0
  167. {otvision-0.6.5 → otvision-0.6.7}/tests/cli/test_detect_cli.py +0 -0
  168. {otvision-0.6.5 → otvision-0.6.7}/tests/cli/test_track_cli.py +0 -0
  169. {otvision-0.6.5 → otvision-0.6.7}/tests/conftest.py +0 -0
  170. {otvision-0.6.5 → otvision-0.6.7}/tests/convert/__init__.py +0 -0
  171. {otvision-0.6.5 → otvision-0.6.7}/tests/convert/test_convert.py +0 -0
  172. {otvision-0.6.5 → otvision-0.6.7}/tests/data/Testvideo_CamView.png +0 -0
  173. {otvision-0.6.5 → otvision-0.6.7}/tests/data/Testvideo_CamView_Cars-Cyclist.png +0 -0
  174. {otvision-0.6.5 → otvision-0.6.7}/tests/data/Testvideo_CamView_Cars-Truck.png +0 -0
  175. {otvision-0.6.5 → otvision-0.6.7}/tests/data/Testvideo_CamView_refpts.png +0 -0
  176. {otvision-0.6.5 → otvision-0.6.7}/tests/data/Testvideo_Cars-Cyclist_FR20_2020-01-01_00-00-00.gpkg +0 -0
  177. {otvision-0.6.5 → otvision-0.6.7}/tests/data/Testvideo_Cars-Cyclist_FR20_2020-01-01_00-00-00.h264 +0 -0
  178. {otvision-0.6.5 → otvision-0.6.7}/tests/data/Testvideo_Cars-Cyclist_FR20_2020-01-01_00-00-00.mp4 +0 -0
  179. {otvision-0.6.5 → otvision-0.6.7}/tests/data/Testvideo_Cars-Cyclist_FR20_2020-01-01_00-00-00.otdet +0 -0
  180. {otvision-0.6.5 → otvision-0.6.7}/tests/data/Testvideo_Cars-Cyclist_FR20_2020-01-01_00-00-00.otrfpts +0 -0
  181. {otvision-0.6.5 → otvision-0.6.7}/tests/data/Testvideo_Cars-Cyclist_FR20_2020-01-01_00-00-00.ottrk +0 -0
  182. {otvision-0.6.5 → otvision-0.6.7}/tests/data/Testvideo_Cars-Truck_FR20_2020-01-01_00-00-00.gpkg +0 -0
  183. {otvision-0.6.5 → otvision-0.6.7}/tests/data/Testvideo_Cars-Truck_FR20_2020-01-01_00-00-00.h264 +0 -0
  184. {otvision-0.6.5 → otvision-0.6.7}/tests/data/Testvideo_Cars-Truck_FR20_2020-01-01_00-00-00.mp4 +0 -0
  185. {otvision-0.6.5 → otvision-0.6.7}/tests/data/Testvideo_Cars-Truck_FR20_2020-01-01_00-00-00.otdet +0 -0
  186. {otvision-0.6.5 → otvision-0.6.7}/tests/data/Testvideo_Cars-Truck_FR20_2020-01-01_00-00-00.otrfpts +0 -0
  187. {otvision-0.6.5 → otvision-0.6.7}/tests/data/Testvideo_Cars-Truck_FR20_2020-01-01_00-00-00.ottrk +0 -0
  188. {otvision-0.6.5 → otvision-0.6.7}/tests/data/Testvideo_FR20.otrfpts +0 -0
  189. {otvision-0.6.5 → otvision-0.6.7}/tests/data/Testvideo_Satellite.jpg +0 -0
  190. {otvision-0.6.5 → otvision-0.6.7}/tests/data/Testvideo_Satellite_far.jpg +0 -0
  191. {otvision-0.6.5 → otvision-0.6.7}/tests/data/convert/default/Testvideo_Cars-Cyclist_FR20_2020-01-01_00-00-00.h264 +0 -0
  192. {otvision-0.6.5 → otvision-0.6.7}/tests/data/convert/default/Testvideo_Cars-Cyclist_FR20_2020-01-01_00-00-00.mp4 +0 -0
  193. {otvision-0.6.5 → otvision-0.6.7}/tests/data/convert/default/Testvideo_Cars-Truck_FR20_2020-01-01_00-00-00.h264 +0 -0
  194. {otvision-0.6.5 → otvision-0.6.7}/tests/data/convert/default/Testvideo_Cars-Truck_FR20_2020-01-01_00-00-00.mp4 +0 -0
  195. {otvision-0.6.5 → otvision-0.6.7}/tests/data/convert/fail_fps_from_filename/Testvideo_Cars-Cyclist_F20_2020-01-01_00-00-00.h264 +0 -0
  196. {otvision-0.6.5 → otvision-0.6.7}/tests/data/convert/fail_fps_from_filename/Testvideo_Cars-Truck_2020-01-01_00-00-00.h264 +0 -0
  197. {otvision-0.6.5 → otvision-0.6.7}/tests/data/convert/fps_from_filename/Testvideo_Cars-Cyclist_FR20_2020-01-01_00-00-00.h264 +0 -0
  198. {otvision-0.6.5 → otvision-0.6.7}/tests/data/convert/fps_from_filename/Testvideo_Cars-Cyclist_FR20_2020-01-01_00-00-00.mp4 +0 -0
  199. {otvision-0.6.5 → otvision-0.6.7}/tests/data/convert/fps_from_filename/Testvideo_Cars-Truck_FR20_2020-01-01_00-00-00.h264 +0 -0
  200. {otvision-0.6.5 → otvision-0.6.7}/tests/data/convert/fps_from_filename/Testvideo_Cars-Truck_FR20_2020-01-01_00-00-00.mp4 +0 -0
  201. {otvision-0.6.5 → otvision-0.6.7}/tests/data/convert/input_fps_20/Testvideo_Cars-Cyclist_FR20_2020-01-01_00-00-00.h264 +0 -0
  202. {otvision-0.6.5 → otvision-0.6.7}/tests/data/convert/input_fps_20/Testvideo_Cars-Cyclist_FR20_2020-01-01_00-00-00.mp4 +0 -0
  203. {otvision-0.6.5 → otvision-0.6.7}/tests/data/convert/input_fps_20/Testvideo_Cars-Truck_FR20_2020-01-01_00-00-00.h264 +0 -0
  204. {otvision-0.6.5 → otvision-0.6.7}/tests/data/convert/input_fps_20/Testvideo_Cars-Truck_FR20_2020-01-01_00-00-00.mp4 +0 -0
  205. {otvision-0.6.5 → otvision-0.6.7}/tests/data/convert/input_fps_40/Testvideo_Cars-Cyclist_FR20_2020-01-01_00-00-00.h264 +0 -0
  206. {otvision-0.6.5 → otvision-0.6.7}/tests/data/convert/input_fps_40/Testvideo_Cars-Cyclist_FR20_2020-01-01_00-00-00.mp4 +0 -0
  207. {otvision-0.6.5 → otvision-0.6.7}/tests/data/convert/input_fps_40/Testvideo_Cars-Truck_FR20_2020-01-01_00-00-00.h264 +0 -0
  208. {otvision-0.6.5 → otvision-0.6.7}/tests/data/convert/input_fps_40/Testvideo_Cars-Truck_FR20_2020-01-01_00-00-00.mp4 +0 -0
  209. {otvision-0.6.5 → otvision-0.6.7}/tests/data/convert/output_filetype_avi/Testvideo_Cars-Cyclist_FR20_2020-01-01_00-00-00.avi +0 -0
  210. {otvision-0.6.5 → otvision-0.6.7}/tests/data/convert/output_filetype_avi/Testvideo_Cars-Cyclist_FR20_2020-01-01_00-00-00.h264 +0 -0
  211. {otvision-0.6.5 → otvision-0.6.7}/tests/data/convert/output_filetype_avi/Testvideo_Cars-Truck_FR20_2020-01-01_00-00-00.avi +0 -0
  212. {otvision-0.6.5 → otvision-0.6.7}/tests/data/convert/output_filetype_avi/Testvideo_Cars-Truck_FR20_2020-01-01_00-00-00.h264 +0 -0
  213. {otvision-0.6.5 → otvision-0.6.7}/tests/data/convert/output_filetype_mkv/Testvideo_Cars-Cyclist_FR20_2020-01-01_00-00-00.h264 +0 -0
  214. {otvision-0.6.5 → otvision-0.6.7}/tests/data/convert/output_filetype_mkv/Testvideo_Cars-Cyclist_FR20_2020-01-01_00-00-00.mkv +0 -0
  215. {otvision-0.6.5 → otvision-0.6.7}/tests/data/convert/output_filetype_mkv/Testvideo_Cars-Truck_FR20_2020-01-01_00-00-00.h264 +0 -0
  216. {otvision-0.6.5 → otvision-0.6.7}/tests/data/convert/output_filetype_mkv/Testvideo_Cars-Truck_FR20_2020-01-01_00-00-00.mkv +0 -0
  217. {otvision-0.6.5 → otvision-0.6.7}/tests/data/convert/output_filetype_mov/Testvideo_Cars-Cyclist_FR20_2020-01-01_00-00-00.h264 +0 -0
  218. {otvision-0.6.5 → otvision-0.6.7}/tests/data/convert/output_filetype_mov/Testvideo_Cars-Cyclist_FR20_2020-01-01_00-00-00.mov +0 -0
  219. {otvision-0.6.5 → otvision-0.6.7}/tests/data/convert/output_filetype_mov/Testvideo_Cars-Truck_FR20_2020-01-01_00-00-00.h264 +0 -0
  220. {otvision-0.6.5 → otvision-0.6.7}/tests/data/convert/output_filetype_mov/Testvideo_Cars-Truck_FR20_2020-01-01_00-00-00.mov +0 -0
  221. {otvision-0.6.5 → otvision-0.6.7}/tests/data/convert/output_filetype_mp4/Testvideo_Cars-Cyclist_FR20_2020-01-01_00-00-00.h264 +0 -0
  222. {otvision-0.6.5 → otvision-0.6.7}/tests/data/convert/output_filetype_mp4/Testvideo_Cars-Cyclist_FR20_2020-01-01_00-00-00.mp4 +0 -0
  223. {otvision-0.6.5 → otvision-0.6.7}/tests/data/convert/output_filetype_mp4/Testvideo_Cars-Truck_FR20_2020-01-01_00-00-00.h264 +0 -0
  224. {otvision-0.6.5 → otvision-0.6.7}/tests/data/convert/output_filetype_mp4/Testvideo_Cars-Truck_FR20_2020-01-01_00-00-00.mp4 +0 -0
  225. {otvision-0.6.5 → otvision-0.6.7}/tests/data/convert/rotation/Testvideo_Cars-Cyclist_FR20_2020-01-01_00-00-00_rotate.h264 +0 -0
  226. {otvision-0.6.5 → otvision-0.6.7}/tests/data/convert/rotation/Testvideo_Cars-Cyclist_FR20_2020-01-01_00-00-00_rotate.mov +0 -0
  227. {otvision-0.6.5 → otvision-0.6.7}/tests/data/convert/rotation/Testvideo_Cars-Cyclist_FR20_2020-01-01_00-00-00_rotate.mp4 +0 -0
  228. {otvision-0.6.5 → otvision-0.6.7}/tests/data/convert/rotation/Testvideo_Cars-Truck_FR20_2020-01-01_00-00-00_rotate.h264 +0 -0
  229. {otvision-0.6.5 → otvision-0.6.7}/tests/data/convert/rotation/Testvideo_Cars-Truck_FR20_2020-01-01_00-00-00_rotate.mov +0 -0
  230. {otvision-0.6.5 → otvision-0.6.7}/tests/data/convert/rotation/Testvideo_Cars-Truck_FR20_2020-01-01_00-00-00_rotate.mp4 +0 -0
  231. {otvision-0.6.5 → otvision-0.6.7}/tests/data/detect/Testvideo_Cars-Cyclist_FR20_2020-01-01_00-00-00.mp4 +0 -0
  232. {otvision-0.6.5 → otvision-0.6.7}/tests/data/detect/Testvideo_Cars-Truck_FR20_2020-01-01_00-00-00.mp4 +0 -0
  233. {otvision-0.6.5 → otvision-0.6.7}/tests/data/detect/default/Testvideo_Cars-Cyclist_FR20_2020-01-01_00-00-00.otdet +0 -0
  234. {otvision-0.6.5 → otvision-0.6.7}/tests/data/detect/default/Testvideo_Cars-Truck_FR20_2020-01-01_00-00-00.otdet +0 -0
  235. {otvision-0.6.5 → otvision-0.6.7}/tests/data/detect/rotated-Testvideo_Cars-Cyclist_FR20_2020-01-01_00-00-00.mp4 +0 -0
  236. {otvision-0.6.5 → otvision-0.6.7}/tests/data/log/_otvision_logs/test.log +0 -0
  237. {otvision-0.6.5 → otvision-0.6.7}/tests/data/track/default/Testvideo_Cars-Cyclist_FR20_2020-01-01_00-00-00.otdet +0 -0
  238. {otvision-0.6.5 → otvision-0.6.7}/tests/data/track/default/Testvideo_Cars-Cyclist_FR20_2020-01-01_00-00-00.ottrk +0 -0
  239. {otvision-0.6.5 → otvision-0.6.7}/tests/data/track/default/Testvideo_Cars-Truck_FR20_2020-01-01_00-00-00.otdet +0 -0
  240. {otvision-0.6.5 → otvision-0.6.7}/tests/data/track/default/Testvideo_Cars-Truck_FR20_2020-01-01_00-00-00.ottrk +0 -0
  241. {otvision-0.6.5 → otvision-0.6.7}/tests/data/track/sigma_h_0_2/Testvideo_Cars-Cyclist_FR20_2020-01-01_00-00-00.otdet +0 -0
  242. {otvision-0.6.5 → otvision-0.6.7}/tests/data/track/sigma_h_0_2/Testvideo_Cars-Cyclist_FR20_2020-01-01_00-00-00.ottrk +0 -0
  243. {otvision-0.6.5 → otvision-0.6.7}/tests/data/track/sigma_h_0_2/Testvideo_Cars-Truck_FR20_2020-01-01_00-00-00.otdet +0 -0
  244. {otvision-0.6.5 → otvision-0.6.7}/tests/data/track/sigma_h_0_2/Testvideo_Cars-Truck_FR20_2020-01-01_00-00-00.ottrk +0 -0
  245. {otvision-0.6.5 → otvision-0.6.7}/tests/data/track/sigma_h_0_6/Testvideo_Cars-Cyclist_FR20_2020-01-01_00-00-00.otdet +0 -0
  246. {otvision-0.6.5 → otvision-0.6.7}/tests/data/track/sigma_h_0_6/Testvideo_Cars-Cyclist_FR20_2020-01-01_00-00-00.ottrk +0 -0
  247. {otvision-0.6.5 → otvision-0.6.7}/tests/data/track/sigma_h_0_6/Testvideo_Cars-Truck_FR20_2020-01-01_00-00-00.otdet +0 -0
  248. {otvision-0.6.5 → otvision-0.6.7}/tests/data/track/sigma_h_0_6/Testvideo_Cars-Truck_FR20_2020-01-01_00-00-00.ottrk +0 -0
  249. {otvision-0.6.5 → otvision-0.6.7}/tests/data/track/sigma_iou_0_2/Testvideo_Cars-Cyclist_FR20_2020-01-01_00-00-00.otdet +0 -0
  250. {otvision-0.6.5 → otvision-0.6.7}/tests/data/track/sigma_iou_0_2/Testvideo_Cars-Cyclist_FR20_2020-01-01_00-00-00.ottrk +0 -0
  251. {otvision-0.6.5 → otvision-0.6.7}/tests/data/track/sigma_iou_0_2/Testvideo_Cars-Truck_FR20_2020-01-01_00-00-00.otdet +0 -0
  252. {otvision-0.6.5 → otvision-0.6.7}/tests/data/track/sigma_iou_0_2/Testvideo_Cars-Truck_FR20_2020-01-01_00-00-00.ottrk +0 -0
  253. {otvision-0.6.5 → otvision-0.6.7}/tests/data/track/sigma_iou_0_6/Testvideo_Cars-Cyclist_FR20_2020-01-01_00-00-00.otdet +0 -0
  254. {otvision-0.6.5 → otvision-0.6.7}/tests/data/track/sigma_iou_0_6/Testvideo_Cars-Cyclist_FR20_2020-01-01_00-00-00.ottrk +0 -0
  255. {otvision-0.6.5 → otvision-0.6.7}/tests/data/track/sigma_iou_0_6/Testvideo_Cars-Truck_FR20_2020-01-01_00-00-00.otdet +0 -0
  256. {otvision-0.6.5 → otvision-0.6.7}/tests/data/track/sigma_iou_0_6/Testvideo_Cars-Truck_FR20_2020-01-01_00-00-00.ottrk +0 -0
  257. {otvision-0.6.5 → otvision-0.6.7}/tests/data/track/sigma_l_0_1/Testvideo_Cars-Cyclist_FR20_2020-01-01_00-00-00.otdet +0 -0
  258. {otvision-0.6.5 → otvision-0.6.7}/tests/data/track/sigma_l_0_1/Testvideo_Cars-Cyclist_FR20_2020-01-01_00-00-00.ottrk +0 -0
  259. {otvision-0.6.5 → otvision-0.6.7}/tests/data/track/sigma_l_0_1/Testvideo_Cars-Truck_FR20_2020-01-01_00-00-00.otdet +0 -0
  260. {otvision-0.6.5 → otvision-0.6.7}/tests/data/track/sigma_l_0_1/Testvideo_Cars-Truck_FR20_2020-01-01_00-00-00.ottrk +0 -0
  261. {otvision-0.6.5 → otvision-0.6.7}/tests/data/track/sigma_l_0_5/Testvideo_Cars-Cyclist_FR20_2020-01-01_00-00-00.otdet +0 -0
  262. {otvision-0.6.5 → otvision-0.6.7}/tests/data/track/sigma_l_0_5/Testvideo_Cars-Cyclist_FR20_2020-01-01_00-00-00.ottrk +0 -0
  263. {otvision-0.6.5 → otvision-0.6.7}/tests/data/track/sigma_l_0_5/Testvideo_Cars-Truck_FR20_2020-01-01_00-00-00.otdet +0 -0
  264. {otvision-0.6.5 → otvision-0.6.7}/tests/data/track/sigma_l_0_5/Testvideo_Cars-Truck_FR20_2020-01-01_00-00-00.ottrk +0 -0
  265. {otvision-0.6.5 → otvision-0.6.7}/tests/data/track/t_min_10/Testvideo_Cars-Cyclist_FR20_2020-01-01_00-00-00.otdet +0 -0
  266. {otvision-0.6.5 → otvision-0.6.7}/tests/data/track/t_min_10/Testvideo_Cars-Cyclist_FR20_2020-01-01_00-00-00.ottrk +0 -0
  267. {otvision-0.6.5 → otvision-0.6.7}/tests/data/track/t_min_10/Testvideo_Cars-Truck_FR20_2020-01-01_00-00-00.otdet +0 -0
  268. {otvision-0.6.5 → otvision-0.6.7}/tests/data/track/t_min_10/Testvideo_Cars-Truck_FR20_2020-01-01_00-00-00.ottrk +0 -0
  269. {otvision-0.6.5 → otvision-0.6.7}/tests/data/track/t_min_3/Testvideo_Cars-Cyclist_FR20_2020-01-01_00-00-00.otdet +0 -0
  270. {otvision-0.6.5 → otvision-0.6.7}/tests/data/track/t_min_3/Testvideo_Cars-Cyclist_FR20_2020-01-01_00-00-00.ottrk +0 -0
  271. {otvision-0.6.5 → otvision-0.6.7}/tests/data/track/t_min_3/Testvideo_Cars-Truck_FR20_2020-01-01_00-00-00.otdet +0 -0
  272. {otvision-0.6.5 → otvision-0.6.7}/tests/data/track/t_min_3/Testvideo_Cars-Truck_FR20_2020-01-01_00-00-00.ottrk +0 -0
  273. {otvision-0.6.5 → otvision-0.6.7}/tests/data/track/t_miss_max_25/Testvideo_Cars-Cyclist_FR20_2020-01-01_00-00-00.otdet +0 -0
  274. {otvision-0.6.5 → otvision-0.6.7}/tests/data/track/t_miss_max_25/Testvideo_Cars-Cyclist_FR20_2020-01-01_00-00-00.ottrk +0 -0
  275. {otvision-0.6.5 → otvision-0.6.7}/tests/data/track/t_miss_max_25/Testvideo_Cars-Truck_FR20_2020-01-01_00-00-00.otdet +0 -0
  276. {otvision-0.6.5 → otvision-0.6.7}/tests/data/track/t_miss_max_25/Testvideo_Cars-Truck_FR20_2020-01-01_00-00-00.ottrk +0 -0
  277. {otvision-0.6.5 → otvision-0.6.7}/tests/data/track/t_miss_max_75/Testvideo_Cars-Cyclist_FR20_2020-01-01_00-00-00.otdet +0 -0
  278. {otvision-0.6.5 → otvision-0.6.7}/tests/data/track/t_miss_max_75/Testvideo_Cars-Cyclist_FR20_2020-01-01_00-00-00.ottrk +0 -0
  279. {otvision-0.6.5 → otvision-0.6.7}/tests/data/track/t_miss_max_75/Testvideo_Cars-Truck_FR20_2020-01-01_00-00-00.otdet +0 -0
  280. {otvision-0.6.5 → otvision-0.6.7}/tests/data/track/t_miss_max_75/Testvideo_Cars-Truck_FR20_2020-01-01_00-00-00.ottrk +0 -0
  281. {otvision-0.6.5 → otvision-0.6.7}/tests/data/transform/Testvideo_Cars-Cyclist_FR20_2020-01-01_00-00-00.gpkg +0 -0
  282. {otvision-0.6.5 → otvision-0.6.7}/tests/data/transform/Testvideo_Cars-Cyclist_FR20_2020-01-01_00-00-00.otrfpts +0 -0
  283. {otvision-0.6.5 → otvision-0.6.7}/tests/data/transform/Testvideo_Cars-Cyclist_FR20_2020-01-01_00-00-00.ottrk +0 -0
  284. {otvision-0.6.5 → otvision-0.6.7}/tests/data/transform/Testvideo_Cars-Truck_FR20_2020-01-01_00-00-00.gpkg +0 -0
  285. {otvision-0.6.5 → otvision-0.6.7}/tests/data/transform/Testvideo_Cars-Truck_FR20_2020-01-01_00-00-00.otrfpts +0 -0
  286. {otvision-0.6.5 → otvision-0.6.7}/tests/data/transform/Testvideo_Cars-Truck_FR20_2020-01-01_00-00-00.ottrk +0 -0
  287. {otvision-0.6.5 → otvision-0.6.7}/tests/data/transform/Testvideo_FR20.otrfpts +0 -0
  288. {otvision-0.6.5 → otvision-0.6.7}/tests/data/yolov8m.mlpackage/Data/com.apple.CoreML/model.mlmodel +0 -0
  289. {otvision-0.6.5 → otvision-0.6.7}/tests/data/yolov8m.mlpackage/Data/com.apple.CoreML/weights/weight.bin +0 -0
  290. {otvision-0.6.5 → otvision-0.6.7}/tests/data/yolov8m.mlpackage/Manifest.json +0 -0
  291. {otvision-0.6.5 → otvision-0.6.7}/tests/detect/__init__.py +0 -0
  292. {otvision-0.6.5 → otvision-0.6.7}/tests/detect/detect_test.py +0 -0
  293. {otvision-0.6.5 → otvision-0.6.7}/tests/detect/plugin_av/__init__.py +0 -0
  294. {otvision-0.6.5 → otvision-0.6.7}/tests/detect/plugin_av/test_rotate_frame.py +0 -0
  295. {otvision-0.6.5 → otvision-0.6.7}/tests/detect/test_otdet_file_writer.py +0 -0
  296. {otvision-0.6.5 → otvision-0.6.7}/tests/detect/test_pyav_frame_count_provider.py +0 -0
  297. {otvision-0.6.5 → otvision-0.6.7}/tests/helpers/__init__.py +0 -0
  298. {otvision-0.6.5 → otvision-0.6.7}/tests/helpers/files_test.py +0 -0
  299. {otvision-0.6.5 → otvision-0.6.7}/tests/helpers/formats_test.py +0 -0
  300. {otvision-0.6.5 → otvision-0.6.7}/tests/helpers/test_log.py +0 -0
  301. {otvision-0.6.5 → otvision-0.6.7}/tests/log/__init__.py +0 -0
  302. {otvision-0.6.5 → otvision-0.6.7}/tests/log/log_maker.py +0 -0
  303. {otvision-0.6.5 → otvision-0.6.7}/tests/log/test_log.py +0 -0
  304. {otvision-0.6.5 → otvision-0.6.7}/tests/test_config.py +0 -0
  305. {otvision-0.6.5 → otvision-0.6.7}/tests/track/__init__.py +0 -0
  306. {otvision-0.6.5 → otvision-0.6.7}/tests/track/helper/__init__.py +0 -0
  307. {otvision-0.6.5 → otvision-0.6.7}/tests/track/parser/__init__.py +0 -0
  308. {otvision-0.6.5 → otvision-0.6.7}/tests/track/parser/test_chunk_parser_plugins.py +0 -0
  309. {otvision-0.6.5 → otvision-0.6.7}/tests/track/test_frame_group.py +0 -0
  310. {otvision-0.6.5 → otvision-0.6.7}/tests/track/test_frame_group_parser_plugins.py +0 -0
  311. {otvision-0.6.5 → otvision-0.6.7}/tests/track/test_track.py +0 -0
  312. {otvision-0.6.5 → otvision-0.6.7}/tests/transform/__init__.py +0 -0
  313. {otvision-0.6.5 → otvision-0.6.7}/tests/transform/test_transform.py +0 -0
  314. {otvision-0.6.5 → otvision-0.6.7}/tests/utils/__init__.py +0 -0
  315. {otvision-0.6.5 → otvision-0.6.7}/tests/utils/generator.py +0 -0
  316. {otvision-0.6.5 → otvision-0.6.7}/tests/utils/mocking.py +0 -0
  317. {otvision-0.6.5 → otvision-0.6.7}/track.py +0 -0
  318. {otvision-0.6.5 → otvision-0.6.7}/transform.py +0 -0
  319. {otvision-0.6.5 → otvision-0.6.7}/update_precommit.py +0 -0
  320. {otvision-0.6.5 → otvision-0.6.7}/view.py +0 -0
@@ -26,14 +26,37 @@ jobs:
26
26
  steps:
27
27
  - name: Checkout code
28
28
  uses: actions/checkout@v4
29
+
30
+ - name: Fetch all tags
31
+ run: git fetch --tags --unshallow
32
+
29
33
  - name: Set up Python
30
34
  uses: actions/setup-python@v5
31
35
  with:
32
36
  python-version: "3.12"
37
+
38
+ - name: Get latest tag and create new version
39
+ id: get_version
40
+ run: |
41
+ # Get the latest tag in format v*.*.* (ignoring tags like "nightly")
42
+ LATEST_TAG="$(git tag -l "v*.*.*" | sort -V | tail -n 1 || echo 'v0.0.0')"
43
+ # Extract version without 'v' prefix
44
+ VERSION="${LATEST_TAG#v}"
45
+ # Split version into parts
46
+ IFS='.' read -r MAJOR MINOR PATCH <<< "$VERSION"
47
+ # Increment patch version
48
+ PATCH="$((PATCH + 1))"
49
+ # Create new version with incremented patch
50
+ INCREMENTED_VERSION="$MAJOR.$MINOR.$PATCH"
51
+ DATE_TIME="$(date +'%Y%m%d%H%M%S')"
52
+ NEW_VERSION="${INCREMENTED_VERSION}a${DATE_TIME}"
53
+ echo "Final version: $NEW_VERSION"
54
+ echo "new_version=$NEW_VERSION" >> "$GITHUB_OUTPUT"
55
+
33
56
  - name: Update Python Package Version
34
57
  uses: platomo/update-version-py-action@v1.0.1
35
58
  with:
36
- version: nightly
59
+ version: ${{ steps.get_version.outputs.new_version }}
37
60
  file-path: "OTVision"
38
61
  - name: Install pypa/build
39
62
  shell: bash
@@ -63,14 +63,13 @@ repos:
63
63
  - pre-commit==3.8.0
64
64
  - pytest-cov==5.0.0
65
65
  - pytest==8.3.3
66
- - torch==2.3.1
67
66
  - torchvision==0.18.1
68
67
  - twine==6.1.0
69
68
  - types-PyYAML
70
69
  - types-flake8
71
70
  - types-geopandas
72
71
  - types-jsonschema
73
- - types-setuptools
72
+ - types-torch
74
73
  - types-tqdm
75
74
  - types-ujson
76
75
  - ultralytics==8.3.94
@@ -20,6 +20,7 @@ class DetectedFrameFactory:
20
20
 
21
21
  return DetectedFrame(
22
22
  source=frame[FrameKeys.source],
23
+ output=frame[FrameKeys.output],
23
24
  no=frame[FrameKeys.frame],
24
25
  occurrence=frame[FrameKeys.occurrence],
25
26
  detections=detections,
@@ -62,7 +62,7 @@ class OtdetFileWriter:
62
62
  detect_config = config.detect
63
63
 
64
64
  actual_frames = len(event.frames)
65
- if (expected_duration := detect_config.expected_duration) is not None:
65
+ if expected_duration := detect_config.expected_duration:
66
66
  actual_fps = actual_frames / expected_duration.total_seconds()
67
67
  else:
68
68
  actual_fps = actual_frames / source_metadata.duration.total_seconds()
@@ -27,10 +27,12 @@ from OTVision.domain.time import DatetimeProvider
27
27
 
28
28
  RTSP_URL = "rtsp://127.0.0.1:8554/test"
29
29
  RETRY_SECONDS = 1
30
+ DEFAULT_READ_FAIL_THRESHOLD = 5
30
31
 
31
32
 
32
33
  class Counter:
33
34
  def __init__(self, start_value: int = 0) -> None:
35
+ self._start_value = start_value
34
36
  self.__counter = start_value
35
37
 
36
38
  def increment(self) -> None:
@@ -39,6 +41,9 @@ class Counter:
39
41
  def get(self) -> int:
40
42
  return self.__counter
41
43
 
44
+ def reset(self) -> None:
45
+ self.__counter = self._start_value
46
+
42
47
 
43
48
  class RtspInputSource(InputSourceDetect):
44
49
 
@@ -68,12 +73,17 @@ class RtspInputSource(InputSourceDetect):
68
73
  def flush_buffer_size(self) -> int:
69
74
  return self.stream_config.flush_buffer_size
70
75
 
76
+ @property
77
+ def fps(self) -> float:
78
+ return self.config.convert.output_fps
79
+
71
80
  def __init__(
72
81
  self,
73
82
  subject: Subject[FlushEvent],
74
83
  datetime_provider: DatetimeProvider,
75
84
  frame_counter: Counter,
76
85
  get_current_config: GetCurrentConfig,
86
+ read_fail_threshold: int = DEFAULT_READ_FAIL_THRESHOLD,
77
87
  ) -> None:
78
88
  super().__init__(subject)
79
89
  self._datetime_provider = datetime_provider
@@ -82,6 +92,11 @@ class RtspInputSource(InputSourceDetect):
82
92
  self._get_current_config = get_current_config
83
93
  self._current_stream: str | None = None
84
94
  self._current_video_capture: VideoCapture | None = None
95
+ self._stream_start_time: datetime = self._datetime_provider.provide()
96
+ self._current_video_start_time = self._stream_start_time
97
+ self._outdated = True
98
+ self._read_fail_threshold = read_fail_threshold
99
+ self._consecutive_read_fails = 0
85
100
 
86
101
  @property
87
102
  def _video_capture(self) -> VideoCapture:
@@ -106,20 +121,30 @@ class RtspInputSource(InputSourceDetect):
106
121
  return self._current_video_capture
107
122
 
108
123
  def produce(self) -> Generator[Frame, None, None]:
109
- start_time = self._datetime_provider.provide()
124
+ self._stream_start_time = self._datetime_provider.provide()
125
+ self._current_video_start_time = self._stream_start_time
110
126
  while not self.should_stop():
111
127
  if (frame := self._read_next_frame()) is not None:
112
128
  self._frame_counter.increment()
129
+ occurrence = self._datetime_provider.provide()
130
+
131
+ if self._outdated:
132
+ self._current_video_start_time = occurrence
133
+ self._outdated = False
113
134
 
114
135
  yield Frame(
115
136
  data=convert_frame_to_rgb(frame), # YOLO expects RGB
116
137
  frame=self.current_frame_number,
117
138
  source=self.rtsp_url,
118
- occurrence=self._datetime_provider.provide(),
139
+ output=self.create_output(),
140
+ occurrence=occurrence,
119
141
  )
120
142
  if self.flush_condition_met():
121
- self._notify(start_time)
122
- self._notify(start_time)
143
+ self._notify()
144
+ self._outdated = True
145
+ self._frame_counter.reset()
146
+
147
+ self._notify()
123
148
 
124
149
  def _init_video_capture(self, source: str) -> VideoCapture:
125
150
  cap = VideoCapture(source)
@@ -136,10 +161,22 @@ class RtspInputSource(InputSourceDetect):
136
161
  def _read_next_frame(self) -> ndarray | None:
137
162
  successful, frame = self._video_capture.read()
138
163
  if successful:
164
+ self._consecutive_read_fails = 0
139
165
  return frame
166
+ self._consecutive_read_fails += 1
167
+
168
+ if self._consecutive_read_fails >= self._read_fail_threshold:
169
+ self._try_reconnecting_stream()
170
+
140
171
  logger().debug("Failed to grab frame")
141
172
  return None
142
173
 
174
+ def _try_reconnecting_stream(self) -> None:
175
+ self._video_capture.release()
176
+ self._current_video_capture = None
177
+ if not self.should_stop() and self._current_stream is not None:
178
+ self._current_video_capture = self._init_video_capture(self._current_stream)
179
+
143
180
  def should_stop(self) -> bool:
144
181
  return self._stop_capture
145
182
 
@@ -152,24 +189,16 @@ class RtspInputSource(InputSourceDetect):
152
189
  def flush_condition_met(self) -> bool:
153
190
  return self.current_frame_number % self.flush_buffer_size == 0
154
191
 
155
- def _notify(self, start_time: datetime) -> None:
192
+ def _notify(self) -> None:
156
193
  frame_width = int(self._video_capture.get(CAP_PROP_FRAME_WIDTH))
157
194
  frame_height = int(self._video_capture.get(CAP_PROP_FRAME_HEIGHT))
158
- fps = self.config.convert.output_fps
159
- _start_time = calculate_start_time(
160
- start_time, self.current_frame_number, fps, self.flush_buffer_size
161
- )
162
195
  frames = (
163
196
  self.flush_buffer_size
164
197
  if self.current_frame_number % self.flush_buffer_size == 0
165
198
  else self.current_frame_number % self.flush_buffer_size
166
199
  )
167
- duration = timedelta(seconds=round(frames / fps))
168
- output_filename = (
169
- f"{self.stream_config.name}_FR{round(fps)}"
170
- f"_{_start_time.strftime(DATETIME_FORMAT)}.mp4"
171
- )
172
- output = str(self.stream_config.save_dir / output_filename)
200
+ duration = timedelta(seconds=round(frames / self.fps))
201
+ output = self.create_output()
173
202
  self._subject.notify(
174
203
  FlushEvent.create(
175
204
  source=self.rtsp_url,
@@ -177,22 +206,17 @@ class RtspInputSource(InputSourceDetect):
177
206
  duration=duration,
178
207
  source_width=frame_width,
179
208
  source_height=frame_height,
180
- source_fps=fps,
181
- start_time=_start_time,
209
+ source_fps=self.fps,
210
+ start_time=self._current_video_start_time,
182
211
  )
183
212
  )
184
213
 
185
-
186
- def calculate_start_time(
187
- start: datetime, current_frame_number: int, fps: float, flush_buffer_size: int
188
- ) -> datetime:
189
- offset_in_frames = (
190
- current_frame_number // flush_buffer_size - 1
191
- ) * flush_buffer_size
192
- if offset_in_frames == 0:
193
- return start
194
- offset_in_seconds = offset_in_frames / fps
195
- return start + timedelta(seconds=offset_in_seconds)
214
+ def create_output(self) -> str:
215
+ output_filename = (
216
+ f"{self.stream_config.name}_FR{round(self.fps)}"
217
+ f"_{self._current_video_start_time.strftime(DATETIME_FORMAT)}.mp4"
218
+ )
219
+ return str(self.stream_config.save_dir / output_filename)
196
220
 
197
221
 
198
222
  def convert_frame_to_rgb(frame: ndarray) -> ndarray:
@@ -61,6 +61,7 @@ class VideoTimestamper(Timestamper):
61
61
  data=frame[FrameKeys.data],
62
62
  frame=frame[FrameKeys.frame],
63
63
  source=frame[FrameKeys.source],
64
+ output=frame[FrameKeys.output],
64
65
  occurrence=occurrence,
65
66
  )
66
67
 
@@ -116,6 +116,7 @@ class VideoSource(InputSourceDetect):
116
116
  FrameKeys.data: rotated_image,
117
117
  FrameKeys.frame: frame_number,
118
118
  FrameKeys.source: str(video_file),
119
+ FrameKeys.output: str(video_file),
119
120
  }
120
121
  )
121
122
  else:
@@ -124,6 +125,7 @@ class VideoSource(InputSourceDetect):
124
125
  FrameKeys.data: None,
125
126
  FrameKeys.frame: frame_number,
126
127
  FrameKeys.source: str(video_file),
128
+ FrameKeys.output: str(video_file),
127
129
  }
128
130
  )
129
131
  counter += 1
@@ -206,8 +208,9 @@ class VideoSource(InputSourceDetect):
206
208
  def __add_occurrence(self, timestamper: Timestamper, frame: dict) -> Frame:
207
209
  updated = timestamper.stamp(frame)
208
210
  return Frame(
209
- data=updated["data"],
210
- frame=updated["frame"],
211
- source=updated["source"],
212
- occurrence=updated["occurrence"],
211
+ data=updated[FrameKeys.data],
212
+ frame=updated[FrameKeys.frame],
213
+ source=updated[FrameKeys.source],
214
+ output=updated[FrameKeys.output],
215
+ occurrence=updated[FrameKeys.occurrence],
213
216
  )
@@ -20,6 +20,7 @@ class FrameKeys:
20
20
  frame: Literal["frame"] = "frame"
21
21
  source: Literal["source"] = "source"
22
22
  occurrence: Literal["occurrence"] = "occurrence"
23
+ output: Literal["output"] = "output"
23
24
 
24
25
 
25
26
  class Frame(TypedDict):
@@ -35,6 +36,7 @@ class Frame(TypedDict):
35
36
  data: Optional[ndarray]
36
37
  frame: int
37
38
  source: str
39
+ output: str
38
40
  occurrence: datetime
39
41
 
40
42
 
@@ -49,6 +51,7 @@ class DetectedFrame:
49
51
  no (FrameNo): Frame number.
50
52
  occurrence (datetime): Time stamp, at which frame was recorded.
51
53
  source (str): Source from where frame was obtained, e.g. video file path.
54
+ output (str): Output file name, e.g. video file name.
52
55
  detections (Sequence[Detection]): A sequence of Detections occurring in frame.
53
56
  image (Optional[ndarray]): Optional image data of frame.
54
57
  """
@@ -56,6 +59,7 @@ class DetectedFrame:
56
59
  no: FrameNo
57
60
  occurrence: datetime
58
61
  source: str
62
+ output: str
59
63
  detections: Sequence[Detection]
60
64
  image: Optional[ndarray] = None
61
65
 
@@ -64,6 +68,7 @@ class DetectedFrame:
64
68
  no=self.no,
65
69
  occurrence=self.occurrence,
66
70
  source=self.source,
71
+ output=self.output,
67
72
  detections=self.detections,
68
73
  image=None,
69
74
  )
@@ -153,6 +158,7 @@ class TrackedFrame(DetectedFrame):
153
158
  no=self.no,
154
159
  occurrence=self.occurrence,
155
160
  source=self.source,
161
+ output=self.output,
156
162
  finished_tracks=self.finished_tracks,
157
163
  detections=detections,
158
164
  image=self.image,
@@ -62,6 +62,7 @@ class JsonChunkParser(ChunkParser):
62
62
  no=int(key) + frame_offset,
63
63
  occurrence=occurrence,
64
64
  source=str(file),
65
+ output=str(file),
65
66
  detections=detections,
66
67
  image=None,
67
68
  )
@@ -222,6 +222,7 @@ class IouTracker(Tracker):
222
222
  no=frame.no,
223
223
  occurrence=frame.occurrence,
224
224
  source=frame.source,
225
+ output=frame.output,
225
226
  detections=tracked_detections,
226
227
  image=frame.image,
227
228
  finished_tracks=set(finished_track_ids),
@@ -1,4 +1,4 @@
1
- __version__ = "v0.6.5"
1
+ __version__ = "v0.6.7"
2
2
 
3
3
 
4
4
  def otdet_version() -> str:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: OTVision
3
- Version: 0.6.5
3
+ Version: 0.6.7
4
4
  Summary: OTVision is a core module of the OpenTrafficCam framework to perform object detection and tracking.
5
5
  Project-URL: Homepage, https://opentrafficcam.org/
6
6
  Project-URL: Documentation, https://opentrafficcam.org/overview/
@@ -27,7 +27,6 @@ Requires-Dist: numpy==2.1.1; sys_platform != 'win32'
27
27
  Requires-Dist: opencv-python==4.10.0.84
28
28
  Requires-Dist: pandas==2.2.3
29
29
  Requires-Dist: pyyaml==6.0.2
30
- Requires-Dist: setuptools==74.0.0
31
30
  Requires-Dist: torch==2.3.1
32
31
  Requires-Dist: torchvision==0.18.1
33
32
  Requires-Dist: tqdm==4.67.1
@@ -9,7 +9,6 @@ numpy==1.26.4; sys_platform == 'win32' # ultralytics requires numpy <= 2.1.1; to
9
9
  opencv-python==4.10.0.84 # only upgrade when https://github.com/opencv/opencv/issues/27091 is resolved
10
10
  pandas==2.2.3
11
11
  PyYAML==6.0.2
12
- setuptools==74.0.0
13
12
  # Follow instructions at https://pytorch.org to install torch with CUDA
14
13
  torch==2.3.1 # NOTE: Omit if using torch with CUDA and install manually
15
14
  torchvision==0.18.1 # NOTE: Omit if using torch with CUDA and install manually
@@ -16,6 +16,7 @@ class TestDetectedFrameFactory:
16
16
 
17
17
  assert actual == DetectedFrame(
18
18
  source=given_frame[FrameKeys.source],
19
+ output=given_frame[FrameKeys.output],
19
20
  no=given_frame[FrameKeys.frame],
20
21
  occurrence=given_frame[FrameKeys.occurrence],
21
22
  detections=given_detections,
@@ -28,6 +29,7 @@ class TestDetectedFrameFactory:
28
29
  frame=1,
29
30
  occurrence=datetime(2020, 1, 1, 12, 1, 1),
30
31
  source="path/to/source.mp4",
32
+ output="path/to/output.mp4",
31
33
  )
32
34
 
33
35
  def create_detections(self) -> list[Detection]:
@@ -98,6 +98,7 @@ def create_frame_without_occurrence(frame_number: int) -> dict:
98
98
  FrameKeys.data: Mock(),
99
99
  FrameKeys.frame: frame_number,
100
100
  FrameKeys.source: SOURCE,
101
+ FrameKeys.output: SOURCE,
101
102
  }
102
103
 
103
104
 
@@ -112,5 +113,6 @@ def create_expected_frame(raw_data: dict, occurrence: datetime) -> Frame:
112
113
  data=raw_data[FrameKeys.data],
113
114
  frame=raw_data[FrameKeys.frame],
114
115
  source=raw_data[FrameKeys.source],
116
+ output=raw_data[FrameKeys.output],
115
117
  occurrence=occurrence,
116
118
  )
@@ -47,6 +47,7 @@ class TestDetectedFrameBuffer:
47
47
  frame_number = 1
48
48
  occurrence = datetime(2020, 1, 1, 12, 0, 0)
49
49
  source = "my_source"
50
+ output = "path/to/output.mp4"
50
51
  detections: list[Detection] = create_mocks(3)
51
52
  image = Mock()
52
53
 
@@ -54,6 +55,7 @@ class TestDetectedFrameBuffer:
54
55
  no=frame_number,
55
56
  occurrence=occurrence,
56
57
  source=source,
58
+ output=output,
57
59
  detections=detections,
58
60
  image=image,
59
61
  )
@@ -64,6 +66,7 @@ class TestDetectedFrameBuffer:
64
66
  no=frame_number,
65
67
  occurrence=occurrence,
66
68
  source=source,
69
+ output=output,
67
70
  detections=detections,
68
71
  image=None,
69
72
  )
@@ -19,6 +19,7 @@ GIVEN_ACTUAL_DURATION = timedelta(
19
19
  hours=36, seconds=33, milliseconds=12, microseconds=15
20
20
  )
21
21
  EXPECTED_VIDEO_LENGTH = "36:00:33"
22
+ DETECTED_FRAME_OUTPUT = "path/to/output.mp4"
22
23
 
23
24
 
24
25
  def create_expected_video_metadata(
@@ -109,6 +110,7 @@ def create_detected_frame(source: str, frame_number: int) -> DetectedFrame:
109
110
  )
110
111
  return DetectedFrame(
111
112
  source=source,
113
+ output=DETECTED_FRAME_OUTPUT,
112
114
  no=frame_number,
113
115
  detections=[detection],
114
116
  occurrence=datetime(2020, 1, 1, 12, 0, 10),