MyCaffe  1.12.2.41
Deep learning software for Windows C# programmers.
MasterList.cs
1using MyCaffe.basecode;
3using System;
4using System.Collections.Generic;
5using System.Diagnostics;
6using System.Linq;
7using System.Text;
8using System.Threading;
9using System.Threading.Tasks;
10
11namespace MyCaffe.db.image
12{
16 public class MasterList : IDisposable
17 {
18 CryptoRandom m_random;
19 DatasetFactory m_factory;
20 SourceDescriptor m_src;
21 SimpleDatum[] m_rgImages = null;
22 RefreshManager m_refreshManager = null;
23 LoadSequence m_loadSequence = null;
24 List<WaitHandle> m_rgAbort = new List<WaitHandle>();
25 ManualResetEvent m_evtCancel = new ManualResetEvent(false);
26 ManualResetEvent m_evtDone = new ManualResetEvent(false);
27 ManualResetEvent m_evtRunning = new ManualResetEvent(false);
28 ManualResetEvent m_evtRefreshCancel = new ManualResetEvent(false);
29 ManualResetEvent m_evtRefreshRunning = new ManualResetEvent(false);
30 ManualResetEvent m_evtRefreshDone = new ManualResetEvent(false);
31 Thread m_dataLoadThread;
32 Thread m_dataRefreshThread;
33 SimpleDatum m_imgMean = null;
34 Log m_log = null;
35 int m_nLoadedCount = 0;
36 bool m_bSilent = false;
37 int m_nLoadCount = 0;
38 int m_nReplacementBatch = 100;
39 object m_syncObj = new object();
40
44 public event EventHandler<CalculateImageMeanArgs> OnCalculateImageMean;
45
55 public MasterList(CryptoRandom random, Log log, SourceDescriptor src, DatasetFactory factory, List<WaitHandle> rgAbort, int nMaxLoadCount = 0)
56 {
57 m_random = random;
58 m_log = log;
59 m_src = src;
60 m_factory = factory;
61
62 m_rgAbort.Add(m_evtCancel);
63 if (rgAbort.Count > 0)
64 m_rgAbort.AddRange(rgAbort);
65
66 m_imgMean = m_factory.LoadImageMean(m_src.ID);
67
68 m_nLoadCount = nMaxLoadCount;
69 if (m_nLoadCount == 0 || m_nLoadCount > m_src.ImageCount)
70 m_nLoadCount = m_src.ImageCount;
71
72 m_rgImages = new SimpleDatum[m_nLoadCount];
73 m_nLoadedCount = 0;
74
75 if (m_nLoadCount < m_src.ImageCount)
76 m_refreshManager = new RefreshManager(random, m_src, m_factory);
77 }
78
82 public void Dispose()
83 {
84 m_evtCancel.Set();
85 if (m_evtRunning.WaitOne(0))
86 m_evtDone.WaitOne();
87
88 m_evtRefreshCancel.Set();
89 if (m_evtRefreshRunning.WaitOne(0))
90 m_evtRefreshDone.WaitOne();
91 }
92
97 public void Verify(MasterIndexes idx)
98 {
99 if (idx.RawIndexes.Count != m_rgImages.Length)
100 throw new Exception("The index count should match the image count!");
101
102 List<int> rgObservedIdx = new List<int>();
103 for (int i = 0; i < m_rgImages.Length; i++)
104 {
105 if (rgObservedIdx.Contains(m_rgImages[i].Index))
106 throw new Exception("Duplicate image index found! Your dataset may be corrupt.");
107
108 if (idx.RawIndexes[i].Index != m_rgImages[i].Index)
109 throw new Exception("The image indexs do not match! You may need to re-index the image list.");
110
111 rgObservedIdx.Add(m_rgImages[i].Index);
112 }
113 }
114
119 {
120 get
121 {
122 if (m_refreshManager != null)
123 return true;
124
125 return false;
126 }
127 }
128
132 public bool IsFull
133 {
134 get
135 {
136 return (m_nLoadedCount == GetTotalCount()) ? true : false;
137 }
138 }
139
145 public bool Load(bool bSilent = false)
146 {
147 lock (m_syncObj)
148 {
149 if (m_evtRunning.WaitOne(0))
150 return false;
151
152 m_bSilent = bSilent;
153 Unload(false);
154
155 m_dataLoadThread = new Thread(new ThreadStart(dataLoadThread));
156 m_dataLoadThread.Priority = ThreadPriority.AboveNormal;
157 m_dataLoadThread.Start();
158 m_evtRunning.WaitOne(1000);
159
160 return true;
161 }
162 }
163
168 public void Unload(bool bReLoad)
169 {
170 lock (m_syncObj)
171 {
172 if (m_evtRunning.WaitOne(0))
173 {
174 m_evtCancel.Set();
175 m_evtDone.WaitOne();
176 }
177
178 m_evtCancel.Reset();
179 m_evtDone.Reset();
180 m_evtRunning.Reset();
181 m_rgImages = new SimpleDatum[m_nLoadCount];
182 m_nLoadedCount = 0;
183 GC.Collect();
184
185 StopRefresh();
186
187 m_loadSequence = new LoadSequence(m_random, m_rgImages.Length, m_src.ImageCount, m_refreshManager);
188 }
189
190 if (bReLoad)
191 Load();
192 }
193
199 public bool StartRefresh(double dfReplacementPct = 0.25)
200 {
201 lock (m_syncObj)
202 {
203 if (m_evtRefreshRunning.WaitOne(0))
204 return false;
205
206 if (m_rgImages.Length >= m_src.ImageCount)
207 return false;
208
209 int nMaxRefresh = (int)(m_nLoadCount * dfReplacementPct);
210 if (nMaxRefresh == 0)
211 nMaxRefresh = 1;
212
213 m_nReplacementBatch = nMaxRefresh;
214 m_evtRefreshCancel.Reset();
215 m_evtRefreshDone.Reset();
216 m_dataRefreshThread = new Thread(new ThreadStart(dataRefreshThread));
217 m_dataRefreshThread.Start();
218 m_evtRefreshRunning.WaitOne();
219
220 return true;
221 }
222 }
223
230 public bool WaitForRefreshToComplete(List<WaitHandle> rgAbort, int nWait)
231 {
232 if (!m_evtRefreshRunning.WaitOne(0))
233 return true;
234
235 List<WaitHandle> rgWait = new List<WaitHandle>();
236 rgWait.Add(m_evtRefreshDone);
237 rgWait.AddRange(rgAbort);
238
239 int nRes = WaitHandle.WaitAny(rgWait.ToArray(), nWait);
240 if (nRes == 0)
241 return true;
242
243 return false;
244 }
245
249 public bool IsRefreshDone
250 {
251 get
252 {
253 if (m_evtRefreshDone.WaitOne(0) || !m_evtRefreshRunning.WaitOne(0))
254 return true;
255
256 return false;
257 }
258 }
259
264 {
265 get
266 {
267 return m_evtRefreshRunning.WaitOne(0);
268 }
269 }
270
274 public void StopRefresh()
275 {
276 if (!m_evtRefreshRunning.WaitOne(0))
277 return;
278
279 m_evtRefreshCancel.Set();
280 m_evtRefreshDone.WaitOne();
281 }
282
288 public void SetImageMean(SimpleDatum d, bool bSave = false)
289 {
290 m_imgMean = d;
291
292 if (bSave)
293 m_factory.SaveImageMean(d, true);
294 }
295
300 public int GetTotalCount()
301 {
302 lock (m_syncObj)
303 {
304 return m_rgImages.Length;
305 }
306 }
307
312 public int GetLoadedCount()
313 {
314 return m_nLoadedCount;
315 }
316
324 public SimpleDatum GetImageMean(Log log, WaitHandle[] rgAbort, bool bQueryOnly)
325 {
326 if (m_imgMean != null || bQueryOnly)
327 return m_imgMean;
328
329 int nLoadedCount = GetLoadedCount();
330 int nTotalCount = GetTotalCount();
331
332 if (nLoadedCount < nTotalCount)
333 {
334 double dfPct = (double)nLoadedCount / (double)nTotalCount;
335
336 if (log != null)
337 log.WriteLine("WARNING: Cannot create the image mean until all images have loaded - the data is currently " + dfPct.ToString("P") + " loaded.");
338
339 return null;
340 }
341
342 if (OnCalculateImageMean != null)
343 {
344 CalculateImageMeanArgs args = new CalculateImageMeanArgs(m_rgImages);
345 OnCalculateImageMean(this, args);
346
347 if (args.Cancelled)
348 return null;
349
350 m_imgMean = args.ImageMean;
351 return m_imgMean;
352 }
353
354 RawImageMean imgMean = m_factory.GetRawImageMean();
355 if (m_imgMean != null)
356 {
357 m_imgMean = m_factory.LoadDatum(imgMean);
358 }
359 else
360 {
361 log.WriteLine("Calculating mean...");
362 m_imgMean = SimpleDatum.CalculateMean(log, m_rgImages, rgAbort);
363 m_factory.PutRawImageMean(m_imgMean, true);
364 }
365
366 m_imgMean.SetLabel(0);
367
368 return m_imgMean;
369 }
370
375 public List<DbItem> ReloadIndexing()
376 {
377 return m_rgImages.Select(p => new DbItem { id = p.ImageID, virtualid = p.VirtualID, index = p.Index, label = p.Label, boost = p.Boost, time = p.TimeStamp, desc = p.Description, originalsrcid = p.OriginalSourceID, active = true }).ToList();
378 }
379
384 public List<DbItem> ResetLabels()
385 {
386 if (!IsFull)
387 throw new Exception("Relabeling only supported on fully loaded data sets.");
388
389 foreach (SimpleDatum sd in m_rgImages)
390 {
391 if (sd != null)
392 sd.ResetLabel();
393 }
394
395 return ReloadIndexing();
396 }
397
403 public List<DbItem> Relabel(LabelMappingCollection col)
404 {
405 if (!IsFull)
406 throw new Exception("Relabeling only supported on fully loaded data sets.");
407
408 foreach (SimpleDatum sd in m_rgImages)
409 {
410 if (sd != null)
411 sd.SetLabel(col.MapLabelWithoutBoost(sd.OriginalLabel));
412 }
413
414 return ReloadIndexing();
415 }
416
421 public List<DbItem> ResetAllBoosts()
422 {
423 if (!IsFull)
424 throw new Exception("Relabeling only supported on fully loaded data sets.");
425
426 foreach (SimpleDatum sd in m_rgImages)
427 {
428 if (sd != null)
429 sd.ResetBoost();
430 }
431
432 return ReloadIndexing();
433 }
434
441 public int FindImageIndex(List<DbItem> rgItems, string strDesc)
442 {
443 List<int?> rgIdx = rgItems.Select(p => p.index).ToList();
444 List<SimpleDatum> rgSd;
445
446 lock (m_syncObj)
447 {
448 if (m_rgImages == null)
449 return -1;
450
451 rgSd = m_rgImages.Where(p => p != null && rgIdx.Contains(p.Index)).ToList();
452 }
453
454 if (rgSd.Count == 0)
455 return -1;
456
457 rgSd = rgSd.Where(p => p.Description == strDesc).ToList();
458 if (rgSd.Count == 0)
459 return -1;
460
461 return rgSd[0].Index;
462 }
463
469 public SimpleDatum FindImage(int nImageId)
470 {
471 List<SimpleDatum> rgSd;
472
473 lock (m_syncObj)
474 {
475 rgSd = m_rgImages.Where(p => p != null && p.ImageID == nImageId).ToList();
476 }
477
478 if (rgSd.Count == 0)
479 return null;
480
481 return rgSd[0];
482 }
483
484 private IEnumerable<SimpleDatum> getQuery(bool bSuperboostOnly, string strFilterVal = null, int? nBoostVal = null)
485 {
486 IEnumerable<SimpleDatum> iQuery = m_rgImages.Where(p => p != null);
487
488 if (bSuperboostOnly)
489 {
490 if (nBoostVal.HasValue)
491 {
492 int nVal = nBoostVal.Value;
493
494 if (nVal < 0)
495 {
496 nVal = Math.Abs(nVal);
497 iQuery = iQuery.Where(p => p.Boost == nVal);
498 }
499 else
500 {
501 iQuery = iQuery.Where(p => p.Boost >= nVal);
502 }
503 }
504 else
505 {
506 iQuery = iQuery.Where(p => p.Boost > 0);
507 }
508 }
509
510 if (!string.IsNullOrEmpty(strFilterVal))
511 iQuery = iQuery.Where(p => p.Description == strFilterVal);
512
513 return iQuery;
514 }
515
524 public SimpleDatum GetImage(int nIdx, bool bLoadDataCriteria, bool bLoadDebugData, DB_LOAD_METHOD loadMethod)
525 {
526 SimpleDatum sd = m_rgImages[nIdx];
527
528 if (sd == null)
529 {
530 if (m_refreshManager != null)
531 {
532 while (nIdx > 0 && m_rgImages[nIdx] == null)
533 {
534 nIdx--;
535 }
536
537 sd = m_rgImages[nIdx];
538
539 if (sd == null)
540 throw new Exception("No images should be null when using LoadLimit loading!");
541 }
542 else
543 {
544 if (!m_evtRunning.WaitOne(0) && (loadMethod != DB_LOAD_METHOD.LOAD_ON_DEMAND && loadMethod != DB_LOAD_METHOD.LOAD_ON_DEMAND_NOCACHE))
545 Load((loadMethod == DB_LOAD_METHOD.LOAD_ON_DEMAND_BACKGROUND) ? true : false);
546
547 sd = directLoadImage(nIdx);
548 if (sd == null)
549 throw new Exception("The image is still null yet should have loaded!");
550
551 if (loadMethod == DB_LOAD_METHOD.LOAD_ON_DEMAND)
552 m_rgImages[nIdx] = sd;
553 }
554 }
555
556 // Double check that the conditional data has loaded (if needed).
557 if (bLoadDataCriteria || bLoadDebugData)
558 m_factory.LoadRawData(sd, bLoadDataCriteria, bLoadDebugData);
559
560 return sd;
561 }
562
573 public int GetCount(QueryState state, string strFilterVal = null, int? nBoostVal = null, bool bBoostValIsExact = false)
574 {
575 List<int> rgIdx = state.GetIndexes(0, int.MaxValue, strFilterVal, nBoostVal, bBoostValIsExact);
576 return rgIdx.Count();
577 }
578
592 public List<SimpleDatum> GetImages(QueryState state, int nStartIdx, int nQueryCount = int.MaxValue, string strFilterVal = null, int? nBoostVal = null, bool bBoostValIsExact = false, bool bAttemptDirectLoad = false)
593 {
594 List<int> rgIdx = state.GetIndexes(nStartIdx, nQueryCount, strFilterVal, nBoostVal, bBoostValIsExact);
595 List<SimpleDatum> rgSd;
596
597 lock (m_syncObj)
598 {
599 rgSd = m_rgImages.Where(p => p != null && rgIdx.Contains(p.Index)).ToList();
600 }
601
602 if (bAttemptDirectLoad)
603 {
604 foreach (SimpleDatum sd in rgSd)
605 {
606 if (sd != null)
607 rgIdx.Remove(sd.Index);
608 }
609
610 for (int i = 0; i < rgIdx.Count; i++)
611 {
612 rgSd.Add(directLoadImage(rgIdx[i]));
613 }
614
615 rgSd = rgSd.OrderBy(p => p.Index).ToList();
616 }
617
618 return rgSd;
619 }
620
633 public List<SimpleDatum> GetImages(QueryState state, DateTime dtStart, int nQueryCount = int.MaxValue, string strFilterVal = null, int? nBoostVal = null, bool bBoostValIsExact = false)
634 {
635 List<int> rgIdx = state.GetIndexes(dtStart, nQueryCount, strFilterVal, nBoostVal, bBoostValIsExact);
636
637 lock (m_syncObj)
638 {
639 return m_rgImages.Where(p => p != null && rgIdx.Contains(p.Index)).ToList();
640 }
641 }
642
653 public List<SimpleDatum> GetImages(bool bSuperboostOnly, string strFilterVal, int? nBoostVal, int[] rgIdx)
654 {
655 lock (m_syncObj)
656 {
657 IEnumerable<SimpleDatum> iQuery = getQuery(bSuperboostOnly, strFilterVal, nBoostVal);
658
659 iQuery = iQuery.Where(p => p != null && rgIdx.Contains(p.Index));
660
661 return iQuery.ToList();
662 }
663 }
664
671 public bool WaitForLoadingToComplete(List<WaitHandle> rgAbort, int nWait = int.MaxValue)
672 {
673 int nLoadCount = GetLoadedCount();
674
675 lock (m_syncObj)
676 {
677 if (nLoadCount == 0 && !m_evtRunning.WaitOne(0))
678 return false;
679 }
680
681 List<WaitHandle> rgWait = new List<WaitHandle>();
682 rgWait.Add(m_evtDone);
683 rgWait.AddRange(rgAbort);
684
685 int nRes = WaitHandle.WaitAny(rgWait.ToArray(), nWait);
686 if (nRes == 0)
687 return true;
688
689 return false;
690 }
691
692 private int getBatchSize(SourceDescriptor src)
693 {
694 int nBatchSize = 20000;
695
696 int nImageSize = src.Height * src.Width * src.Channels;
697 if (nImageSize > 60000)
698 nBatchSize = 5000;
699 else if (nImageSize > 20000)
700 nBatchSize = 7500;
701 else if (nImageSize > 3000)
702 nBatchSize = 10000;
703
704 if (nBatchSize > m_nLoadCount)
705 nBatchSize = m_nLoadCount;
706
707 return nBatchSize;
708 }
709
715 private SimpleDatum directLoadImage(int nIdx)
716 {
717 return m_factory.LoadImageAt(nIdx);
718 }
719
723 private void dataLoadThread()
724 {
725 m_evtRunning.Set();
726 DatasetFactory factory = new DatasetFactory(m_factory);
727 int? nNextIdx = m_loadSequence.GetNext();
728 Stopwatch sw = new Stopwatch();
729
730 if (m_refreshManager != null)
731 m_refreshManager.Reset();
732
733 try
734 {
735 sw.Start();
736
737 List<int> rgIdxBatch = new List<int>();
738 int nBatchSize = getBatchSize(m_src);
739
740 if (m_nLoadedCount > 0)
741 throw new Exception("The loaded count is > 0!");
742
743 factory.Open(m_src);
744
745 m_log.WriteLine(m_src.Name + " loading " + m_loadSequence.Count.ToString("N0") + " items...", true);
746
747 while (nNextIdx.HasValue || rgIdxBatch.Count > 0)
748 {
749 if (nNextIdx.HasValue)
750 rgIdxBatch.Add(nNextIdx.Value);
751
752 if (rgIdxBatch.Count >= nBatchSize || !nNextIdx.HasValue)
753 {
754 List<RawImage> rgImg;
755
756 if (m_refreshManager == null)
757 rgImg = factory.GetRawImagesAt(rgIdxBatch[0], rgIdxBatch.Count);
758 else
759 rgImg = factory.GetRawImagesAt(rgIdxBatch, m_evtCancel);
760
761 if (rgImg == null)
762 break;
763
764 for (int j = 0; j < rgImg.Count; j++)
765 {
766 SimpleDatum sd = factory.LoadDatum(rgImg[j]);
767
768 if (m_refreshManager != null)
769 m_refreshManager.AddLoaded(sd);
770
771 m_rgImages[m_nLoadedCount] = sd;
772 m_nLoadedCount++;
773
774 if (sw.Elapsed.TotalMilliseconds > 1000)
775 {
776 if (m_log != null && !m_bSilent)
777 {
778 double dfPct = m_nLoadedCount / (double)m_rgImages.Length;
779 m_log.Progress = dfPct;
780 m_log.WriteLine("Loading '" + m_src.Name + "' at " + dfPct.ToString("P") + " (" + m_nLoadedCount.ToString("N0") + " of " + m_rgImages.Length.ToString("N0") + ")...", true);
781 }
782
783 int nWait = WaitHandle.WaitAny(m_rgAbort.ToArray(), 0);
784 if (nWait != WaitHandle.WaitTimeout)
785 return;
786
787 sw.Restart();
788 }
789 }
790
791 rgIdxBatch = new List<int>();
792 }
793
794 nNextIdx = m_loadSequence.GetNext();
795 }
796
797 if (rgIdxBatch.Count > 0)
798 m_log.FAIL("Not all images were loaded!");
799 }
800 finally
801 {
802 factory.Close();
803 factory.Dispose();
804 m_evtRunning.Reset();
805 m_evtDone.Set();
806 }
807 }
808
809 private void dataRefreshThread()
810 {
811 m_evtRefreshRunning.Set();
812 DatasetFactory factory = new DatasetFactory(m_factory);
813 Stopwatch sw = new Stopwatch();
814
815 try
816 {
817 sw.Start();
818
819 m_log.WriteLine("Starting refresh of " + m_nReplacementBatch.ToString("N0") + " items...", true);
820
821 List<Tuple<int, SimpleDatum>> rgReplace = new List<Tuple<int, SimpleDatum>>();
822 List<Tuple<int, DbItem>> rgItems = new List<Tuple<int, DbItem>>();
823 List<DbItem> rgDbItems = new List<DbItem>();
824
825 // Load the replacement set.
826 for (int i = 0; i < m_nReplacementBatch; i++)
827 {
828 int nIdx = m_random.Next(m_rgImages.Length);
829 int? nLabel = null;
830
831 if (m_rgImages[nIdx] != null)
832 nLabel = m_rgImages[nIdx].Label;
833
834 DbItem img = m_refreshManager.GetNextImageId(nLabel);
835 rgItems.Add(new Tuple<int, DbItem>(nIdx, img));
836 rgDbItems.Add(img);
837
838 if (sw.Elapsed.TotalMilliseconds > 1000)
839 {
840 if (m_evtRefreshCancel.WaitOne(0))
841 return;
842
843 sw.Restart();
844 }
845 }
846
847 // Get the Datums, ordered by ID.
848 List<SimpleDatum> rgImg = m_factory.GetImagesAt(rgDbItems, m_evtCancel);
849 if (rgImg == null)
850 return;
851
852 rgImg = rgImg.OrderBy(p => p.ImageID).ToList();
853 rgItems = rgItems.OrderBy(p => p.Item2.ID).ToList();
854
855 if (rgImg.Count != rgItems.Count)
856 {
857 List<Tuple<int, DbItem>> rgItems1 = new List<Tuple<int, DbItem>>();
858 int nIdx = 0;
859 for (int i = 0; i < rgImg.Count; i++)
860 {
861 while (nIdx < rgItems.Count && rgItems[nIdx].Item2.ID < rgImg[i].ImageID)
862 {
863 nIdx++;
864 }
865
866 if (rgItems[nIdx].Item2.ID == rgImg[i].ImageID)
867 {
868 rgItems1.Add(rgItems[nIdx]);
869 nIdx++;
870 }
871 }
872
873 rgItems = rgItems1;
874 }
875
876 for (int i = 0; i < rgItems.Count; i++)
877 {
878 rgReplace.Add(new Tuple<int, SimpleDatum>(rgItems[i].Item1, rgImg[i]));
879 }
880
881 lock (m_syncObj)
882 {
883 int nMismatchCount = 0;
884
885 for (int i = 0; i < rgReplace.Count; i++)
886 {
887 int nIdx = rgReplace[i].Item1;
888 if (m_rgImages[nIdx] != null && m_rgImages[nIdx].Label != rgReplace[i].Item2.Label)
889 nMismatchCount++;
890 else
891 m_rgImages[nIdx] = rgReplace[i].Item2;
892 }
893
894 if (nMismatchCount > 0)
895 m_log.WriteLine("WARNING: " + nMismatchCount.ToString("N0") + " label mismatches found!", true);
896 }
897 }
898 finally
899 {
900 m_evtRefreshRunning.Reset();
901 m_evtRefreshDone.Set();
902 }
903 }
904 }
905
906#pragma warning disable 1591
907
908 public class LoadSequence
909 {
910 List<int> m_rgLoadSequence = new List<int>();
911 Dictionary<int, Tuple<bool, bool>> m_rgLoadConditions = new Dictionary<int, Tuple<bool, bool>>();
912 Dictionary<int, AutoResetEvent> m_rgPending = new Dictionary<int, AutoResetEvent>();
913 object m_syncObj = new object();
914
915 public LoadSequence(CryptoRandom random, int nCount, int nImageCount, RefreshManager refresh)
916 {
917 // When using load limit (count < image count), load item indexes in such
918 // a way that balances the number of items per label.
919 if (nCount < nImageCount)
920 {
921 Dictionary<int, List<DbItem>> rgItemsByLabel = refresh.GetItemsByLabel();
922 List<int> rgLabel = rgItemsByLabel.Where(p => p.Value.Count > 0).Select(p => p.Key).ToList();
923
924 for (int i = 0; i < nCount; i++)
925 {
926 int nLabelIdx = random.Next(rgLabel.Count);
927 int nLabel = rgLabel[nLabelIdx];
928 List<DbItem> rgItems = rgItemsByLabel[nLabel];
929 int nItemIdx = random.Next(rgItems.Count);
930 DbItem item = rgItems[nItemIdx];
931
932 m_rgLoadSequence.Add(item.Index);
933
934 rgLabel.Remove(nLabel);
935 if (rgLabel.Count == 0)
936 rgLabel = rgItemsByLabel.Where(p => p.Value.Count > 0).Select(p => p.Key).ToList();
937 }
938
939 refresh.Reset();
940 }
941 // Otherwise just load all item indexes.
942 else
943 {
944 for (int i = 0; i < nCount; i++)
945 {
946 m_rgLoadSequence.Add(i);
947 }
948 }
949 }
950
951 public int Count
952 {
953 get { return m_rgLoadSequence.Count; }
954 }
955
956 public bool IsEmpty
957 {
958 get
959 {
960 lock (m_syncObj)
961 {
962 return (m_rgLoadSequence.Count == 0) ? true : false;
963 }
964 }
965 }
966
967 public void PreEmpt(int nIdx, bool bLoadDataCriteria, bool bLoadDebugData)
968 {
969 lock (m_syncObj)
970 {
971 m_rgLoadConditions.Add(nIdx, new Tuple<bool, bool>(bLoadDataCriteria, bLoadDebugData));
972 m_rgPending.Add(nIdx, new AutoResetEvent(false));
973 m_rgLoadSequence.Remove(nIdx);
974 m_rgLoadSequence.Insert(0, nIdx);
975 }
976 }
977
978 public void SetLoaded(int nIdx)
979 {
980 lock (m_syncObj)
981 {
982 m_rgLoadConditions.Remove(nIdx);
983
984 if (!m_rgPending.ContainsKey(nIdx))
985 return;
986
987 m_rgPending[nIdx].Set();
988 }
989 }
990
991 public bool WaitForLoad(int nIdx, int nWaitMs = 5000)
992 {
993 if (!m_rgPending.ContainsKey(nIdx))
994 return false;
995
996 bool bRes = m_rgPending[nIdx].WaitOne(nWaitMs);
997
998 lock (m_syncObj)
999 {
1000 m_rgPending.Remove(nIdx);
1001 }
1002
1003 return bRes;
1004 }
1005
1006 public int? GetNext()
1007 {
1008 lock (m_syncObj)
1009 {
1010 if (m_rgLoadSequence.Count == 0)
1011 return null;
1012
1013 int nIdx = m_rgLoadSequence[0];
1014 m_rgLoadSequence.RemoveAt(0);
1015
1016 return nIdx;
1017 }
1018 }
1019 }
1020
1021 public class RefreshManager
1022 {
1023 CryptoRandom m_random;
1024 List<DbItem> m_rgItems;
1025 Dictionary<int, List<DbItem>> m_rgItemsByLabel = null;
1026 Dictionary<int, List<int>> m_rgLoadedIdx = new Dictionary<int, List<int>>();
1027 Dictionary<int, List<int>> m_rgNotLoadedIdx = new Dictionary<int, List<int>>();
1028
1029 public RefreshManager(CryptoRandom random, SourceDescriptor src, DatasetFactory factory)
1030 {
1031 m_random = random;
1032 m_rgItems = factory.LoadImageIndexes(false, true);
1033 }
1034
1035 public Dictionary<int, List<DbItem>> GetItemsByLabel()
1036 {
1037 if (m_rgItemsByLabel == null)
1038 {
1039 m_rgItemsByLabel = new Dictionary<int, List<DbItem>>();
1040
1041 for (int i=0; i<m_rgItems.Count; i++)
1042 {
1043 DbItem item = m_rgItems[i];
1044 item.Tag = i;
1045
1046 if (!m_rgItemsByLabel.ContainsKey(item.Label))
1047 m_rgItemsByLabel.Add(item.Label, new List<DbItem>());
1048
1049 m_rgItemsByLabel[item.Label].Add(item);
1050 }
1051
1052 Reset();
1053 }
1054
1055 return m_rgItemsByLabel;
1056 }
1057
1058 public void Reset()
1059 {
1060 m_rgLoadedIdx = new Dictionary<int, List<int>>();
1061 m_rgNotLoadedIdx = new Dictionary<int, List<int>>();
1062
1063 foreach (KeyValuePair<int, List<DbItem>> kv in m_rgItemsByLabel)
1064 {
1065 m_rgNotLoadedIdx.Add(kv.Key, kv.Value.Select(p => (int)p.Tag).ToList());
1066 }
1067 }
1068
1069 public void AddLoaded(SimpleDatum sd)
1070 {
1071 if (!m_rgLoadedIdx.ContainsKey(sd.Label))
1072 m_rgLoadedIdx.Add(sd.Label, new List<int>());
1073
1074 DbItem item = m_rgItemsByLabel[sd.Label].Where(p => p.ID == sd.ImageID).First();
1075 m_rgLoadedIdx[sd.Label].Add((int)item.Tag);
1076
1077 m_rgNotLoadedIdx[sd.Label].Remove((int)item.Tag);
1078 }
1079
1080 public DbItem GetNextImageId(int? nLabel)
1081 {
1082 if (!nLabel.HasValue)
1083 {
1084 int nLabelIdx = m_random.Next(m_rgItemsByLabel.Count);
1085 nLabel = m_rgItemsByLabel.ElementAt(nLabelIdx).Key;
1086 }
1087
1088 if (!m_rgLoadedIdx.ContainsKey(nLabel.Value))
1089 m_rgLoadedIdx.Add(nLabel.Value, new List<int>());
1090
1091 List<int> rgLoadedIdx = m_rgLoadedIdx[nLabel.Value];
1092 List<int> rgNotLoadedIdx = m_rgNotLoadedIdx[nLabel.Value];
1093
1094 if (rgNotLoadedIdx.Count == 0)
1095 {
1096 rgLoadedIdx.Clear();
1097 rgNotLoadedIdx = m_rgItemsByLabel[nLabel.Value].Select(p => (int)p.Tag).ToList();
1098 }
1099
1100 int nIdx = m_random.Next(rgNotLoadedIdx.Count);
1101 int nMainIdx = rgNotLoadedIdx[nIdx];
1102 DbItem item = m_rgItems[nMainIdx];
1103
1104 rgNotLoadedIdx.RemoveAt(nIdx);
1105 rgLoadedIdx.Add(nMainIdx);
1106
1107 return item;
1108 }
1109 }
1110
1111#pragma warning restore 1591
1112}
The CalculateImageMeanArgs is passed as an argument to the MyCaffeImageDatabase::OnCalculateImageMean...
Definition: EventArgs.cs:136
SimpleDatum ImageMean
Get/set the image mean calculated from the Images.
Definition: EventArgs.cs:162
bool Cancelled
Get/set a flag indicating to cancel the operation.
Definition: EventArgs.cs:171
The CryptoRandom is a random number generator that can use either the standard .Net Random objec or t...
Definition: CryptoRandom.cs:14
int Next(int nMinVal, int nMaxVal, bool bMaxInclusive=true)
Returns a random int within the range
The LabelMappingCollection manages a collection of LabelMapping's.
Definition: LabelMapping.cs:15
The Log class provides general output in text form.
Definition: Log.cs:13
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
double Progress
Get/set the progress associated with the Log.
Definition: Log.cs:147
The SimpleDatum class holds a data input within host memory.
Definition: SimpleDatum.cs:161
int OriginalLabel
Get/set the original known label of the data.
static SimpleDatum CalculateMean(Log log, SimpleDatum[] rgImg, WaitHandle[] rgAbort)
Calculate the mean of an array of SimpleDatum and return the mean as a new SimpleDatum.
void ResetBoost()
Reset the boost to the original boost.
void SetLabel(int nLabel)
Sets the label.
SimpleDatum Add(SimpleDatum d)
Creates a new SimpleDatum and adds another SimpleDatum to it.
override string ToString()
Return a string representation of the SimpleDatum.
int Index
Returns the index of the SimpleDatum.
void ResetLabel()
Resets the label to the original label used when creating the SimpleDatum.
int ImageID
Returns the ID of the image in the database.
int Label
Return the known label of the data.
int ID
Get/set the database ID of the item.
string Name
Get/set the name of the item.
The SourceDescriptor class contains all information describing a data source.
int Height
Returns the height of each data item in the data source.
int Width
Returns the width of each data item in the data source.
int ImageCount
Returns the number of images within this data source.
int Channels
Returns the item colors - 1 channel = black/white, 3 channels = RGB color.
The DatasetFactory manages the connection to the Database object.
bool SaveImageMean(SimpleDatum sd, bool bUpdate, int nSrcId=0)
Save the SimpleDatum as a RawImageMean in the database.
RawImageMean GetRawImageMean()
Return the RawImageMean for the open data source.
List< SimpleDatum > GetImagesAt(List< int > rgImageIdx, ManualResetEvent evtCancel, int nSrcId=0, string strDescription=null)
Returns a list of SimpleDatum from the database for a data source.
SimpleDatum LoadImageAt(int nIdx, bool? bLoadDataCriteria=null, bool? bLoadDebugData=null, int nSrcId=0, int nPadW=0, int nPadH=0)
Load an image at a given index.
SimpleDatum LoadImageMean(int nSrcId, ConnectInfo ci=null)
Returns the image mean for a give data source.
void LoadRawData(SimpleDatum sd, bool bLoadDataCriteria, bool bLoadDebugData)
Load the data criteria and/or debug data.
int PutRawImageMean(SimpleDatum sd, bool bUpdate, ConnectInfo ci=null)
Save the SimpleDatum as a RawImageMean in the database for the open data source.
SimpleDatum LoadDatum(int nImageId, int nChannels, bool bDataIsReal, int nLabel, int nSrcId=0)
Loads a new SimpleDataum from a RawImage ID.
Specifies a database item used when querying boosted items.
Definition: Database.cs:5816
int VirtualID
Specifies the image VirtualID (if any).
Definition: Database.cs:5871
The MasterIndexes stores the indexes that define the index structure of the data source data.
List< DbItem > RawIndexes
Returns the raw indexes.
List< int > GetIndexes(int nStartIdx, int nQueryCount=int.MaxValue, string strFilterVal=null, int? nBoostVal=null, bool bBoostValIsExact=false)
Returns the indexes fitting the criteria.
The MasterList is responsible for loading and managing access to the master list of images for a data...
Definition: MasterList.cs:17
bool Load(bool bSilent=false)
Start loading the dataset.
Definition: MasterList.cs:145
List< DbItem > ResetAllBoosts()
Reset all image boosts.
Definition: MasterList.cs:421
int FindImageIndex(List< DbItem > rgItems, string strDesc)
Find the image index based by searching the rgItems for an image that contains the description specif...
Definition: MasterList.cs:441
SimpleDatum FindImage(int nImageId)
Find an image based on its image ID (e.g. the image ID in the database).
Definition: MasterList.cs:469
bool IsRefreshRunning
Returns true if the refresh is running, false otherwise.
Definition: MasterList.cs:264
SimpleDatum GetImageMean(Log log, WaitHandle[] rgAbort, bool bQueryOnly)
Returns the image mean for the ImageSet.
Definition: MasterList.cs:324
bool WaitForRefreshToComplete(List< WaitHandle > rgAbort, int nWait)
Wait for the refres to complete.
Definition: MasterList.cs:230
List< SimpleDatum > GetImages(bool bSuperboostOnly, string strFilterVal, int? nBoostVal, int[] rgIdx)
Returns the array of images in the image set, possibly filtered with the filtering parameters.
Definition: MasterList.cs:653
void StopRefresh()
Stop the refresh thread if running.
Definition: MasterList.cs:274
List< DbItem > ReloadIndexing()
Reload the image indexing.
Definition: MasterList.cs:375
bool? IsFull
Returns true when the master list is fully loaded, false otherwise.
Definition: MasterList.cs:133
MasterList(CryptoRandom random, Log log, SourceDescriptor src, DatasetFactory factory, List< WaitHandle > rgAbort, int nMaxLoadCount=0)
The constructor.
Definition: MasterList.cs:55
void Dispose()
Release all resources used.
Definition: MasterList.cs:82
bool WaitForLoadingToComplete(List< WaitHandle > rgAbort, int nWait=int.MaxValue)
Wait for the image loading to complete - this is used when performing LOAD_ALL.
Definition: MasterList.cs:671
EventHandler< CalculateImageMeanArgs > OnCalculateImageMean
The OnCalculateImageMean event fires when the ImageSet needs to calculate the image mean for the imag...
Definition: MasterList.cs:44
bool StartRefresh(double dfReplacementPct=0.25)
Start the refresh thread which will run if the number of images stored in memory is less than the tot...
Definition: MasterList.cs:199
int GetCount(QueryState state, string strFilterVal=null, int? nBoostVal=null, bool bBoostValIsExact=false)
Returns the number of images in the image set, optionally with super-boosted values only.
Definition: MasterList.cs:573
int GetTotalCount()
Return the total number of images whether loaded or not, in the data source.
Definition: MasterList.cs:300
List< DbItem > Relabel(LabelMappingCollection col)
Relabel the images based on the LabelMappingCollection.
Definition: MasterList.cs:403
void Unload(bool bReLoad)
Unload the data source images.
Definition: MasterList.cs:168
bool IsLoadLimitEnabled
Returns true when the database is loaded with LoadLimit > 0, false otherwise.
Definition: MasterList.cs:119
SimpleDatum GetImage(int nIdx, bool bLoadDataCriteria, bool bLoadDebugData, DB_LOAD_METHOD loadMethod)
Get the image with a specific image index.
Definition: MasterList.cs:524
void Verify(MasterIndexes idx)
Verify the loaded images against the master indexes.
Definition: MasterList.cs:97
List< DbItem > ResetLabels()
Reset the labels of all images to the original labels.
Definition: MasterList.cs:384
List< SimpleDatum > GetImages(QueryState state, int nStartIdx, int nQueryCount=int.MaxValue, string strFilterVal=null, int? nBoostVal=null, bool bBoostValIsExact=false, bool bAttemptDirectLoad=false)
Returns the array of images in the image set, possibly filtered with the filtering parameters.
Definition: MasterList.cs:592
bool IsRefreshDone
Returns true after the refresh completes.
Definition: MasterList.cs:250
void SetImageMean(SimpleDatum d, bool bSave=false)
Set the image mean.
Definition: MasterList.cs:288
int GetLoadedCount()
Return the currently loaded images in the data source.
Definition: MasterList.cs:312
List< SimpleDatum > GetImages(QueryState state, DateTime dtStart, int nQueryCount=int.MaxValue, string strFilterVal=null, int? nBoostVal=null, bool bBoostValIsExact=false)
Returns the array of images in the image set, possibly filtered with the filtering parameters.
Definition: MasterList.cs:633
Initially the QueryState is copied from the MasterIndexes and during each query is altered by removin...
Definition: QueryState.cs:19
The descriptors namespace contains all descriptor used to describe various items stored within the da...
The MyCaffe.basecode contains all generic types used throughout MyCaffe.
Definition: Annotation.cs:12
DB_LOAD_METHOD
Defines how to laod the items into the in-memory database.
Definition: Interfaces.cs:154
The MyCaffe.db.image namespace contains all image database related classes.
Definition: Database.cs:18
The MyCaffe namespace contains the main body of MyCaffe code that closesly tracks the C++ Caffe open-...
Definition: Annotation.cs:12