MyCaffe  1.12.2.41
Deep learning software for Windows C# programmers.
VideoDataLayer.cs
1using System;
2using System.Collections.Generic;
3using System.Diagnostics;
4using System.Linq;
5using System.Text;
6using System.Threading.Tasks;
7using MyCaffe.basecode;
8using MyCaffe.common;
9using MyCaffe.data;
10using MyCaffe.db.image;
11using MyCaffe.param;
12using MyCaffe.param.ssd;
13using WebCam;
14using DirectX.Capture;
15using System.Windows.Forms;
16using System.Drawing;
17using System.Threading;
18using System.IO;
19
23namespace MyCaffe.layers.ssd
24{
35 {
36 VideoDataParameter.VideoType m_videoType;
37 object m_objSync = new object();
38 WebCam.WebCam m_webcam = null;
39 Bitmap m_bmpSnapshot = null;
40 AutoResetEvent m_evtSnapshotReady = new AutoResetEvent(false);
41 Filter m_filter = null;
42 int m_nSkipFrames;
43 int m_nVideoWidth;
44 int m_nVideoHeight;
45 List<int> m_rgTopShape;
49 protected Stopwatch m_swTimerBatch;
53 protected Stopwatch m_swTimerTransaction;
57 protected double m_dfReadTime;
61 protected double m_dfTransTime;
62 private T[] m_rgTopData = null;
63 private long m_lDuration = 0;
64
74 : base(cuda, log, p, db, evtCancel)
75 {
76 m_type = LayerParameter.LayerType.VIDEO_DATA;
77
79 {
80 m_swTimerBatch = new Stopwatch();
81 m_swTimerTransaction = new Stopwatch();
82 }
83 }
84
86 protected override void dispose()
87 {
88 base.dispose();
89
90 lock (m_objSync)
91 {
92 if (m_webcam != null)
93 {
94 m_webcam.Close();
95 m_webcam.Dispose();
96 m_webcam = null;
97 m_filter = null;
98 }
99 }
100 }
101
105 public override int ExactNumBottomBlobs
106 {
107 get { return 0; }
108 }
109
113 public override int MinTopBlobs
114 {
115 get { return 1; }
116 }
117
123 protected override void DataLayerSetUp(BlobCollection<T> colBottom, BlobCollection<T> colTop)
124 {
125 Bitmap bmp = null;
126
127 int nBatchSize = (int)m_param.data_param.batch_size;
128 m_videoType = m_param.video_data_param.video_type;
129 m_nSkipFrames = (int)m_param.video_data_param.skip_frames;
130 m_nVideoWidth = (int)m_param.video_data_param.video_width;
131 m_nVideoHeight = (int)m_param.video_data_param.video_height;
132
133 // Read an image and use it to initialize the top blob.
134 if (m_videoType == VideoDataParameter.VideoType.WEBCAM)
135 {
136 m_webcam = new WebCam.WebCam();
137 m_webcam.OnSnapshot += m_webcam_OnSnapshot;
138
139 // Default 'source' is a Video File.
140 if (m_webcam.VideoInputDevices.Count == 0)
141 m_log.FAIL("Could not find a web-cam!");
142
143 if (m_param.video_data_param.device_id >= m_webcam.VideoInputDevices.Count)
144 m_log.FAIL("The video device_id is greater than the number of web cam devices detected (" + m_webcam.VideoInputDevices.Count.ToString() + ").");
145
146 m_filter = m_webcam.VideoInputDevices[m_param.video_data_param.device_id];
147 m_log.WriteLine("Using web-cam '" + m_filter.Name + "' for video input.");
148
149 m_webcam.Open(m_filter, null, null);
150 m_webcam.GetImage();
151 if (!m_evtSnapshotReady.WaitOne(1000))
152 m_log.FAIL("Failed to get a web-cam snapshot!");
153
154 bmp = m_bmpSnapshot;
155 }
156 else if (m_videoType == VideoDataParameter.VideoType.VIDEO)
157 {
158 m_webcam = new WebCam.WebCam();
159 m_webcam.OnSnapshot += m_webcam_OnSnapshot;
160
161 if (!File.Exists(m_param.video_data_param.video_file))
162 m_log.FAIL("The video file '" + m_param.video_data_param.video_file + "' does not exist!");
163
164 m_log.WriteLine("Using video source '" + m_param.video_data_param.video_file + "' for video input.");
165
166 m_lDuration = m_webcam.Open(null, null, m_param.video_data_param.video_file);
167 m_webcam.GetImage();
168 if (!m_evtSnapshotReady.WaitOne(1000))
169 m_log.FAIL("Failed to get a video snapshot!");
170
171 bmp = m_bmpSnapshot;
172 }
173 else
174 {
175 m_log.FAIL("Unknown video type!");
176 }
177
178 m_log.CHECK(bmp != null, "Could not load an image!");
179
180 // Resize the image if needed.
181 if (bmp.Width != m_nVideoWidth || bmp.Height != m_nVideoHeight)
182 {
183 Bitmap bmpNew = ImageTools.ResizeImage(bmp, m_nVideoWidth, m_nVideoHeight);
184 bmp.Dispose();
185 bmp = bmpNew;
186 }
187
188 // Use data_transformer to infer the expected blob shape from a bitmap.
189 m_rgTopShape = m_transformer.InferBlobShape(3, bmp.Width, bmp.Height);
190 m_rgTopShape[0] = nBatchSize;
191 colTop[0].Reshape(m_rgTopShape);
192
193 for (int i = 0; i < m_rgPrefetch.Length; i++)
194 {
195 m_rgPrefetch[i].Data.Reshape(m_rgTopShape);
196 }
197
198 m_log.WriteLine("Output data size: " + colTop[0].shape_string);
199
200 // Label.
201 if (m_bOutputLabels)
202 {
203 List<int> rgLabelShape = MyCaffe.basecode.Utility.Create<int>(1, nBatchSize);
204 colTop[1].Reshape(rgLabelShape);
205
206 for (int i = 0; i < m_rgPrefetch.Length; i++)
207 {
208 m_rgPrefetch[i].Label.Reshape(rgLabelShape);
209 }
210 }
211 }
212
213 private void m_webcam_OnSnapshot(object sender, ImageArgs e)
214 {
215 if (m_bmpSnapshot != null)
216 m_bmpSnapshot.Dispose();
217
218 m_bmpSnapshot = e.Image;
219 m_evtSnapshotReady.Set();
220 }
221
226 protected override void load_batch(Batch<T> batch)
227 {
228 m_log.CHECK(batch.Data.count() > 0, "There is no space allocated for data!");
229 int nBatchSize = (int)m_param.data_param.batch_size;
230
231 // Reshape batch according to the batch size.
232 m_rgTopShape[0] = nBatchSize;
233 batch.Data.Reshape(m_rgTopShape);
234
235 T[] rgTopLabel = null;
236 if (m_bOutputLabels)
237 rgTopLabel = batch.Label.mutable_cpu_data;
238
240 {
241 m_swTimerBatch.Restart();
242 m_dfReadTime = 0;
243 m_dfTransTime = 0;
244 }
245
246 int nSkipFrames = m_nSkipFrames;
247 int nDim = 0;
248 Bitmap bmp = null;
249
250 for (int i = 0; i < nBatchSize; i++)
251 {
253 m_swTimerTransaction.Restart();
254
255 lock (m_objSync)
256 {
257 if (m_videoType == VideoDataParameter.VideoType.WEBCAM)
258 {
259 if (m_webcam == null)
260 return;
261
262 m_webcam.GetImage();
263 if (!m_evtSnapshotReady.WaitOne(1000))
264 m_log.FAIL("Failed to get web-cam snapshot!");
265
266 bmp = m_bmpSnapshot;
267 }
268 else if (m_videoType == VideoDataParameter.VideoType.VIDEO)
269 {
270 if (m_webcam == null)
271 return;
272
273 if (nSkipFrames > 0)
274 nSkipFrames--;
275
276 if (nSkipFrames > 0)
277 m_webcam.Step(nSkipFrames);
278
279 m_webcam.GetImage();
280
281 if (!m_evtSnapshotReady.WaitOne(1000))
282 m_log.FAIL("Failed to get video file snapshot!");
283
284 if (m_webcam.IsAtEnd)
285 m_webcam.SetPosition(0);
286
287 bmp = m_bmpSnapshot;
288 }
289 else
290 {
291 m_log.FAIL("Unknown video type!");
292 }
293
294 m_log.CHECK(bmp != null, "Could not load image!");
295
296 // Resize the image if needed.
297 if (bmp.Width != m_nVideoWidth || bmp.Height != m_nVideoHeight)
298 {
299 Bitmap bmpNew = ImageTools.ResizeImage(bmp, m_nVideoWidth, m_nVideoHeight);
300 bmp.Dispose();
301 bmp = bmpNew;
302 }
303
305 {
306 m_dfReadTime += m_swTimerTransaction.Elapsed.TotalMilliseconds;
307 m_swTimerTransaction.Restart();
308 }
309
310 SimpleDatum datum = null;
311
312 if (i == 0)
313 {
314 datum = ImageData.GetImageDataD(bmp, batch.Data.channels, false, 0);
315
316 // Reshape according to the first datum of each batch
317 // on single input batches allows for inputs of varying dimension.
318 // Use data trabnsformer to infer the expected blob shape for datum.
319 List<int> rgTopShape = m_transformer.InferBlobShape(datum);
320
321 // Reshape batch according to the batch size.
322 rgTopShape[0] = nBatchSize;
323 batch.Data.Reshape(rgTopShape);
324
325 nDim = 1;
326 for (int k = 1; k < rgTopShape.Count; k++)
327 {
328 nDim *= rgTopShape[k];
329 }
330
331 int nTopLen = nDim * nBatchSize;
332 if (m_rgTopData == null || m_rgTopData.Length != nTopLen)
333 m_rgTopData = new T[nTopLen];
334 }
335
336 nSkipFrames = m_nSkipFrames;
337
338 if (datum == null)
339 datum = ImageData.GetImageDataD(bmp, batch.Data.channels, false, 0);
340
341 // Apply transformations (mirror, crop...) to the image.
342 T[] rgTrans = m_transformer.Transform(datum);
343 Array.Copy(rgTrans, 0, m_rgTopData, nDim * i, nDim);
344
345 // Copy label.
346 if (m_bOutputLabels)
347 rgTopLabel[i] = (T)Convert.ChangeType(datum.Label, typeof(T));
348
350 m_dfTransTime += m_swTimerTransaction.Elapsed.TotalMilliseconds;
351 }
352 }
353
354 batch.Data.SetCPUData(m_rgTopData);
355
356 if (m_bOutputLabels)
357 batch.Label.SetCPUData(rgTopLabel);
358
360 {
361 m_swTimerBatch.Stop();
363 m_log.WriteLine("Prefetch batch: " + m_swTimerBatch.ElapsedMilliseconds.ToString() + " ms.", true);
364 m_log.WriteLine(" Read time: " + m_dfReadTime.ToString() + " ms.", true);
365 m_log.WriteLine("Transform time: " + m_dfTransTime.ToString() + " ms.", true);
366 }
367 }
368 }
369}
The CancelEvent provides an extension to the manual cancel event that allows for overriding the manua...
Definition: CancelEvent.cs:17
The ImageData class is a helper class used to convert between Datum, other raw data,...
Definition: ImageData.cs:14
static Datum GetImageDataD(Bitmap bmp, int nChannels, bool bDataIsReal, int nLabel, bool bUseLockBitmap=true, int[] rgFocusMap=null)
The GetImageDataD function converts a Bitmap into a Datum using the double type for real data.
Definition: ImageData.cs:44
The ImageTools class is a helper class used to manipulate image data.
Definition: ImageTools.cs:16
static Bitmap ResizeImage(Image image, int width, int height)
Resize the image to the specified width and height.
Definition: ImageTools.cs:39
The Log class provides general output in text form.
Definition: Log.cs:13
void CHECK(bool b, string str)
Test a flag for true.
Definition: Log.cs:227
void WriteLine(string str, bool bOverrideEnabled=false, bool bHeader=false, bool bError=false, bool bDisable=false)
Write a line of output.
Definition: Log.cs:80
void FAIL(string str)
Causes a failure which throws an exception with the desciptive text.
Definition: Log.cs:394
The SimpleDatum class holds a data input within host memory.
Definition: SimpleDatum.cs:161
int Label
Return the known label of the data.
The Utility class provides general utility funtions.
Definition: Utility.cs:35
static List< int > Create(int nCount, int nStart, int nInc)
Create a new List and fill it with values starting with start and incrementing by inc.
Definition: Utility.cs:721
The BlobCollection contains a list of Blobs.
void Reshape(int[] rgShape)
Reshapes all blobs in the collection to the given shape.
The CudaDnn object is the main interface to the Low-Level Cuda C++ DLL.
Definition: CudaDnn.cs:969
bool m_bOutputLabels
Specifies whether or not the Layer should output labels.
DataTransformer< T > m_transformer
Specifies the DataTransformer used to transform each data item as it loaded.
The BasePrefetchingDataLayer is the base class for data Layers that pre-fetch data before feeding the...
Batch< T >[] m_rgPrefetch
Specifies the pre-fetch cache.
The Batch contains both the data and label Blobs of the batch.
Blob< T > Label
Returns the label Blob of the batch.
Blob< T > Data
Returns the data Blob of the batch.
Log m_log
Specifies the Log for output.
Definition: Layer.cs:43
LayerParameter m_param
Specifies the LayerParameter describing the Layer.
Definition: Layer.cs:47
LayerParameter.LayerType m_type
Specifies the Layer type.
Definition: Layer.cs:35
The VideoDataLayer provides data to the Net from a WebCam or Video file. This layer is initialized wi...
override void load_batch(Batch< T > batch)
Load a batch of data in the background (this is run on an internal thread within the BasePrefetchingD...
override void DataLayerSetUp(BlobCollection< T > colBottom, BlobCollection< T > colTop)
Setup the DataLayer by starting up the pre-fetching.
override void dispose()
Releases all GPU and host resources used by the Layer.
VideoDataLayer(CudaDnn< T > cuda, Log log, LayerParameter p, IXDatabaseBase db, CancelEvent evtCancel)
The VideoDataLayer constructor.
Stopwatch m_swTimerBatch
Specifies a first timer used to calcualte the batch time.
override int ExactNumBottomBlobs
No bottom blobs are used by this layer.
double m_dfTransTime
Specifies the transaction time.
double m_dfReadTime
Specifies the read time.
Stopwatch m_swTimerTransaction
Specfies a second timer used to calculate the transaction time.
override int MinTopBlobs
Specifies the minimum number of required top (output) Blobs: data
virtual uint batch_size
Specifies the batch size.
bool display_timing
(optional, default = false) Specifies whether or not to display the timing of each image read.
Specifies the base parameter for all layers.
DataParameter data_param
Returns the parameter set when initialized with LayerType.DATA
VideoDataParameter video_data_param
Returns the parameter set when initialized with LayerType.VIDEO_DATA
LayerType
Specifies the layer type.
Specifies the parameters for the VideoDataLayer.
uint video_width
Optionally, specifies the video width (default = 400).
uint skip_frames
Optionally, specifies the number of frames to be skipped before processing a frame (default = 0).
string video_file
Specifies the video file when using the VIDEO type.
int device_id
Specifies the device ID (default = 0).
uint video_height
Optionally, specifies the video height (default = 300).
VideoType video_type
Specifies the video type (default = WEBCAM).
The IXDatabaseBase interface defines the general interface to the in-memory database.
Definition: Interfaces.cs:444
The MyCaffe.basecode contains all generic types used throughout MyCaffe.
Definition: Annotation.cs:12
The MyCaffe.common namespace contains common MyCaffe classes.
Definition: BatchInput.cs:8
The MyCaffe.data namespace contains dataset creators used to create common testing datasets such as M...
Definition: BinaryFile.cs:16
The MyCaffe.db.image namespace contains all image database related classes.
Definition: Database.cs:18
The MyCaffe.layers.ssd namespace contains all Single-Shot MultiBox (SSD) related layers.
Definition: LayerFactory.cs:19
The MyCaffe.param.ssd namespace contains all SSD related parameter objects that correspond to the nat...
The MyCaffe.param namespace contains parameters used to create models.
The MyCaffe namespace contains the main body of MyCaffe code that closesly tracks the C++ Caffe open-...
Definition: Annotation.cs:12