2using System.Collections.Generic;
27 int m_nBackgroundLabelId;
28 float m_fOverlapThreshold;
29 bool m_bEvaluateDifficultGt;
30 List<SizeF> m_rgSizes =
new List<SizeF>();
32 bool m_bUseNormalizedBbox;
53 if (m_bboxUtil !=
null)
90 m_log.
CHECK_GT(m_fOverlapThreshold, 0.0f,
"The overlap_threshold must be non-negative.");
98 string strLine = sr.ReadLine();
100 while (strLine !=
null)
102 string[] rgstr = strLine.Split(
' ',
',');
103 if (rgstr.Length == 3 || rgstr.Length == 4)
105 int nNameIdx = (rgstr.Length == 4) ? 1 : 0;
106 string strName = rgstr[nNameIdx].Trim(
',');
107 int nHeight =
int.Parse(rgstr[nNameIdx + 1].Trim(
','));
108 int nWidth =
int.Parse(rgstr[nNameIdx + 2].Trim(
','));
110 m_rgSizes.Add(
new SizeF(nWidth, nHeight));
113 strLine = sr.ReadLine();
121 m_bUseNormalizedBbox = (m_rgSizes.Count == 0) ?
true :
false;
134 m_log.
CHECK_LE(m_nCount, m_rgSizes.Count,
"The count must be less than or equal to the number of Sizes.");
135 m_log.
CHECK_EQ(colBottom[0].num, 1,
"The bottom[0].num must = 1.");
136 m_log.
CHECK_EQ(colBottom[0].channels, 1,
"The bottom[0].channels must = 1.");
137 m_log.
CHECK_EQ(colBottom[0].width, 7,
"The bottom[0].width must = 7.");
138 m_log.
CHECK_EQ(colBottom[1].num, 1,
"The bottom[1].num must = 1.");
139 m_log.
CHECK_EQ(colBottom[1].channels, 1,
"The bottom[1].channels must = 1.");
140 m_log.
CHECK_EQ(colBottom[1].width, 8,
"The bottom[1].width must = 8.");
144 int nNumPosClasses = (m_nBackgroundLabelId == -1) ? m_nNumClasses : m_nNumClasses - 1;
145 int nNumValidDet = 0;
148 float[] rgfDetData =
convertF(colBottom[0].mutable_cpu_data);
149 for (
int i = 0; i < colBottom[0].height; i++)
151 if (rgfDetData[1 + nOffset] != -1)
157 rgTopShape.Add(nNumPosClasses + nNumValidDet);
189 float[] rgfDetData =
convertF(colBottom[0].mutable_cpu_data);
190 float[] rgfGtData =
convertF(colBottom[1].mutable_cpu_data);
193 Dictionary<int, Dictionary<int, List<NormalizedBBox>>> rgAllDetections = m_bboxUtil.
GetDetectionResults(rgfDetData, colBottom[0].height, m_nBackgroundLabelId);
196 Dictionary<int, LabelBBox> rgAllGtBboxes = m_bboxUtil.
GetGroundTruthEx(rgfGtData, colBottom[1].height, m_nBackgroundLabelId,
true);
199 float[] rgfTopData =
convertF(colTop[0].mutable_cpu_data);
203 Dictionary<int, int> rgNumPos =
new Dictionary<int, int>();
204 List<KeyValuePair<int, LabelBBox>> rgAllGtBboxList = rgAllGtBboxes.ToList();
206 foreach (KeyValuePair<int, LabelBBox> kv
in rgAllGtBboxList)
208 List<KeyValuePair<int, List<NormalizedBBox>>> kvLabels = kv.Value.ToList();
209 foreach (KeyValuePair<
int, List<NormalizedBBox>> kvLabel
in kvLabels)
213 if (m_bEvaluateDifficultGt)
215 nCount = kvLabel.Value.Count;
220 for (
int i = 0; i < kvLabel.Value.Count; i++)
222 if (!kvLabel.Value[i].difficult)
227 if (!rgNumPos.ContainsKey(kvLabel.Key))
228 rgNumPos.Add(kvLabel.Key, nCount);
230 rgNumPos[kvLabel.Key] += nCount;
234 for (
int c = 0; c < m_nNumClasses; c++)
236 if (c == m_nBackgroundLabelId)
239 rgfTopData[nNumDet * 5 + 0] = -1;
240 rgfTopData[nNumDet * 5 + 1] = c;
242 if (!rgNumPos.ContainsKey(c))
243 rgfTopData[nNumDet * 5 + 2] = 0;
245 rgfTopData[nNumDet * 5 + 2] = rgNumPos[c];
247 rgfTopData[nNumDet * 5 + 3] = -1;
248 rgfTopData[nNumDet * 5 + 4] = -1;
253 foreach (KeyValuePair<
int, Dictionary<
int, List<NormalizedBBox>>> kv
in rgAllDetections)
255 int nImageId = kv.Key;
256 Dictionary<int, List<NormalizedBBox>> detections = kv.Value;
259 if (!rgAllGtBboxes.ContainsKey(nImageId))
261 List<KeyValuePair<int, List<NormalizedBBox>>> kvLabels = detections.OrderBy(p => p.Key).ToList();
262 foreach (KeyValuePair<
int, List<NormalizedBBox>> kvLabel
in kvLabels)
264 int nLabel = kvLabel.Key;
268 List<NormalizedBBox> bboxes = kvLabel.Value;
269 for (
int i = 0; i < bboxes.Count; i++)
271 rgfTopData[nNumDet * 5 + 0] = nImageId;
272 rgfTopData[nNumDet * 5 + 1] = nLabel;
273 rgfTopData[nNumDet * 5 + 2] = bboxes[i].score;
274 rgfTopData[nNumDet * 5 + 3] = 0;
275 rgfTopData[nNumDet * 5 + 4] = 1;
284 LabelBBox label_bboxes = rgAllGtBboxes[nImageId];
286 List<KeyValuePair<int, List<NormalizedBBox>>> kvLabels = detections.OrderBy(p => p.Key).
ToList();
287 foreach (KeyValuePair<
int, List<NormalizedBBox>> kvLabel
in kvLabels)
289 int nLabel = kvLabel.Key;
293 List<NormalizedBBox> bboxes = kvLabel.Value;
296 if (!label_bboxes.Contains(nLabel))
298 for (
int i = 0; i < bboxes.Count; i++)
300 rgfTopData[nNumDet * 5 + 0] = nImageId;
301 rgfTopData[nNumDet * 5 + 1] = nLabel;
302 rgfTopData[nNumDet * 5 + 2] = bboxes[i].score;
303 rgfTopData[nNumDet * 5 + 3] = 0;
304 rgfTopData[nNumDet * 5 + 4] = 1;
312 List<NormalizedBBox> gt_bboxes = label_bboxes[nLabel];
314 if (!m_bUseNormalizedBbox)
316 m_log.
CHECK_LE(m_nCount, m_rgSizes.Count,
"The count must be <= the sizes count.");
317 for (
int i = 0; i < gt_bboxes.Count; i++)
319 gt_bboxes[i] = m_bboxUtil.
Output(gt_bboxes[i], m_rgSizes[m_nCount], m_resizeParam);
323 List<bool> rgbVisited =
Utility.
Create<
bool>(gt_bboxes.Count,
false);
326 if (bboxes.Count > 1)
327 bboxes.Sort(
new Comparison<NormalizedBBox>(sortBboxDescending));
329 for (
int i = 0; i < bboxes.Count; i++)
331 rgfTopData[nNumDet * 5 + 0] = nImageId;
332 rgfTopData[nNumDet * 5 + 1] = nLabel;
333 rgfTopData[nNumDet * 5 + 2] = bboxes[i].score;
335 if (!m_bUseNormalizedBbox)
336 bboxes[i] = m_bboxUtil.
Output(bboxes[i], m_rgSizes[m_nCount], m_resizeParam);
339 float fOverlapMax = -1;
342 for (
int j = 0; j < gt_bboxes.Count; j++)
344 float fOverlap = m_bboxUtil.
JaccardOverlap(bboxes[i], gt_bboxes[j], m_bUseNormalizedBbox);
345 if (fOverlap > fOverlapMax)
347 fOverlapMax = fOverlap;
352 if (fOverlapMax >= m_fOverlapThreshold)
354 if (m_bEvaluateDifficultGt || (!m_bEvaluateDifficultGt && !gt_bboxes[nJmax].difficult))
357 if (!rgbVisited[nJmax])
359 rgfTopData[nNumDet * 5 + 3] = 1;
360 rgfTopData[nNumDet * 5 + 4] = 0;
361 rgbVisited[nJmax] =
true;
366 rgfTopData[nNumDet * 5 + 3] = 0;
367 rgfTopData[nNumDet * 5 + 4] = 1;
374 rgfTopData[nNumDet * 5 + 3] = 0;
375 rgfTopData[nNumDet * 5 + 4] = 1;
384 if (m_rgSizes.Count > 0)
389 if (m_nCount == m_rgSizes.Count)
394 colTop[0].mutable_cpu_data =
convert(rgfTopData);
405 throw new NotImplementedException();
The LabelBBox manages a bounding box used in SSD.
List< KeyValuePair< int, List< NormalizedBBox > > > ToList()
Returns the internal dictionary of items as a list.
The Log class provides general output in text form.
void CHECK_EQ(double df1, double df2, string str)
Test whether one number is equal to another.
void CHECK_GT(double df1, double df2, string str)
Test whether one number is greater than another.
void CHECK_LE(double df1, double df2, string str)
Test whether one number is less than or equal to another.
The NormalizedBBox manages a bounding box used in SSD.
float score
Get/set the score.
The Utility class provides general utility funtions.
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.
The BBox class processes the NormalizedBBox data used with SSD.
void Dispose()
Clean up all resources.
Dictionary< int, Dictionary< int, List< NormalizedBBox > > > GetDetectionResults(float[] rgData, int nNumDet, int nBackgroundLabelId)
Get detection results from rgData.
Dictionary< int, LabelBBox > GetGroundTruthEx(float[] rgGtData, int nNumGt, int nBackgroundLabelId, bool bUseDifficultGt)
Create a set of ground truth bounding boxes from the rgGtData.
float JaccardOverlap(NormalizedBBox bbox1, NormalizedBBox bbox2, bool bNormalized=true)
Calculates the Jaccard overlap between two bounding boxes.
NormalizedBBox Output(NormalizedBBox bbox, SizeF szImg, ResizeParameter p)
Output the predicted bbox on the actual image.
The BlobCollection contains a list of Blobs.
void SetData(double df)
Set all blob data to the value specified.
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.
An interface for the units of computation which can be composed into a Net.
Log m_log
Specifies the Log for output.
LayerParameter m_param
Specifies the LayerParameter describing the Layer.
void convert(BlobCollection< T > col)
Convert a collection of blobs from / to half size.
float convertF(T df)
Converts a generic to a float value.
LayerParameter.LayerType m_type
Specifies the Layer type.
The DetectionEvaluateLayer generates the detection evaluation based on the DetectionOutputLayer and g...
override int ExactNumBottomBlobs
Returns the exact number of required bottom (input) Blobs: det res, gt
override void forward(BlobCollection< T > colBottom, BlobCollection< T > colTop)
Evaluate the detection output.
override int ExactNumTopBlobs
Returns the exact number of required top (output) Blobs: det
override void Reshape(BlobCollection< T > colBottom, BlobCollection< T > colTop)
Reshape the bottom (input) and top (output) blobs.
override void LayerSetUp(BlobCollection< T > colBottom, BlobCollection< T > colTop)
Setup the layer.
DetectionEvaluateLayer(CudaDnn< T > cuda, Log log, LayerParameter p)
The DetectionEvaluateLayer constructor.
override void backward(BlobCollection< T > colTop, List< bool > rgbPropagateDown, BlobCollection< T > colBottom)
Does not implement.
override void dispose()
Releases all GPU and host resources used by the Layer.
Specifies the base parameter for all layers.
DetectionEvaluateParameter detection_evaluate_param
Returns the parmeter set when initialized with LayerType.DETECTION_EVALUATE
LayerType
Specifies the layer type.
uint background_label_id
Specifies the background class.
bool evaulte_difficult_gt
Specifies whether or not to consider the ground truth for evaluation.
string name_size_file
Specifies the file which contains a list of names and sizes in the same order of the input database....
uint num_classes
Specifies the number of classes that are actually predicted - required!
float overlap_threshold
Specifies the threshold for deciding true/false positive.
ResizeParameter resize_param
Specifies the resize parameter used in converting the NormalizedBBox to the original size.
Specifies the parameters for the ResizeParameter for use with SSD.
The MyCaffe.basecode contains all generic types used throughout MyCaffe.
The MyCaffe.common namespace contains common MyCaffe classes.
The MyCaffe.fillers namespace contains all fillers including the Filler class.
The MyCaffe.layers.ssd namespace contains all Single-Shot MultiBox (SSD) related layers.
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-...