pybaseutils 2.4.7__tar.gz → 2.4.9__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 (331) hide show
  1. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/PKG-INFO +1 -1
  2. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/__init__.py +1 -1
  3. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/base/list_queue.py +5 -0
  4. pybaseutils-2.4.9/pybaseutils/base/producer_consumer.py +155 -0
  5. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/base64_utils.py +2 -2
  6. pybaseutils-2.4.9/pybaseutils/cvutils/camera.py +90 -0
  7. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/cvutils/video_utils.py +59 -35
  8. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/dataloader/parser_labelme.py +22 -16
  9. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/dataloader/parser_labelme_line.py +0 -0
  10. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/dict_uils.py +2 -1
  11. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/file_utils.py +1 -0
  12. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/image_utils.py +32 -26
  13. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/json_utils.py +28 -2
  14. pybaseutils-2.4.9/pybaseutils/nets_utils.py +24 -0
  15. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/singleton_utils.py +3 -0
  16. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/transforms/build_transform.py +0 -0
  17. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils.egg-info/PKG-INFO +1 -1
  18. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils.egg-info/SOURCES.txt +7 -0
  19. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils.egg-info/dependency_links.txt +0 -0
  20. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils.egg-info/not-zip-safe +0 -0
  21. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils.egg-info/top_level.txt +0 -0
  22. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/setup.cfg +0 -0
  23. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/aije/demo_labelme_crop_ailt.py +7 -4
  24. pybaseutils-2.4.9/test_py/aije/demo_motion_blur.py +91 -0
  25. pybaseutils-2.4.9/test_py/aije/demo_video_aije.py +42 -0
  26. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/aije/mask_image.py +0 -0
  27. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/converter/fall_dataset.py +0 -0
  28. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/converter/parking_rois_gopro.py +0 -0
  29. pybaseutils-2.4.9/test_py/demo1.py +46 -0
  30. pybaseutils-2.4.9/test_py/demo2.py +69 -0
  31. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/demo_gif_video.py +4 -4
  32. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/demo_lableme_vis.py +1 -5
  33. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/demo_nii.py +5 -5
  34. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/demo_video2frame.py +5 -4
  35. pybaseutils-2.4.9/test_py/fast_api/__init__.py +9 -0
  36. pybaseutils-2.4.9/test_py/fast_api/create_image_url.py +55 -0
  37. pybaseutils-2.4.9/test_py/fast_api/get_image_url.py +88 -0
  38. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/qrcode/__init__.py +0 -0
  39. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/qrcode/demo.py +0 -0
  40. pybaseutils-2.4.9/test_py/registry/main.py +23 -0
  41. pybaseutils-2.4.9/test_py/test_camera.py +28 -0
  42. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/web_socket/chat_service.py +52 -28
  43. pybaseutils-2.4.7/pybaseutils/base/producer_consumer.py +0 -138
  44. pybaseutils-2.4.7/test_py/aije/demo_video_aije.py +0 -97
  45. pybaseutils-2.4.7/test_py/demo1.py +0 -21
  46. pybaseutils-2.4.7/test_py/demo2.py +0 -50
  47. pybaseutils-2.4.7/test_py/registry/main.py +0 -62
  48. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/LICENCE +0 -0
  49. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/README.md +0 -0
  50. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/audio/__init__.py +0 -0
  51. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/audio/audio_utils.py +0 -0
  52. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/audio/pyaudio_utils.py +0 -0
  53. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/audio/vad_utils.py +0 -0
  54. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/base/__init__.py +0 -0
  55. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/base/dict_queue.py +0 -0
  56. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/batch_utils.py +0 -0
  57. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/build_utils/__init__.py +0 -0
  58. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/build_utils/cython_utils.py +0 -0
  59. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/build_utils/pyarmor_utils.py +0 -0
  60. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/cluster/__init__.py +0 -0
  61. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/cluster/kmean.py +0 -0
  62. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/cluster/maxmin_distance.py +0 -0
  63. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/cluster/similarity.py +0 -0
  64. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/color_utils.py +0 -0
  65. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/config_utils.py +0 -0
  66. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/converter/__init__.py +0 -0
  67. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/converter/build_coco.py +0 -0
  68. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/converter/build_cvat.py +0 -0
  69. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/converter/build_labelme.py +0 -0
  70. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/converter/build_voc.py +0 -0
  71. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/converter/concat_coco.py +0 -0
  72. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/converter/convert_coco2labelme.py +0 -0
  73. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/converter/convert_coco2voc.py +0 -0
  74. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/converter/convert_cvat2labelme.py +0 -0
  75. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/converter/convert_labelme2coco.py +0 -0
  76. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/converter/convert_labelme2cvat.py +0 -0
  77. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/converter/convert_labelme2labelme.py +0 -0
  78. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/converter/convert_labelme2voc.py +0 -0
  79. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/converter/convert_labelme2yolo.py +0 -0
  80. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/converter/convert_voc2coco.py +0 -0
  81. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/converter/convert_voc2labelme.py +0 -0
  82. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/converter/convert_voc2voc.py +0 -0
  83. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/converter/convert_voc2yolo.py +0 -0
  84. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/converter/convert_yolo2labelme.py +0 -0
  85. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/converter/convert_yolo2voc.py +0 -0
  86. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/converter/prelabelme.py +0 -0
  87. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/coords_utils.py +0 -0
  88. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/cvutils/__init__.py +0 -0
  89. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/cvutils/corner_utils.py +0 -0
  90. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/cvutils/monitor.py +0 -0
  91. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/cvutils/mouse_utils.py +0 -0
  92. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/cvutils/nms_utils.py +0 -0
  93. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/data_utils.py +0 -0
  94. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/dataloader/__init__.py +0 -0
  95. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/dataloader/balanced_classes.py +0 -0
  96. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/dataloader/base_coco.py +0 -0
  97. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/dataloader/base_dataset.py +0 -0
  98. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/dataloader/data_resample.py +0 -0
  99. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/dataloader/parser_coco_det.py +0 -0
  100. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/dataloader/parser_coco_ins.py +0 -0
  101. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/dataloader/parser_coco_kps.py +0 -0
  102. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/dataloader/parser_image_folder.py +0 -0
  103. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/dataloader/parser_image_text.py +0 -0
  104. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/dataloader/parser_labelme_crop.py +0 -0
  105. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/dataloader/parser_video_folder.py +0 -0
  106. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/dataloader/parser_video_text.py +0 -0
  107. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/dataloader/parser_voc.py +0 -0
  108. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/dataloader/parser_yolo.py +0 -0
  109. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/dataloader/voc_seg_utils.py +0 -0
  110. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/filter/QueueTable.py +0 -0
  111. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/filter/__init__.py +0 -0
  112. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/filter/demo.py +0 -0
  113. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/filter/kalman_filter.py +0 -0
  114. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/filter/mean_filter.py +0 -0
  115. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/filter/motion_filter.py +0 -0
  116. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/filter/pose_filter.py +0 -0
  117. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/font_style/__init__.py +0 -0
  118. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/font_utils.py +0 -0
  119. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/geometry_tools.py +0 -0
  120. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/heatmap_utils.py +0 -0
  121. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/http_utils.py +0 -0
  122. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/log.py +0 -0
  123. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/log_utils.py +0 -0
  124. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/media/__init__.py +0 -0
  125. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/media/ffmpeg_utils.py +0 -0
  126. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/metrics/__init__.py +0 -0
  127. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/metrics/accuracy.py +0 -0
  128. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/metrics/average_meter.py +0 -0
  129. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/metrics/class_report.py +0 -0
  130. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/metrics/plot_pr.py +0 -0
  131. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/metrics/plot_roc.py +0 -0
  132. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/numpy_utils.py +0 -0
  133. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/pandas_utils.py +0 -0
  134. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/plot_utils.py +0 -0
  135. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/pose/__init__.py +0 -0
  136. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/pose/bones_utils.py +0 -0
  137. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/pose/human_pose.py +0 -0
  138. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/pose/pose_utils.py +0 -0
  139. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/pycpp/__init__.py +0 -0
  140. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/pycpp/demo.py +0 -0
  141. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/pycpp/main.py +0 -0
  142. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/server/__init__.py +0 -0
  143. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/server/apm_server.py +0 -0
  144. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/setup_config.py +0 -0
  145. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/text_utils.py +0 -0
  146. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/thread_utils.py +0 -0
  147. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/time_utils.py +0 -0
  148. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/tracemalloc_utils.py +0 -0
  149. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/tracemalloc_utils2.py +0 -0
  150. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/tracking/QueueTable.py +0 -0
  151. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/tracking/__init__.py +0 -0
  152. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/tracking/demo.py +0 -0
  153. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/tracking/kalman_filter.py +0 -0
  154. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/tracking/mean_filter.py +0 -0
  155. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/tracking/motion_filter.py +0 -0
  156. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/tracking/pose_filter.py +0 -0
  157. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/transforms/__init__.py +0 -0
  158. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/transforms/affine_transform.py +0 -0
  159. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/transforms/face_alignment.py +0 -0
  160. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/transforms/imgaug_utils.py +0 -0
  161. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/transforms/transform_utils.py +0 -0
  162. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/web/__init__.py +0 -0
  163. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/web/app_gradio_image.py +0 -0
  164. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/web/app_stweb_image.py +0 -0
  165. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/web/app_webio_image.py +0 -0
  166. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/web/demo.py +0 -0
  167. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/word_utils.py +0 -0
  168. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/worker.py +0 -0
  169. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/pybaseutils/yaml_utils.py +0 -0
  170. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/setup.py +0 -0
  171. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/Image_enhance/__init__.py +0 -0
  172. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/Image_enhance/dmeo01.py +0 -0
  173. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/WebCrawler/__init__.py +0 -0
  174. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/WebCrawler/search_baidu.py +0 -0
  175. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/WebCrawler/search_biying.py +0 -0
  176. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/__init__.py +0 -0
  177. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/aije/__init__.py +0 -0
  178. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/aije/action_dataset.py +0 -0
  179. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/aije/build_cython.py +0 -0
  180. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/aije/build_pyarmor.py +0 -0
  181. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/aije/build_service.py +0 -0
  182. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/aije/convert_cvat2labelme.py +0 -0
  183. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/aije/convert_labelme2coco.py +0 -0
  184. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/aije/convert_labelme2voc.py +0 -0
  185. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/aije/copy_move.py +0 -0
  186. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/aije/demo_labelme_crop_aije.py +0 -0
  187. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/aije/demo_labelme_shock.py +0 -0
  188. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/aije/demo_voc_crop.py +0 -0
  189. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/aije/demo_voc_vis.py +0 -0
  190. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/aije/get_pair_data.py +0 -0
  191. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/aije/video_convertor.py +0 -0
  192. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/audio/__init__.py +0 -0
  193. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/audio/demo.py +0 -0
  194. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/audio/main.py +0 -0
  195. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/audio/main_read.py +0 -0
  196. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/audio/segment.py +0 -0
  197. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/audio/speechbrain_asr_indoor_prod.py +0 -0
  198. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/audio/speechbrain_demo.py +0 -0
  199. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/audio_demo1.py +0 -0
  200. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/camera/__init__.py +0 -0
  201. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/camera/demo.py +0 -0
  202. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/captcha/__init__.py +0 -0
  203. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/captcha/demo.py +0 -0
  204. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/class_attribute.py +0 -0
  205. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/class_names.py +0 -0
  206. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/converter/AffectNet.py +0 -0
  207. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/converter/AsianMovie.py +0 -0
  208. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/converter/BITVehicle2voc.py +0 -0
  209. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/converter/BSTLD2voc.py +0 -0
  210. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/converter/CCPD.py +0 -0
  211. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/converter/CCPD2voc.py +0 -0
  212. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/converter/FL3D_dataset.py +0 -0
  213. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/converter/FreiHAND2coco.py +0 -0
  214. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/converter/MTFL2voc.py +0 -0
  215. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/converter/TT100K.py +0 -0
  216. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/converter/WaterMeters1.py +0 -0
  217. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/converter/WaterMeters2.py +0 -0
  218. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/converter/__init__.py +0 -0
  219. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/converter/concat_coco.py +0 -0
  220. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/converter/convert_coco2voc.py +0 -0
  221. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/converter/convert_cvat2labelme.py +0 -0
  222. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/converter/convert_gesture2hand.py +0 -0
  223. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/converter/convert_labelme2coco.py +0 -0
  224. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/converter/convert_labelme2cvat.py +0 -0
  225. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/converter/convert_labelme2labelme.py +0 -0
  226. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/converter/convert_labelme2voc.py +0 -0
  227. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/converter/convert_voc2labelme.py +0 -0
  228. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/converter/convert_yolo2labelme.py +0 -0
  229. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/converter/fatigue_driving.py +0 -0
  230. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/converter/fdd_dataset.py +0 -0
  231. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/converter/get_pair_data.py +0 -0
  232. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/converter/handpose2coco.py +0 -0
  233. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/converter/insects_for_aichallenger.py +0 -0
  234. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/converter/tt100k_utils.py +0 -0
  235. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/converter/ua_detrac2voc.py +0 -0
  236. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/converter/ucf101_dataset.py +0 -0
  237. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/converter/voc_sbd2labelme.py +0 -0
  238. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/cython_build/__init__.py +0 -0
  239. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/cython_build/build_cython.py +0 -0
  240. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/cython_build/build_pyarmor.py +0 -0
  241. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/cython_build/cryptography_demo.py +0 -0
  242. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/cython_build/fun_sum.py +0 -0
  243. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/cython_build/main.py +0 -0
  244. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/cython_build/model_des_enctypt.py +0 -0
  245. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/cython_build/model_enctypt.py +0 -0
  246. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/date_dataset.py +0 -0
  247. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/date_demo.py +0 -0
  248. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/datedataset_bk.py +0 -0
  249. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/demo3.py +0 -0
  250. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/demo4.py +0 -0
  251. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/demo_async_await1.py +0 -0
  252. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/demo_async_await2.py +0 -0
  253. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/demo_coco_vis.py +0 -0
  254. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/demo_copy_files.py +0 -0
  255. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/demo_copy_files_for_voc.py +0 -0
  256. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/demo_ffmpy.py +0 -0
  257. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/demo_for_annular_to_rect.py +0 -0
  258. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/demo_for_pair_file.py +0 -0
  259. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/demo_for_polygon.py +0 -0
  260. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/demo_for_trt.py +0 -0
  261. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/demo_get_file_label.py +0 -0
  262. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/demo_get_file_list.py +0 -0
  263. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/demo_gif.py +0 -0
  264. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/demo_image_crop.py +0 -0
  265. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/demo_kpts.py +0 -0
  266. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/demo_labelme.py +0 -0
  267. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/demo_labelme_crop.py +0 -0
  268. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/demo_letterbox.py +0 -0
  269. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/demo_metrics.py +0 -0
  270. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/demo_mosaic.py +0 -0
  271. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/demo_mouse.py +0 -0
  272. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/demo_pandas.py +0 -0
  273. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/demo_plot.py +0 -0
  274. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/demo_prelabelme.py +0 -0
  275. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/demo_rename.py +0 -0
  276. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/demo_standard_image .py +0 -0
  277. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/demo_standard_video .py +0 -0
  278. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/demo_taichi.py +0 -0
  279. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/demo_video_crop.py +0 -0
  280. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/demo_voc_crop.py +0 -0
  281. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/demo_voc_vis.py +0 -0
  282. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/demo_word_similar.py +0 -0
  283. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/demo_worker1.py +0 -0
  284. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/demo_worker2.py +0 -0
  285. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/detector/__init__.py +0 -0
  286. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/detector/demo.py +0 -0
  287. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/detector/detect_face_person.py +0 -0
  288. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/detector/predet_labelme.py +0 -0
  289. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/edit_distance/__init__.py +0 -0
  290. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/edit_distance/demo.py +0 -0
  291. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/edit_distance/text_matching.py +0 -0
  292. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/flask_demo/__init__.py +0 -0
  293. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/flask_demo/app.py +0 -0
  294. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/flask_demo/utils/__init__.py +0 -0
  295. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/flask_demo/utils/utils.py +0 -0
  296. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/get_file_list.py +0 -0
  297. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/gradio_app.py +0 -0
  298. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/gradio_app_v2.py +0 -0
  299. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/image_correction/__init__.py +0 -0
  300. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/image_correction/demo_correction_v1.py +0 -0
  301. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/image_correction/demo_correction_v2.py +0 -0
  302. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/image_correction/demo_correction_v3.py +0 -0
  303. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/kafka_worker.py +0 -0
  304. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/men_tracemalloc.py +0 -0
  305. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/milvus_demo/__init__.py +0 -0
  306. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/milvus_demo/demo01.py +0 -0
  307. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/milvus_demo/demo02.py +0 -0
  308. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/milvus_demo/hello_milvus.py +0 -0
  309. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/milvus_demo/milvus_client.py +0 -0
  310. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/model_process.py +0 -0
  311. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/performance.py +0 -0
  312. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/pose/__init__.py +0 -0
  313. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/pose/human_pose.py +0 -0
  314. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/redis_py/__init__.py +0 -0
  315. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/redis_py/knn_search.py +0 -0
  316. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/redis_py/redis_client.py +0 -0
  317. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/registry/__init__.py +0 -0
  318. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/registry/base.py +0 -0
  319. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/registry/component.py +0 -0
  320. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/registry/register.py +0 -0
  321. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/single_class/GRU.py +0 -0
  322. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/single_class/TCN.py +0 -0
  323. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/single_class/__init__.py +0 -0
  324. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/single_class/demo.py +0 -0
  325. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/slowfastnet.py +0 -0
  326. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/test_fr/__init__.py +0 -0
  327. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/test_fr/demo11.py +0 -0
  328. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/test_fr/idcardocr.py +0 -0
  329. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/web_socket/__init__.py +0 -0
  330. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/web_socket/asr_clients.py +0 -0
  331. {pybaseutils-2.4.7 → pybaseutils-2.4.9}/test_py/web_socket/asr_service.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pybaseutils
3
- Version: 2.4.7
3
+ Version: 2.4.9
4
4
  Summary: pybaseutils
5
5
  Home-page: https://github.com/PanJinquan/base-utils
6
6
  Author: PanJinquan
@@ -8,4 +8,4 @@
8
8
  # --------------------------------------------------------
9
9
  """
10
10
 
11
- __version__ = '2.4.7'
11
+ __version__ = '2.4.9'
@@ -113,6 +113,11 @@ class Queue():
113
113
  return data1 + data2
114
114
  return []
115
115
 
116
+ def clear(self):
117
+ """清空队列"""
118
+ with self.queue.mutex:
119
+ self.queue.queue.clear()
120
+
116
121
 
117
122
  if __name__ == '__main__':
118
123
  q = Queue(maxsize=3)
@@ -0,0 +1,155 @@
1
+ # -*- coding: utf-8 -*-
2
+ """
3
+ # --------------------------------------------------------
4
+ # @Author : Pan
5
+ # @E-mail :
6
+ # @Date : 2025-10-29 16:52:22
7
+ # @Brief :
8
+ # --------------------------------------------------------
9
+ """
10
+ import os
11
+ import numpy as np
12
+ import time
13
+ import threading
14
+ from typing import List, Dict, Callable
15
+ from pybaseutils import thread_utils, file_utils, image_utils, base64_utils
16
+ from pybaseutils.cvutils import video_utils
17
+ from pybaseutils.base import list_queue
18
+
19
+ thread_lock = threading.Lock()
20
+
21
+
22
+ class ProducerConsumer:
23
+ def __init__(self, winsize=3, overlap=0.0, max_workers=2, **kwargs) -> None:
24
+ """
25
+ :param winsize:
26
+ :param overlap:
27
+ :param max_workers:
28
+ :param kwargs:
29
+ """
30
+ self.tag = self.__class__.__name__
31
+ self.log = kwargs.get('log', print) if kwargs.get('log', print) else print
32
+ self.winsize = winsize
33
+ self.overlap = overlap
34
+ self.max_workers = max_workers
35
+ self.kwargs = kwargs
36
+ self.producer = list_queue.Queue(maxsize=self.winsize) # 生产者
37
+ self.consumer = list_queue.Queue(maxsize=self.winsize) # 消费者
38
+ self.producer_end = False # 生产者是否结束
39
+ self.consumer_end = False # 消费者是否结束
40
+
41
+ def stop_producer(self):
42
+ """
43
+ 停止生产者线程
44
+ :return:
45
+ """
46
+ self.producer_end = True
47
+ self.log("stop producer")
48
+
49
+ def stop_consumer(self):
50
+ """
51
+ 停止消费者线程
52
+ :return:
53
+ """
54
+ self.consumer_end = True
55
+ self.log("stop consumer")
56
+
57
+ def task(self, data: List, *args, **kwargs):
58
+ """
59
+ 任务函数,处理输入数据
60
+ :param data: 输入数据
61
+ :return: 处理结果
62
+ """
63
+ self.log(f"args ={args},kwargs={kwargs}")
64
+ time.sleep(3)
65
+ result = "收到消息:" + file_utils.get_time(format="s")
66
+ return result
67
+
68
+ def task_consumer(self, task, *args, **kwargs):
69
+ """消费者任务"""
70
+ self.log(f"start consumer thread")
71
+ self.consumer_end = False
72
+ pool = thread_utils.ThreadPool(max_workers=self.max_workers)
73
+ future = []
74
+ while True:
75
+ # winsize = self.producer.qsize() if self.producer_end else self.winsize
76
+ if self.producer_end and self.producer.qsize() <= self.winsize:
77
+ winsize, overlap = self.producer.qsize(), 0 # TODO 如果生产者已经结束,则一次性处理剩余的数据
78
+ else:
79
+ winsize, overlap = self.winsize, self.overlap
80
+ while self.producer.qsize() >= winsize > 0 and len(future) < self.max_workers:
81
+ data = self.producer.get_window(winsize=winsize, overlap=overlap, block=False) # 提取窗口数据
82
+ f = pool.submit(task, data, args, **kwargs)
83
+ future.append(f)
84
+ self.log(f"tid={id(f)} producer={self.producer.qsize()} consumer={self.consumer.qsize()} "
85
+ f"winsize={winsize} future={len(future)} ")
86
+ if not future: time.sleep(0.1)
87
+ tmp = []
88
+ for f in future:
89
+ try:
90
+ self.consumer.put(f.result(timeout=0.1))
91
+ except Exception as e:
92
+ tmp.append(f)
93
+ future = tmp
94
+ # 生产者队列空,且停止发送数据(pend=True)
95
+ if len(future) == 0 and self.producer_end and self.producer.qsize() == 0:
96
+ print(f"finish consumer thread")
97
+ break
98
+ self.stop_consumer() # 消费者停止处理数据
99
+
100
+ def start_consumer(self, task: Callable, *args, **kwargs):
101
+ """启动消费者线程
102
+ :param task: 任务函数
103
+ :param args: 任务函数参数
104
+ :param kwargs: 任务函数参数
105
+ :return:
106
+ """
107
+ thread = threading.Thread(target=self.task_consumer, args=args, kwargs={"task": task, **kwargs})
108
+ thread.daemon = True
109
+ thread.start()
110
+
111
+
112
+ def example(text, video, realtime=False, freq=2, wintime=3, overlap=0.5, max_workers=2, delay=20, vis=True, **kwargs):
113
+ """
114
+ 实时分析功能,从视频中提取帧进行分析
115
+ :param text: 用户问题/任务描述
116
+ :param video: 视频文件路径或者摄像头ID
117
+ :param realtime: 是否实时处理视频帧,实时处理会丢弃很多视频帧,非实时会处理所有视频帧,但视频播放会很卡顿
118
+ :param freq: 视频帧提取频率(Hz)
119
+ :param wintime: 窗口时间长度,单位秒
120
+ :param overlap: 滑动窗口重叠比例
121
+ :param max_workers: 视频处理线程数
122
+ :return:
123
+ """
124
+ winsize = int(wintime * freq)
125
+ pc = ProducerConsumer(winsize=winsize, overlap=overlap, max_workers=max_workers, **kwargs)
126
+ # TODO 打开视频文件或摄像头
127
+ w, h, num_frames, fps = image_utils.get_video_info(video)
128
+ fpm = 1 / fps
129
+ interval = int(fps / freq) if fps > 0 else 1
130
+ video_cap = video_utils.video_iterator(video, save_video=None)
131
+ pc.start_consumer(task=pc.task, text=text, freq=freq) # 启动消费者线程
132
+ # TODO 主线程处理视频帧
133
+ for data_info in video_cap:
134
+ t1 = time.time()
135
+ image = data_info["frame"][:, :, ::-1] # BGR to RGB
136
+ image = image_utils.resize_image(image, size=(None, 640))
137
+ data_info["frame"] = image
138
+ # TODO 视频抽帧,放入生产者队列,非实时处理会阻塞,实时处理会丢弃旧的视频帧
139
+ if data_info['count'] % interval == 0:
140
+ # data_info['text'] = text
141
+ # data_info['freq'] = freq
142
+ pc.producer.put(data_info, block=not realtime)
143
+ if vis: image_utils.show_image("image", image, delay=1, use_rgb=True)
144
+ if data_info["finish"]: pc.stop_producer() # 标记生产者是否结束
145
+ td = time.time() - t1 # 秒
146
+ time.sleep(max(0.0, fpm - td)) # 保证视频有40ms延时
147
+ while pc.consumer.qsize() > 0 or (pc.producer_end and not pc.consumer_end):
148
+ result = pc.consumer.pop(block=False, timeout=0.005)
149
+ if result: print("result={}".format(result))
150
+
151
+
152
+ if __name__ == '__main__':
153
+ text = "请分析这个视频"
154
+ video_file = "/home/PKing/Videos/video4.mp4"
155
+ example(text=text, video=video_file, freq=2)
@@ -159,8 +159,8 @@ if __name__ == "__main__":
159
159
  print(image_file)
160
160
  src = image_utils.read_image(image_file, use_rgb=True)
161
161
  image_base64 = image2base64(src, prefix="data:image/jpeg;base64,", )
162
- img = Image.fromarray(src)
163
- data = {"image": img, "file": image_file}
162
+ pltimg = Image.fromarray(src)
163
+ data = {"image": pltimg, "file": image_file}
164
164
  data = serialization(data)
165
165
  data = deserialization(data)
166
166
  dst = data["image"]
@@ -0,0 +1,90 @@
1
+ import cv2
2
+ import time
3
+ import numpy as np
4
+ import subprocess
5
+
6
+
7
+ class CameraCapture(object):
8
+ def __init__(self, video: str or int = 0, size=(1920, 1080), fps=30):
9
+ """
10
+ :param video: 视频设备路径或索引(如 0 或 "/dev/video0")
11
+ :param size: 视频分辨率 (宽, 高)
12
+ :param fps: 视频帧率
13
+ """
14
+ self.size = size
15
+ self.fps = fps
16
+ self.stopped = False
17
+ if isinstance(video, int): video = f"/dev/video{video}"
18
+ # 构建 FFmpeg 命令
19
+ # -re: 以原生帧率读取(模拟直播流)
20
+ # -fflags nobuffer: 关键!禁用缓冲区
21
+ # -flags low_delay: 关键!低延迟模式
22
+ # -probesize 32: 减小探测包大小,加快启动
23
+ # -pix_fmt bgr24: 直接输出 BGR 格式,方便 OpenCV/Numpy 使用,避免后续转换
24
+ command = [
25
+ 'ffmpeg',
26
+ '-re', # 按帧率读取
27
+ '-fflags', 'nobuffer', # 无缓冲
28
+ '-flags', 'low_delay', # 低延迟
29
+ '-probesize', '32', # 快速探测
30
+ '-i', video, # 输入设备
31
+ '-f', 'rawvideo', # 输出原始视频流
32
+ '-pix_fmt', 'bgr24', # 像素格式 BGR (OpenCV 格式)
33
+ '-s', f'{size[0]}x{size[1]}', # 分辨率
34
+ '-r', str(fps), # 帧率
35
+ '-' # 输出到 stdout
36
+ ]
37
+ # 启动进程
38
+ self.pipe = subprocess.Popen(command, stdout=subprocess.PIPE, bufsize=10 ** 8)
39
+ print(f"command: {' '.join(command)}")
40
+
41
+ def read(self):
42
+ if self.stopped:
43
+ self.stop()
44
+ return False, None
45
+ # 读取一帧的数据量 (宽 * 高 * 3通道)
46
+ buf = self.pipe.stdout.read(self.size[0] * self.size[1] * 3)
47
+ if len(buf) != self.size[0] * self.size[1] * 3:
48
+ self.stop()
49
+ return False, None # 读取失败或结束
50
+ # 将字节流转换为 numpy 数组
51
+ frame = np.frombuffer(buf, dtype=np.uint8).reshape((self.size[1], self.size[0], 3))
52
+ return True, frame
53
+
54
+ def release(self):
55
+ self.stop()
56
+
57
+ def stop(self):
58
+ self.stopped = True
59
+ time.sleep(0.1)
60
+ self.pipe.terminate() # 终止进程
61
+ try:
62
+ outs, errs = self.pipe.communicate(timeout=2)
63
+ except subprocess.TimeoutExpired as err:
64
+ # 如果 communicate 也超时(极少见),强制杀死
65
+ self.pipe.kill()
66
+ self.pipe.communicate() # 再次尝试清理
67
+ print(err)
68
+
69
+ def display(self):
70
+ while True:
71
+ t1 = time.time()
72
+ ret, frame = self.read()
73
+ t2 = time.time()
74
+ if not ret:
75
+ break
76
+ t21 = (t2 - t1) * 1000
77
+ print(f"image shape: {frame.shape},耗时: {t21:.3f}ms")
78
+ cv2.imshow('FFmpeg Low Latency', frame)
79
+ if cv2.waitKey(30) & 0xFF == ord('q'):
80
+ break
81
+
82
+
83
+ if __name__ == '__main__':
84
+ fps = 30
85
+ width = 1920
86
+ height = 1080
87
+ video = 0 # Windows 下可能是 0 或 "video=Integrated Webcam"
88
+ # video = "/home/PKing/Videos/demo-src.mp4" # Windows 下可能是 0 或 "video=Integrated Webcam"
89
+ cap = CameraCapture(video=video, size=(width, height), fps=fps)
90
+ cap.display()
@@ -11,6 +11,7 @@ import os
11
11
  import cv2
12
12
  import numpy as np
13
13
  import math
14
+ import time as timelib
14
15
  from typing import Callable
15
16
  from tqdm import tqdm
16
17
  from pybaseutils import image_utils, file_utils
@@ -23,6 +24,26 @@ get_video_info = image_utils.get_video_info
23
24
  get_video_writer = image_utils.get_video_writer
24
25
 
25
26
 
27
+ def get_usb_camera(video=-1, max_index=50):
28
+ """
29
+ 获取当前系统中连接的USB摄像头索引。
30
+ :param video: 视频路径或摄像头索引,默认值为-1表示自动检测。当video>=0时,不进行检测,直接返回video。
31
+ :param max_index: 最大检测索引范围,默认值为50。
32
+ :return: 一摄像头索引,camera=-1表示未检测到摄像头。
33
+ """
34
+ if video >= 0: return video
35
+ print("正在检测USB摄像头ID...")
36
+ camera = -1
37
+ for i in range(max_index):
38
+ cap = cv2.VideoCapture(i)
39
+ if cap.isOpened():
40
+ camera = i
41
+ cap.release()
42
+ break
43
+ print("检测到USB摄像头ID={}".format(camera))
44
+ return camera
45
+
46
+
26
47
  def merge_video(video1, video2, output="./output.mp4"):
27
48
  cmd = f'ffmpeg -i {video1} -i {video2} -filter_complex "[0:v:0][1:v:0]concat=n=2:v=1:a=0[outv]" -map "[outv]" {output}'
28
49
 
@@ -147,11 +168,11 @@ def video2frames(video_file, out_dir=None, task: Callable = None, interval=1, si
147
168
  frame_file = os.path.join(out_dir, "{}_{:0=5d}.jpg".format(filename, count))
148
169
  cv2.imwrite(frame_file, frame)
149
170
  data_info["file"] = frame_file
150
- frames.append(data_info)
171
+ if not out_dir: frames.append(data_info)
151
172
  return frames
152
173
 
153
174
 
154
- def video2frames_similarity(video_file, out_dir=None, func=None, interval=1, thresh=0.3, vis=True, **kwargs):
175
+ def video2frames_similarity(video_file, out_dir=None, func=None, prefix="", interval=1, thresh=0.3, vis=True, **kwargs):
155
176
  """
156
177
  视频抽帧图像
157
178
  :param video_file: 视频文件
@@ -162,7 +183,8 @@ def video2frames_similarity(video_file, out_dir=None, func=None, interval=1, thr
162
183
  :return:
163
184
  """
164
185
  sm = monitor.StatusMonitor()
165
- name = os.path.basename(video_file).split(".")[0]
186
+ name = os.path.basename(video_file).split(".")[0].replace("-", "_")
187
+ if prefix: name = f"{prefix}_{name}"
166
188
  if not out_dir: out_dir = os.path.join(os.path.dirname(video_file), name)
167
189
  video_cap = get_video_capture(video_file)
168
190
  width, height, num_frames, fps = get_video_info(video_cap, **kwargs)
@@ -181,13 +203,13 @@ def video2frames_similarity(video_file, out_dir=None, func=None, interval=1, thr
181
203
  last_frame = curr_frame.copy()
182
204
  diff = sm.get_frame_similarity(curr_frame, last_frame, size=(256, 256), vis=False)
183
205
  if diff > thresh:
184
- frame_file = os.path.join(out_dir, "{}_{:0=4d}.jpg".format(name, count))
206
+ frame_file = os.path.join(out_dir, "{}_{:0=6d}.jpg".format(name, count))
185
207
  last_frame = curr_frame.copy()
186
208
  cv2.imwrite(frame_file, curr_frame)
187
209
  frame_files.append(frame_file)
188
210
  if vis:
189
211
  text = "TH={},diff={:3.3f}".format(thresh, diff)
190
- image = image_utils.draw_text(curr_frame, point=(10, 70), color=(0, 255, 0),
212
+ image = image_utils.draw_text(curr_frame, point=(10, 100), color=(0, 255, 0),
191
213
  text=text, drawType="simple")
192
214
  image = image_utils.cv_show_image("image", image, delay=5)
193
215
  count += 1
@@ -245,7 +267,7 @@ def video2video(video_file: int or str, save_video: str or int, interval=1, size
245
267
  :param interval: 间隔
246
268
  :return:
247
269
  """
248
- video_capture(video_file=video_file, save_video=save_video, interval=interval, size=size, freq=freq, task=task,
270
+ video_capture(video=video_file, save_video=save_video, interval=interval, size=size, freq=freq, task=task,
249
271
  vis=vis, **kwargs)
250
272
 
251
273
 
@@ -284,11 +306,11 @@ def resize_video(video_file, save_video, size=(), start=0, interval=1, vis=True,
284
306
  video_writer.release()
285
307
 
286
308
 
287
- def video_capture(video_file: int or str, save_video: str or int = None, interval=1, size=(), freq=0,
309
+ def video_capture(video: int or str, save_video: str or int = None, interval=1, size=(), freq=0,
288
310
  task: Callable = None, vis=True, **kwargs):
289
311
  """
290
312
  读取摄像头或者视频流
291
- :param video_file: String 视频文件,如*.avi,*.mp4,...
313
+ :param video: String 视频文件,如*.avi,*.mp4,...
292
314
  Int 摄像头ID,如0,1,2
293
315
  :param save_video: 保存task视频处理后的结果
294
316
  :param interval: 抽帧处理间隔
@@ -299,13 +321,13 @@ def video_capture(video_file: int or str, save_video: str or int = None, interva
299
321
  title: 控制显示窗口名
300
322
  :return:
301
323
  """
302
- video_file = file_utils.str2number(video_file)
303
- if isinstance(video_file, str) and os.path.isfile(video_file):
304
- assert os.path.exists(video_file), f"video_file={video_file}"
305
- video_cap = image_utils.get_video_capture(video_file, fps=None)
306
- w, h, num_frames, fps = image_utils.get_video_info(video_cap, **kwargs)
324
+ video = file_utils.str2number(video)
325
+ if isinstance(video, str) and os.path.isfile(video):
326
+ assert os.path.exists(video), f"video={video}"
327
+ cap = image_utils.get_video_capture(video, fps=None)
328
+ w, h, num_frames, fps = image_utils.get_video_info(cap, **kwargs)
307
329
  time = kwargs.get("time", tuple()) # TODO 开始播放时间time[0],结束播放时间time[1],单位秒S
308
- clip = kwargs.get("clip", tuple()) # TODO 开始播放位置index[0],结束播放位置index[1]
330
+ clip = kwargs.get("clip", tuple()) # TODO 开始播放位置clip[0],结束播放位置clip[1]
309
331
  start, end = 0, -1
310
332
  if time and fps > 0:
311
333
  start, end = int(time[0] * fps), int(time[1] * fps)
@@ -319,10 +341,10 @@ def video_capture(video_file: int or str, save_video: str or int = None, interva
319
341
  count = 0
320
342
  video_writer = None
321
343
  while True:
322
- ret, frame = video_cap.read()
344
+ ret, frame = cap.read()
323
345
  if count % interval == 0 and count >= start:
324
346
  # TODO 设置抽帧的位置,但某些格式视频容易出现问题
325
- # if isinstance(video_file, str): video_cap.set(cv2.CAP_PROP_POS_FRAMES, count)
347
+ # if isinstance(video, str): video_cap.set(cv2.CAP_PROP_POS_FRAMES, count)
326
348
  # ret, frame = video_cap.read()
327
349
  if not ret or 0 < end < count or frame is None: break
328
350
  if size: frame = image_utils.resize_image(frame, size=size)
@@ -333,23 +355,23 @@ def video_capture(video_file: int or str, save_video: str or int = None, interva
333
355
  if not video_writer: video_writer = image_utils.get_video_writer(save_video, w, h, save_fps)
334
356
  video_writer.write(frame)
335
357
  count += 1
336
- video_cap.release()
358
+ cap.release()
337
359
  if video_writer:
338
360
  print("save video:{}".format(save_video))
339
361
  video_writer.release()
340
362
 
341
363
 
342
- def video_iterator(video_file, save_video: str or int = None, interval=1, size=(), freq=0,
364
+ def video_iterator(video, save_video: str or int = None, interval=1, size=(), freq=0,
343
365
  task: Callable = None, vis=False, **kwargs):
344
366
  """
345
367
  读取摄像头或者视频流迭代器
346
368
  Usage:
347
369
  from pybaseutils.cvutils import video_utils
348
- video_cap = video_utils.video_iterator(video_file, save_video, time=(4, 10))
349
- for data_info in video_cap:
370
+ cap = video_utils.video_iterator(video, save_video, time=(4, 10))
371
+ for data_info in cap:
350
372
  frame = data_info["frame"]
351
373
  ...
352
- :param video_file: String 视频文件,如*.avi,*.mp4,...
374
+ :param video: String 视频文件,如*.avi,*.mp4,...
353
375
  Int 摄像头ID,如0,1,2
354
376
  :param save_video: 保存task视频处理后的结果
355
377
  :param interval: 抽帧处理间隔,当interval=-1,表示当interval=fps,即一秒一帧
@@ -360,20 +382,20 @@ def video_iterator(video_file, save_video: str or int = None, interval=1, size=(
360
382
  delay: 控制显示延时,默认10S
361
383
  title: 控制显示窗口名,默认video
362
384
  time: 开始播放时间time[0],结束播放时间time[1],单位秒S
363
- clip: 开始播放位置index[0],结束播放位置index[1]
385
+ clip: 开始播放位置clip[0],结束播放位置clip[1]
364
386
  speed: 保存视频的播放速度,默认是播放帧率
365
387
  save_fps: 保存视频的帧率,默认是播放帧率
366
388
  :return: frame, count, w, h, fps =data_info['frame'],data_info['count'],data_info['w'],data_info['h'],data_info['fps']
367
389
  当输入是视频文件时,返回视频偏移量time和duration都是播放时间,单位S,差异不大
368
390
  当输入是摄像头时, 返回视频偏移量time是视频播放时间,duration是根据count计算的播放的时间
369
391
  """
370
- video_file = file_utils.str2number(video_file)
371
- if isinstance(video_file, str) and os.path.isfile(video_file):
372
- assert os.path.exists(video_file), f"video_file={video_file}"
373
- video_cap = image_utils.get_video_capture(video_file, fps=None)
374
- w, h, num_frames, fps = image_utils.get_video_info(video_cap, **kwargs)
392
+ video = file_utils.str2number(video)
393
+ if isinstance(video, str) and os.path.isfile(video):
394
+ assert os.path.exists(video), f"video={video}"
395
+ cap = image_utils.get_video_capture(video, fps=None)
396
+ w, h, num_frames, fps = image_utils.get_video_info(cap, **kwargs)
375
397
  time = kwargs.get("time", tuple()) # TODO 开始播放时间time[0],结束播放时间time[1],单位秒S
376
- clip = kwargs.get("clip", tuple()) # TODO 开始播放位置index[0],结束播放位置index[1]
398
+ clip = kwargs.get("clip", tuple()) # TODO 开始播放位置clip[0],结束播放位置clip[1]
377
399
  start, end = 0, -1
378
400
  if time and fps > 0:
379
401
  start, end = int(time[0] * fps), int(time[1] * fps)
@@ -390,16 +412,17 @@ def video_iterator(video_file, save_video: str or int = None, interval=1, size=(
390
412
  data_info = {}
391
413
  t0 = -1
392
414
  while True:
393
- ret, frame = (False, None) if use_fast else video_cap.read()
394
- t = video_cap.get(cv2.CAP_PROP_POS_MSEC) / 1000 # 获得视频偏移量毫秒为单位
415
+ systime = timelib.time()
416
+ ret, frame = (False, None) if use_fast else cap.read() # 读取视频很快,但读取USB摄像头比较耗时
417
+ t = cap.get(cv2.CAP_PROP_POS_MSEC) / 1000 # 获得视频偏移量毫秒为单位
395
418
  if t0 < 0 < t: t0 = t
396
419
  if t0 > 0: t = t - t0 # 获得视频偏移量毫秒为单位
397
420
  finish = 0 < end <= (count + interval)
398
421
  if count % interval == 0 and count >= start:
399
422
  # TODO 设置抽帧的位置,但某些格式视频容易出现问题
400
- if use_fast and isinstance(video_file, str):
401
- video_cap.set(cv2.CAP_PROP_POS_FRAMES, count)
402
- ret, frame = video_cap.read()
423
+ if use_fast and isinstance(video, str):
424
+ cap.set(cv2.CAP_PROP_POS_FRAMES, count)
425
+ ret, frame = cap.read()
403
426
  if not ret or 0 < end <= count or frame is None: break
404
427
  if size: frame = image_utils.resize_image(frame, size=size)
405
428
  if task: frame = task(frame, **kwargs)
@@ -407,7 +430,7 @@ def video_iterator(video_file, save_video: str or int = None, interval=1, size=(
407
430
  d = round(count / fps, 3) # TODO 通过fps计算播放时间
408
431
  t = round(t, 3) # 通过视频偏移量计算播放时间
409
432
  data_info = {"count": count, "time": t, "frame": frame, "w": w, "h": h, "fps": fps,
410
- "finish": finish, 'duration': d}
433
+ "finish": finish, 'duration': d, 'systime': systime}
411
434
  # TODO 返回data_info
412
435
  yield data_info
413
436
  frame = data_info["frame"]
@@ -416,8 +439,9 @@ def video_iterator(video_file, save_video: str or int = None, interval=1, size=(
416
439
  h, w = frame.shape[:2]
417
440
  if not video_writer: video_writer = image_utils.get_video_writer(save_video, w, h, save_fps)
418
441
  video_writer.write(frame)
442
+ if data_info['finish']: break # 控制结束
419
443
  count += 1
420
- video_cap.release()
444
+ cap.release()
421
445
  if video_writer:
422
446
  print("save video:{}".format(save_video))
423
447
  video_writer.release()
@@ -14,6 +14,7 @@ import glob
14
14
  import random
15
15
  import numbers
16
16
  import json
17
+ import traceback
17
18
  from tqdm import tqdm
18
19
  from pybaseutils import image_utils, file_utils, json_utils, text_utils
19
20
  from pybaseutils.dataloader.base_dataset import Dataset, ConcatDataset
@@ -145,21 +146,26 @@ class LabelMeDataset(Dataset):
145
146
  class_name = []
146
147
  for image_id in tqdm(image_ids, desc="check data"):
147
148
  image_file, anno_file, image_id = self.get_image_anno_file(image_id)
148
- if not os.path.exists(anno_file):
149
- continue
150
- if not os.path.exists(image_file):
151
- continue
152
- annotation, width, height = self.load_annotations(anno_file)
153
- data_info = self.parser_annotation(annotation, self.total_names, size=(width, height),
154
- min_points=self.min_points,
155
- unique=self.unique)
156
- if self.use_kpt:
157
- data_info = self.get_kpts_info(data_info, anno_file=anno_file, check_kpt=self.check_kpt, disp=True)
158
- labels = data_info["labels"]
159
- if len(labels) == 0:
149
+ try:
150
+ if not os.path.exists(anno_file):
151
+ continue
152
+ if not os.path.exists(image_file):
153
+ continue
154
+ annotation, width, height = self.load_annotations(anno_file)
155
+ data_info = self.parser_annotation(annotation, self.total_names, size=(width, height),
156
+ min_points=self.min_points,
157
+ unique=self.unique)
158
+ if self.use_kpt:
159
+ data_info = self.get_kpts_info(data_info, anno_file=anno_file, check_kpt=self.check_kpt, disp=True)
160
+ labels = data_info["labels"]
161
+ if len(labels) == 0:
162
+ continue
163
+ dst_ids.append(image_id)
164
+ class_name += labels
165
+ except Exception as e:
166
+ traceback.print_exc()
167
+ print(anno_file)
160
168
  continue
161
- dst_ids.append(image_id)
162
- class_name += labels
163
169
  if self.class_name is None:
164
170
  class_name = sorted(list(set(class_name)))
165
171
  self.class_name, self.class_dict = self.parser_classes(class_name)
@@ -417,8 +423,8 @@ class LabelMeDataset(Dataset):
417
423
  with open(anno_file, "r") as f:
418
424
  annotation: dict = json.load(f)
419
425
  annos = annotation.get("shapes", [])
420
- width = annotation.get('imageWidth', -1)
421
- height = annotation.get('imageHeight', -1)
426
+ width = int(annotation.get('imageWidth', -1))
427
+ height = int(annotation.get('imageHeight', -1))
422
428
  except Exception as e:
423
429
  # print(e,"illegal annotation:{}".format(anno_file))
424
430
  annos = []
@@ -15,7 +15,7 @@ from collections import defaultdict
15
15
 
16
16
  class Objects(object):
17
17
  def __init__(self, boxes, label, score, names=[], size=[], segms=None, masks=None, keypt=None,
18
- traid=None, trace=None, color=[], image=None):
18
+ traid=None, trace=None, color=[], image=None, file=""):
19
19
  self.boxes = boxes # 目标框(xmin,ymin,xmax,ymax)
20
20
  self.score = score # 目标框置信度
21
21
  self.label = label # 目标框类别
@@ -28,6 +28,7 @@ class Objects(object):
28
28
  self.trace = trace # 轨迹的历史boxes
29
29
  self.color = [(255, 0, 0)] * len(boxes) # 目标框颜色
30
30
  self.size = size # 原始图像大小
31
+ self.file = file # 文件路径
31
32
  self.depth = None # 深度图
32
33
  self.metas = defaultdict() # 其他信息
33
34
 
@@ -1579,6 +1579,7 @@ def zip_file(src, dst=None, s=None):
1579
1579
  return dst
1580
1580
 
1581
1581
 
1582
+
1582
1583
  if __name__ == '__main__':
1583
1584
  from pybaseutils import time_utils
1584
1585