QVideo 3.6.2__tar.gz → 3.6.4__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 (143) hide show
  1. {qvideo-3.6.2 → qvideo-3.6.4}/PKG-INFO +1 -1
  2. {qvideo-3.6.2 → qvideo-3.6.4}/QCamcorder.py +1 -0
  3. qvideo-3.6.4/QCamcorder.ui +51 -0
  4. {qvideo-3.6.2 → qvideo-3.6.4}/QVideo.egg-info/PKG-INFO +1 -1
  5. {qvideo-3.6.2 → qvideo-3.6.4}/QVideo.egg-info/SOURCES.txt +10 -1
  6. qvideo-3.6.4/dvr/QDVRWidget.ui +330 -0
  7. {qvideo-3.6.2 → qvideo-3.6.4}/filters/Median.py +1 -0
  8. {qvideo-3.6.2 → qvideo-3.6.4}/filters/MoMedian.py +1 -0
  9. {qvideo-3.6.2 → qvideo-3.6.4}/filters/Normalize.py +1 -0
  10. {qvideo-3.6.2 → qvideo-3.6.4}/filters/QBlurFilter.py +1 -0
  11. {qvideo-3.6.2 → qvideo-3.6.4}/filters/QEdgeFilter.py +1 -0
  12. {qvideo-3.6.2 → qvideo-3.6.4}/filters/QRGBFilter.py +1 -0
  13. {qvideo-3.6.2 → qvideo-3.6.4}/filters/QSampleHold.py +1 -0
  14. {qvideo-3.6.2 → qvideo-3.6.4}/pyproject.toml +5 -1
  15. qvideo-3.6.4/tests/test_compositedemo.py +97 -0
  16. qvideo-3.6.4/tests/test_qlistflircameras.py +101 -0
  17. qvideo-3.6.4/tests/test_qpicameratree.py +113 -0
  18. qvideo-3.6.4/tests/test_trackpydemo.py +52 -0
  19. qvideo-3.6.4/tests/test_vendor_trees.py +215 -0
  20. qvideo-3.6.4/tests/test_yolodemo.py +59 -0
  21. {qvideo-3.6.2 → qvideo-3.6.4}/LICENSE.md +0 -0
  22. {qvideo-3.6.2 → qvideo-3.6.4}/QVideo.egg-info/dependency_links.txt +0 -0
  23. {qvideo-3.6.2 → qvideo-3.6.4}/QVideo.egg-info/requires.txt +0 -0
  24. {qvideo-3.6.2 → qvideo-3.6.4}/QVideo.egg-info/top_level.txt +0 -0
  25. {qvideo-3.6.2 → qvideo-3.6.4}/README.md +0 -0
  26. {qvideo-3.6.2 → qvideo-3.6.4}/__init__.py +0 -0
  27. {qvideo-3.6.2 → qvideo-3.6.4}/cameras/Basler/__init__.py +0 -0
  28. {qvideo-3.6.2 → qvideo-3.6.4}/cameras/Basler/_camera.py +0 -0
  29. {qvideo-3.6.2 → qvideo-3.6.4}/cameras/Basler/_tree.py +0 -0
  30. {qvideo-3.6.2 → qvideo-3.6.4}/cameras/Flir/QListFlirCameras.py +0 -0
  31. {qvideo-3.6.2 → qvideo-3.6.4}/cameras/Flir/__init__.py +0 -0
  32. {qvideo-3.6.2 → qvideo-3.6.4}/cameras/Flir/_camera.py +0 -0
  33. {qvideo-3.6.2 → qvideo-3.6.4}/cameras/Flir/_tree.py +0 -0
  34. {qvideo-3.6.2 → qvideo-3.6.4}/cameras/Genicam/__init__.py +0 -0
  35. {qvideo-3.6.2 → qvideo-3.6.4}/cameras/Genicam/_camera.py +0 -0
  36. {qvideo-3.6.2 → qvideo-3.6.4}/cameras/Genicam/_tree.py +0 -0
  37. {qvideo-3.6.2 → qvideo-3.6.4}/cameras/IDS/__init__.py +0 -0
  38. {qvideo-3.6.2 → qvideo-3.6.4}/cameras/IDS/_camera.py +0 -0
  39. {qvideo-3.6.2 → qvideo-3.6.4}/cameras/IDS/_tree.py +0 -0
  40. {qvideo-3.6.2 → qvideo-3.6.4}/cameras/MV/__init__.py +0 -0
  41. {qvideo-3.6.2 → qvideo-3.6.4}/cameras/MV/_camera.py +0 -0
  42. {qvideo-3.6.2 → qvideo-3.6.4}/cameras/MV/_tree.py +0 -0
  43. {qvideo-3.6.2 → qvideo-3.6.4}/cameras/Noise/__init__.py +0 -0
  44. {qvideo-3.6.2 → qvideo-3.6.4}/cameras/Noise/_camera.py +0 -0
  45. {qvideo-3.6.2 → qvideo-3.6.4}/cameras/Noise/_tree.py +0 -0
  46. {qvideo-3.6.2 → qvideo-3.6.4}/cameras/OpenCV/QListCVCameras.py +0 -0
  47. {qvideo-3.6.2 → qvideo-3.6.4}/cameras/OpenCV/__init__.py +0 -0
  48. {qvideo-3.6.2 → qvideo-3.6.4}/cameras/OpenCV/_camera.py +0 -0
  49. {qvideo-3.6.2 → qvideo-3.6.4}/cameras/OpenCV/_devices.py +0 -0
  50. {qvideo-3.6.2 → qvideo-3.6.4}/cameras/OpenCV/_tree.py +0 -0
  51. {qvideo-3.6.2 → qvideo-3.6.4}/cameras/Picamera/__init__.py +0 -0
  52. {qvideo-3.6.2 → qvideo-3.6.4}/cameras/Picamera/_camera.py +0 -0
  53. {qvideo-3.6.2 → qvideo-3.6.4}/cameras/Picamera/_tree.py +0 -0
  54. {qvideo-3.6.2 → qvideo-3.6.4}/cameras/Vimbax/__init__.py +0 -0
  55. {qvideo-3.6.2 → qvideo-3.6.4}/cameras/Vimbax/_camera.py +0 -0
  56. {qvideo-3.6.2 → qvideo-3.6.4}/cameras/Vimbax/_tree.py +0 -0
  57. {qvideo-3.6.2 → qvideo-3.6.4}/cameras/__init__.py +0 -0
  58. {qvideo-3.6.2 → qvideo-3.6.4}/demos/ROIdemo.py +0 -0
  59. {qvideo-3.6.2 → qvideo-3.6.4}/demos/__init__.py +0 -0
  60. {qvideo-3.6.2 → qvideo-3.6.4}/demos/compositedemo.py +0 -0
  61. {qvideo-3.6.2 → qvideo-3.6.4}/demos/demo.py +0 -0
  62. {qvideo-3.6.2 → qvideo-3.6.4}/demos/filterdemo.py +0 -0
  63. {qvideo-3.6.2 → qvideo-3.6.4}/demos/trackpydemo.py +0 -0
  64. {qvideo-3.6.2 → qvideo-3.6.4}/demos/yolodemo.py +0 -0
  65. {qvideo-3.6.2 → qvideo-3.6.4}/dvr/QDVRWidget.py +0 -0
  66. {qvideo-3.6.2 → qvideo-3.6.4}/dvr/QHDF5Reader.py +0 -0
  67. {qvideo-3.6.2 → qvideo-3.6.4}/dvr/QHDF5Writer.py +0 -0
  68. {qvideo-3.6.2 → qvideo-3.6.4}/dvr/QOpenCVReader.py +0 -0
  69. {qvideo-3.6.2 → qvideo-3.6.4}/dvr/QOpenCVWriter.py +0 -0
  70. {qvideo-3.6.2 → qvideo-3.6.4}/dvr/__init__.py +0 -0
  71. {qvideo-3.6.2 → qvideo-3.6.4}/dvr/icons_rc.py +0 -0
  72. {qvideo-3.6.2 → qvideo-3.6.4}/filters/QBlobFilter.py +0 -0
  73. {qvideo-3.6.2 → qvideo-3.6.4}/filters/QThresholdFilter.py +0 -0
  74. {qvideo-3.6.2 → qvideo-3.6.4}/filters/QYOLOFilter.py +0 -0
  75. {qvideo-3.6.2 → qvideo-3.6.4}/filters/_MedianBase.py +0 -0
  76. {qvideo-3.6.2 → qvideo-3.6.4}/filters/__init__.py +0 -0
  77. {qvideo-3.6.2 → qvideo-3.6.4}/lib/QCamera.py +0 -0
  78. {qvideo-3.6.2 → qvideo-3.6.4}/lib/QCameraTree.py +0 -0
  79. {qvideo-3.6.2 → qvideo-3.6.4}/lib/QFPSMeter.py +0 -0
  80. {qvideo-3.6.2 → qvideo-3.6.4}/lib/QFilterBank.py +0 -0
  81. {qvideo-3.6.2 → qvideo-3.6.4}/lib/QListCameras.py +0 -0
  82. {qvideo-3.6.2 → qvideo-3.6.4}/lib/QVideoFilter.py +0 -0
  83. {qvideo-3.6.2 → qvideo-3.6.4}/lib/QVideoReader.py +0 -0
  84. {qvideo-3.6.2 → qvideo-3.6.4}/lib/QVideoScreen.py +0 -0
  85. {qvideo-3.6.2 → qvideo-3.6.4}/lib/QVideoSource.py +0 -0
  86. {qvideo-3.6.2 → qvideo-3.6.4}/lib/QVideoWriter.py +0 -0
  87. {qvideo-3.6.2 → qvideo-3.6.4}/lib/__init__.py +0 -0
  88. {qvideo-3.6.2 → qvideo-3.6.4}/lib/chooser.py +0 -0
  89. {qvideo-3.6.2 → qvideo-3.6.4}/lib/clickable.py +0 -0
  90. {qvideo-3.6.2 → qvideo-3.6.4}/lib/videotypes.py +0 -0
  91. {qvideo-3.6.2 → qvideo-3.6.4}/overlays/__init__.py +0 -0
  92. {qvideo-3.6.2 → qvideo-3.6.4}/overlays/trackpy.py +0 -0
  93. {qvideo-3.6.2 → qvideo-3.6.4}/overlays/yolo.py +0 -0
  94. {qvideo-3.6.2 → qvideo-3.6.4}/setup.cfg +0 -0
  95. {qvideo-3.6.2 → qvideo-3.6.4}/tests/test_chooser.py +0 -0
  96. {qvideo-3.6.2 → qvideo-3.6.4}/tests/test_clickable.py +0 -0
  97. {qvideo-3.6.2 → qvideo-3.6.4}/tests/test_demo.py +0 -0
  98. {qvideo-3.6.2 → qvideo-3.6.4}/tests/test_filterdemo.py +0 -0
  99. {qvideo-3.6.2 → qvideo-3.6.4}/tests/test_icons_rc.py +0 -0
  100. {qvideo-3.6.2 → qvideo-3.6.4}/tests/test_median.py +0 -0
  101. {qvideo-3.6.2 → qvideo-3.6.4}/tests/test_momedian.py +0 -0
  102. {qvideo-3.6.2 → qvideo-3.6.4}/tests/test_normalize.py +0 -0
  103. {qvideo-3.6.2 → qvideo-3.6.4}/tests/test_qbaslercamera.py +0 -0
  104. {qvideo-3.6.2 → qvideo-3.6.4}/tests/test_qblobfilter.py +0 -0
  105. {qvideo-3.6.2 → qvideo-3.6.4}/tests/test_qblurfilter.py +0 -0
  106. {qvideo-3.6.2 → qvideo-3.6.4}/tests/test_qcamcorder.py +0 -0
  107. {qvideo-3.6.2 → qvideo-3.6.4}/tests/test_qcamera.py +0 -0
  108. {qvideo-3.6.2 → qvideo-3.6.4}/tests/test_qcameratree.py +0 -0
  109. {qvideo-3.6.2 → qvideo-3.6.4}/tests/test_qdvrwidget.py +0 -0
  110. {qvideo-3.6.2 → qvideo-3.6.4}/tests/test_qedgefilter.py +0 -0
  111. {qvideo-3.6.2 → qvideo-3.6.4}/tests/test_qfilterbank.py +0 -0
  112. {qvideo-3.6.2 → qvideo-3.6.4}/tests/test_qflircamera.py +0 -0
  113. {qvideo-3.6.2 → qvideo-3.6.4}/tests/test_qfpsmeter.py +0 -0
  114. {qvideo-3.6.2 → qvideo-3.6.4}/tests/test_qgenicamcamera.py +0 -0
  115. {qvideo-3.6.2 → qvideo-3.6.4}/tests/test_qgenicamtree.py +0 -0
  116. {qvideo-3.6.2 → qvideo-3.6.4}/tests/test_qhdf5reader.py +0 -0
  117. {qvideo-3.6.2 → qvideo-3.6.4}/tests/test_qhdf5writer.py +0 -0
  118. {qvideo-3.6.2 → qvideo-3.6.4}/tests/test_qidscamera.py +0 -0
  119. {qvideo-3.6.2 → qvideo-3.6.4}/tests/test_qlistcameras.py +0 -0
  120. {qvideo-3.6.2 → qvideo-3.6.4}/tests/test_qlistcvcameras.py +0 -0
  121. {qvideo-3.6.2 → qvideo-3.6.4}/tests/test_qmvcamera.py +0 -0
  122. {qvideo-3.6.2 → qvideo-3.6.4}/tests/test_qnoisecamera.py +0 -0
  123. {qvideo-3.6.2 → qvideo-3.6.4}/tests/test_qnoisetree.py +0 -0
  124. {qvideo-3.6.2 → qvideo-3.6.4}/tests/test_qopencvcamera.py +0 -0
  125. {qvideo-3.6.2 → qvideo-3.6.4}/tests/test_qopencvdevices.py +0 -0
  126. {qvideo-3.6.2 → qvideo-3.6.4}/tests/test_qopencvreader.py +0 -0
  127. {qvideo-3.6.2 → qvideo-3.6.4}/tests/test_qopencvtree.py +0 -0
  128. {qvideo-3.6.2 → qvideo-3.6.4}/tests/test_qopencvwriter.py +0 -0
  129. {qvideo-3.6.2 → qvideo-3.6.4}/tests/test_qpicamera.py +0 -0
  130. {qvideo-3.6.2 → qvideo-3.6.4}/tests/test_qrgbfilter.py +0 -0
  131. {qvideo-3.6.2 → qvideo-3.6.4}/tests/test_qsamplehold.py +0 -0
  132. {qvideo-3.6.2 → qvideo-3.6.4}/tests/test_qthresholdfilter.py +0 -0
  133. {qvideo-3.6.2 → qvideo-3.6.4}/tests/test_qvideoreader.py +0 -0
  134. {qvideo-3.6.2 → qvideo-3.6.4}/tests/test_qvideoscreen.py +0 -0
  135. {qvideo-3.6.2 → qvideo-3.6.4}/tests/test_qvideosource.py +0 -0
  136. {qvideo-3.6.2 → qvideo-3.6.4}/tests/test_qvideowriter.py +0 -0
  137. {qvideo-3.6.2 → qvideo-3.6.4}/tests/test_qvimbaxcamera.py +0 -0
  138. {qvideo-3.6.2 → qvideo-3.6.4}/tests/test_qyolofilter.py +0 -0
  139. {qvideo-3.6.2 → qvideo-3.6.4}/tests/test_resolutions.py +0 -0
  140. {qvideo-3.6.2 → qvideo-3.6.4}/tests/test_roidemo.py +0 -0
  141. {qvideo-3.6.2 → qvideo-3.6.4}/tests/test_trackpy_overlay.py +0 -0
  142. {qvideo-3.6.2 → qvideo-3.6.4}/tests/test_videofilter.py +0 -0
  143. {qvideo-3.6.2 → qvideo-3.6.4}/tests/test_yolo_overlay.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: QVideo
3
- Version: 3.6.2
3
+ Version: 3.6.4
4
4
  Summary: PyQt-based framework for integrating video cameras into research applications
5
5
  Author-email: "David G. Grier" <david.grier@nyu.edu>
6
6
  License: GPL-3.0-or-later
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env python3
2
+
2
3
  '''Composite camcorder widget combining a video screen, camera controls, and DVR.
3
4
 
4
5
  Run directly to launch a full camcorder application with camera selection::
@@ -0,0 +1,51 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <ui version="4.0">
3
+ <class>Form</class>
4
+ <widget class="QWidget" name="Form">
5
+ <property name="geometry">
6
+ <rect>
7
+ <x>0</x>
8
+ <y>0</y>
9
+ <width>628</width>
10
+ <height>519</height>
11
+ </rect>
12
+ </property>
13
+ <property name="windowTitle">
14
+ <string>DVR</string>
15
+ </property>
16
+ <layout class="QHBoxLayout" name="horizontalLayout">
17
+ <item>
18
+ <widget class="QVideoScreen" name="screen" native="true">
19
+ <property name="autoFillBackground">
20
+ <bool>false</bool>
21
+ </property>
22
+ </widget>
23
+ </item>
24
+ <item>
25
+ <widget class="QWidget" name="controls" native="true">
26
+ <layout class="QVBoxLayout" name="verticalLayout">
27
+ <item>
28
+ <widget class="QDVRWidget" name="dvr" native="true"/>
29
+ </item>
30
+ </layout>
31
+ </widget>
32
+ </item>
33
+ </layout>
34
+ </widget>
35
+ <customwidgets>
36
+ <customwidget>
37
+ <class>QVideoScreen</class>
38
+ <extends>QWidget</extends>
39
+ <header>QVideo.lib</header>
40
+ <container>1</container>
41
+ </customwidget>
42
+ <customwidget>
43
+ <class>QDVRWidget</class>
44
+ <extends>QWidget</extends>
45
+ <header>QVideo.dvr</header>
46
+ <container>1</container>
47
+ </customwidget>
48
+ </customwidgets>
49
+ <resources/>
50
+ <connections/>
51
+ </ui>
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: QVideo
3
- Version: 3.6.2
3
+ Version: 3.6.4
4
4
  Summary: PyQt-based framework for integrating video cameras into research applications
5
5
  Author-email: "David G. Grier" <david.grier@nyu.edu>
6
6
  License: GPL-3.0-or-later
@@ -1,9 +1,11 @@
1
1
  LICENSE.md
2
2
  QCamcorder.py
3
+ QCamcorder.ui
3
4
  README.md
4
5
  __init__.py
5
6
  pyproject.toml
6
7
  ./QCamcorder.py
8
+ ./QCamcorder.ui
7
9
  ./__init__.py
8
10
  QVideo.egg-info/PKG-INFO
9
11
  QVideo.egg-info/SOURCES.txt
@@ -49,6 +51,7 @@ demos/filterdemo.py
49
51
  demos/trackpydemo.py
50
52
  demos/yolodemo.py
51
53
  dvr/QDVRWidget.py
54
+ dvr/QDVRWidget.ui
52
55
  dvr/QHDF5Reader.py
53
56
  dvr/QHDF5Writer.py
54
57
  dvr/QOpenCVReader.py
@@ -86,6 +89,7 @@ overlays/trackpy.py
86
89
  overlays/yolo.py
87
90
  tests/test_chooser.py
88
91
  tests/test_clickable.py
92
+ tests/test_compositedemo.py
89
93
  tests/test_demo.py
90
94
  tests/test_filterdemo.py
91
95
  tests/test_icons_rc.py
@@ -110,6 +114,7 @@ tests/test_qhdf5writer.py
110
114
  tests/test_qidscamera.py
111
115
  tests/test_qlistcameras.py
112
116
  tests/test_qlistcvcameras.py
117
+ tests/test_qlistflircameras.py
113
118
  tests/test_qmvcamera.py
114
119
  tests/test_qnoisecamera.py
115
120
  tests/test_qnoisetree.py
@@ -119,6 +124,7 @@ tests/test_qopencvreader.py
119
124
  tests/test_qopencvtree.py
120
125
  tests/test_qopencvwriter.py
121
126
  tests/test_qpicamera.py
127
+ tests/test_qpicameratree.py
122
128
  tests/test_qrgbfilter.py
123
129
  tests/test_qsamplehold.py
124
130
  tests/test_qthresholdfilter.py
@@ -131,5 +137,8 @@ tests/test_qyolofilter.py
131
137
  tests/test_resolutions.py
132
138
  tests/test_roidemo.py
133
139
  tests/test_trackpy_overlay.py
140
+ tests/test_trackpydemo.py
141
+ tests/test_vendor_trees.py
134
142
  tests/test_videofilter.py
135
- tests/test_yolo_overlay.py
143
+ tests/test_yolo_overlay.py
144
+ tests/test_yolodemo.py
@@ -0,0 +1,330 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <ui version="4.0">
3
+ <class>QDVRWidget</class>
4
+ <widget class="QFrame" name="QDVRWidget">
5
+ <property name="geometry">
6
+ <rect>
7
+ <x>0</x>
8
+ <y>0</y>
9
+ <width>279</width>
10
+ <height>200</height>
11
+ </rect>
12
+ </property>
13
+ <property name="sizePolicy">
14
+ <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
15
+ <horstretch>0</horstretch>
16
+ <verstretch>0</verstretch>
17
+ </sizepolicy>
18
+ </property>
19
+ <property name="frameShape">
20
+ <enum>QFrame::Box</enum>
21
+ </property>
22
+ <layout class="QVBoxLayout" name="verticalLayout">
23
+ <property name="spacing">
24
+ <number>6</number>
25
+ </property>
26
+ <property name="leftMargin">
27
+ <number>6</number>
28
+ </property>
29
+ <property name="topMargin">
30
+ <number>6</number>
31
+ </property>
32
+ <property name="rightMargin">
33
+ <number>6</number>
34
+ </property>
35
+ <property name="bottomMargin">
36
+ <number>6</number>
37
+ </property>
38
+ <item>
39
+ <widget class="QWidget" name="widgetRecord" native="true">
40
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
41
+ <property name="spacing">
42
+ <number>2</number>
43
+ </property>
44
+ <property name="leftMargin">
45
+ <number>0</number>
46
+ </property>
47
+ <property name="topMargin">
48
+ <number>0</number>
49
+ </property>
50
+ <property name="rightMargin">
51
+ <number>6</number>
52
+ </property>
53
+ <property name="bottomMargin">
54
+ <number>0</number>
55
+ </property>
56
+ <item>
57
+ <widget class="QPushButton" name="recordButton">
58
+ <property name="statusTip">
59
+ <string>Record video</string>
60
+ </property>
61
+ <property name="text">
62
+ <string>&amp;Record</string>
63
+ </property>
64
+ <property name="icon">
65
+ <iconset resource="icons.qrc">
66
+ <normaloff>:/icons/icons/media-record.svg</normaloff>:/icons/icons/media-record.svg</iconset>
67
+ </property>
68
+ <property name="shortcut">
69
+ <string>R</string>
70
+ </property>
71
+ </widget>
72
+ </item>
73
+ <item>
74
+ <widget class="QPushButton" name="stopButton">
75
+ <property name="statusTip">
76
+ <string>Stop recording</string>
77
+ </property>
78
+ <property name="text">
79
+ <string>&amp;Stop</string>
80
+ </property>
81
+ <property name="icon">
82
+ <iconset resource="icons.qrc">
83
+ <normaloff>:/icons/icons/media-playback-stop.svg</normaloff>:/icons/icons/media-playback-stop.svg</iconset>
84
+ </property>
85
+ <property name="shortcut">
86
+ <string>S</string>
87
+ </property>
88
+ </widget>
89
+ </item>
90
+ <item>
91
+ <widget class="QLCDNumber" name="frameNumber">
92
+ <property name="segmentStyle">
93
+ <enum>QLCDNumber::Flat</enum>
94
+ </property>
95
+ </widget>
96
+ </item>
97
+ </layout>
98
+ </widget>
99
+ </item>
100
+ <item>
101
+ <widget class="QWidget" name="widgetSaveFile" native="true">
102
+ <layout class="QHBoxLayout" name="horizontalLayout_3">
103
+ <property name="spacing">
104
+ <number>6</number>
105
+ </property>
106
+ <property name="leftMargin">
107
+ <number>6</number>
108
+ </property>
109
+ <property name="topMargin">
110
+ <number>0</number>
111
+ </property>
112
+ <property name="rightMargin">
113
+ <number>6</number>
114
+ </property>
115
+ <property name="bottomMargin">
116
+ <number>0</number>
117
+ </property>
118
+ <item>
119
+ <widget class="QLabel" name="saveLabel">
120
+ <property name="text">
121
+ <string>Save As</string>
122
+ </property>
123
+ <property name="buddy">
124
+ <cstring>saveEdit</cstring>
125
+ </property>
126
+ </widget>
127
+ </item>
128
+ <item>
129
+ <widget class="QLineEdit" name="saveEdit">
130
+ <property name="statusTip">
131
+ <string>Video file name</string>
132
+ </property>
133
+ <property name="readOnly">
134
+ <bool>true</bool>
135
+ </property>
136
+ </widget>
137
+ </item>
138
+ </layout>
139
+ </widget>
140
+ </item>
141
+ <item>
142
+ <widget class="QWidget" name="widgetPlay" native="true">
143
+ <layout class="QHBoxLayout" name="horizontalLayout_4">
144
+ <property name="spacing">
145
+ <number>2</number>
146
+ </property>
147
+ <property name="leftMargin">
148
+ <number>0</number>
149
+ </property>
150
+ <property name="topMargin">
151
+ <number>1</number>
152
+ </property>
153
+ <property name="rightMargin">
154
+ <number>0</number>
155
+ </property>
156
+ <property name="bottomMargin">
157
+ <number>1</number>
158
+ </property>
159
+ <item>
160
+ <widget class="QPushButton" name="rewindButton">
161
+ <property name="statusTip">
162
+ <string>Rewind video file</string>
163
+ </property>
164
+ <property name="text">
165
+ <string>&amp;Rewind</string>
166
+ </property>
167
+ <property name="icon">
168
+ <iconset resource="icons.qrc">
169
+ <normaloff>:/icons/icons/media-skip-backward.svg</normaloff>:/icons/icons/media-skip-backward.svg</iconset>
170
+ </property>
171
+ </widget>
172
+ </item>
173
+ <item>
174
+ <widget class="QPushButton" name="pauseButton">
175
+ <property name="statusTip">
176
+ <string>Pause video playback</string>
177
+ </property>
178
+ <property name="text">
179
+ <string>&amp;Pause</string>
180
+ </property>
181
+ <property name="icon">
182
+ <iconset resource="icons.qrc">
183
+ <normaloff>:/icons/icons/media-playback-pause.svg</normaloff>:/icons/icons/media-playback-pause.svg</iconset>
184
+ </property>
185
+ </widget>
186
+ </item>
187
+ <item>
188
+ <widget class="QPushButton" name="playButton">
189
+ <property name="statusTip">
190
+ <string>Play video file</string>
191
+ </property>
192
+ <property name="text">
193
+ <string>P&amp;lay</string>
194
+ </property>
195
+ <property name="icon">
196
+ <iconset resource="icons.qrc">
197
+ <normaloff>:/icons/icons/media-playback-start.svg</normaloff>:/icons/icons/media-playback-start.svg</iconset>
198
+ </property>
199
+ </widget>
200
+ </item>
201
+ </layout>
202
+ </widget>
203
+ </item>
204
+ <item>
205
+ <widget class="QWidget" name="widgetPlayFile" native="true">
206
+ <layout class="QHBoxLayout" name="horizontalLayout_5">
207
+ <property name="spacing">
208
+ <number>6</number>
209
+ </property>
210
+ <property name="leftMargin">
211
+ <number>6</number>
212
+ </property>
213
+ <property name="topMargin">
214
+ <number>0</number>
215
+ </property>
216
+ <property name="rightMargin">
217
+ <number>6</number>
218
+ </property>
219
+ <property name="bottomMargin">
220
+ <number>0</number>
221
+ </property>
222
+ <item>
223
+ <widget class="QLabel" name="labelPlayFile">
224
+ <property name="text">
225
+ <string>Play</string>
226
+ </property>
227
+ <property name="buddy">
228
+ <cstring>playEdit</cstring>
229
+ </property>
230
+ </widget>
231
+ </item>
232
+ <item>
233
+ <widget class="QLineEdit" name="playEdit">
234
+ <property name="statusTip">
235
+ <string>Video file</string>
236
+ </property>
237
+ <property name="readOnly">
238
+ <bool>true</bool>
239
+ </property>
240
+ </widget>
241
+ </item>
242
+ </layout>
243
+ </widget>
244
+ </item>
245
+ <item>
246
+ <widget class="QWidget" name="widgetFrames" native="true">
247
+ <layout class="QHBoxLayout" name="horizontalLayout">
248
+ <property name="spacing">
249
+ <number>6</number>
250
+ </property>
251
+ <property name="leftMargin">
252
+ <number>6</number>
253
+ </property>
254
+ <property name="topMargin">
255
+ <number>4</number>
256
+ </property>
257
+ <property name="rightMargin">
258
+ <number>6</number>
259
+ </property>
260
+ <property name="bottomMargin">
261
+ <number>4</number>
262
+ </property>
263
+ <item>
264
+ <widget class="QLabel" name="labelNFrames">
265
+ <property name="text">
266
+ <string>Duration</string>
267
+ </property>
268
+ <property name="buddy">
269
+ <cstring>nframes</cstring>
270
+ </property>
271
+ </widget>
272
+ </item>
273
+ <item>
274
+ <widget class="QSpinBox" name="nframes">
275
+ <property name="toolTip">
276
+ <string>number of frames to record</string>
277
+ </property>
278
+ <property name="alignment">
279
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
280
+ </property>
281
+ <property name="minimum">
282
+ <number>10</number>
283
+ </property>
284
+ <property name="maximum">
285
+ <number>99000</number>
286
+ </property>
287
+ <property name="singleStep">
288
+ <number>10</number>
289
+ </property>
290
+ <property name="value">
291
+ <number>10000</number>
292
+ </property>
293
+ </widget>
294
+ </item>
295
+ <item>
296
+ <widget class="QLabel" name="labelInterval">
297
+ <property name="text">
298
+ <string>Interval</string>
299
+ </property>
300
+ <property name="buddy">
301
+ <cstring>nskip</cstring>
302
+ </property>
303
+ </widget>
304
+ </item>
305
+ <item>
306
+ <widget class="QSpinBox" name="nskip">
307
+ <property name="toolTip">
308
+ <string>Record every Nth frame</string>
309
+ </property>
310
+ <property name="alignment">
311
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
312
+ </property>
313
+ <property name="minimum">
314
+ <number>1</number>
315
+ </property>
316
+ <property name="maximum">
317
+ <number>999</number>
318
+ </property>
319
+ </widget>
320
+ </item>
321
+ </layout>
322
+ </widget>
323
+ </item>
324
+ </layout>
325
+ </widget>
326
+ <resources>
327
+ <include location="icons.qrc"/>
328
+ </resources>
329
+ <connections/>
330
+ </ui>
@@ -1,3 +1,4 @@
1
+ '''Batch median-of-medians background estimator (remedian algorithm).'''
1
2
  from QVideo.filters._MedianBase import _MedianBase
2
3
  from QVideo.lib.videotypes import Image
3
4
  import numpy as np
@@ -1,3 +1,4 @@
1
+ '''Streaming median-of-medians background estimator (rolling remedian).'''
1
2
  from QVideo.filters._MedianBase import _MedianBase
2
3
  from QVideo.lib.videotypes import Image
3
4
  import numpy as np
@@ -1,3 +1,4 @@
1
+ '''Background-normalisation filters built on median background estimation.'''
1
2
  from QVideo.filters.Median import Median
2
3
  from QVideo.filters.MoMedian import MoMedian
3
4
  from QVideo.lib.videotypes import Image
@@ -1,3 +1,4 @@
1
+ '''Gaussian blur filter and companion Qt widget.'''
1
2
  from qtpy import QtCore, QtWidgets
2
3
  from pyqtgraph import SpinBox
3
4
  from QVideo.lib.QVideoFilter import VideoFilter, QVideoFilter
@@ -1,3 +1,4 @@
1
+ '''Canny edge-detection filter and companion Qt widget.'''
1
2
  from qtpy import QtCore, QtWidgets
2
3
  from pyqtgraph import SpinBox
3
4
  from QVideo.lib.QVideoFilter import VideoFilter, QVideoFilter
@@ -1,3 +1,4 @@
1
+ '''RGB color-channel selection filter and companion Qt widget.'''
1
2
  from qtpy import QtCore, QtWidgets
2
3
  from QVideo.lib.QVideoFilter import VideoFilter, QVideoFilter
3
4
  from QVideo.lib.videotypes import Image
@@ -1,3 +1,4 @@
1
+ '''Sample-and-hold background normalisation filter and companion Qt widget.'''
1
2
  from qtpy import QtCore, QtWidgets
2
3
  from QVideo.filters.Normalize import Normalize
3
4
  from QVideo.lib.QVideoFilter import QVideoFilter
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "QVideo"
7
- version = "3.6.2"
7
+ version = "3.6.4"
8
8
  description = "PyQt-based framework for integrating video cameras into research applications"
9
9
  readme = "README.md"
10
10
  license = { text = "GPL-3.0-or-later" }
@@ -72,6 +72,10 @@ packages = [
72
72
  "QVideo.overlays",
73
73
  ]
74
74
 
75
+ [tool.setuptools.package-data]
76
+ 'QVideo' = ['*.ui']
77
+ 'QVideo.dvr' = ['*.ui']
78
+
75
79
  [tool.setuptools.package-dir]
76
80
  "QVideo" = "."
77
81
  "QVideo.cameras" = "cameras"
@@ -0,0 +1,97 @@
1
+ '''Unit tests for demos.compositedemo.'''
2
+ import unittest
3
+ from unittest.mock import MagicMock, patch
4
+ from qtpy import QtCore, QtWidgets
5
+ import QVideo.overlays.trackpy as _trackpy_mod
6
+ from QVideo.QCamcorder import QCamcorder
7
+ from QVideo.cameras.Noise._tree import QNoiseTree
8
+ from QVideo.demos.compositedemo import CompositeDemo
9
+ from QVideo.overlays.trackpy import QTrackpyWidget, _TrackpyWorker
10
+
11
+
12
+ app = QtWidgets.QApplication.instance() or QtWidgets.QApplication([])
13
+
14
+
15
+ def make_demo():
16
+ with patch.object(_trackpy_mod, 'tp', MagicMock()), \
17
+ patch.object(_TrackpyWorker, 'moveToThread'), \
18
+ patch.object(QtCore.QThread, 'start'):
19
+ return CompositeDemo(QNoiseTree())
20
+
21
+
22
+ class TestCompositeDemoInit(unittest.TestCase):
23
+
24
+ def test_creates_successfully(self):
25
+ widget = make_demo()
26
+ self.assertIsInstance(widget, CompositeDemo)
27
+
28
+ def test_is_subclass_of_qcamcorder(self):
29
+ widget = make_demo()
30
+ self.assertIsInstance(widget, QCamcorder)
31
+
32
+ def test_trackpy_attribute_is_qtrackpywidget(self):
33
+ widget = make_demo()
34
+ self.assertIsInstance(widget.trackpy, QTrackpyWidget)
35
+
36
+ def test_trackpy_source_connected_to_camera_source(self):
37
+ tree = QNoiseTree()
38
+ with patch.object(_trackpy_mod, 'tp', MagicMock()), \
39
+ patch.object(_TrackpyWorker, 'moveToThread'), \
40
+ patch.object(QtCore.QThread, 'start'):
41
+ widget = CompositeDemo(tree)
42
+ self.assertIs(widget.trackpy.source, tree.source)
43
+
44
+ def test_composite_check_is_qcheckbox(self):
45
+ widget = make_demo()
46
+ self.assertIsInstance(widget._compositeCheck, QtWidgets.QCheckBox)
47
+
48
+ def test_composite_check_label(self):
49
+ widget = make_demo()
50
+ self.assertEqual(widget._compositeCheck.text(), 'Composite')
51
+
52
+ def test_controls_contains_trackpy_widget(self):
53
+ widget = make_demo()
54
+ layout = widget.controls.layout()
55
+ items = [layout.itemAt(i).widget() for i in range(layout.count())]
56
+ self.assertIn(widget.trackpy, items)
57
+
58
+ def test_controls_contains_composite_check(self):
59
+ widget = make_demo()
60
+ layout = widget.controls.layout()
61
+ items = [layout.itemAt(i).widget() for i in range(layout.count())]
62
+ self.assertIn(widget._compositeCheck, items)
63
+
64
+ def test_overlay_added_to_screen(self):
65
+ widget = make_demo()
66
+ self.assertIn(widget.trackpy.overlay, widget.screen._overlays)
67
+
68
+
69
+ class TestCompositeDemoToggle(unittest.TestCase):
70
+
71
+ def setUp(self):
72
+ self.widget = make_demo()
73
+
74
+ def test_composite_off_by_default(self):
75
+ self.assertFalse(self.widget._compositeCheck.isChecked())
76
+
77
+ def test_toggle_on_sets_screen_composite(self):
78
+ self.widget._onCompositeToggled(True)
79
+ self.assertTrue(self.widget.screen.composite)
80
+
81
+ def test_toggle_on_sets_dvr_source_to_screen(self):
82
+ self.widget._onCompositeToggled(True)
83
+ self.assertIs(self.widget.dvr.source, self.widget.screen)
84
+
85
+ def test_toggle_off_clears_screen_composite(self):
86
+ self.widget._onCompositeToggled(True)
87
+ self.widget._onCompositeToggled(False)
88
+ self.assertFalse(self.widget.screen.composite)
89
+
90
+ def test_toggle_off_restores_dvr_source_to_camera(self):
91
+ self.widget._onCompositeToggled(True)
92
+ self.widget._onCompositeToggled(False)
93
+ self.assertIs(self.widget.dvr.source, self.widget.source)
94
+
95
+
96
+ if __name__ == '__main__': # pragma: no cover
97
+ unittest.main()