public static Tensor ProcessPrediction(int inputSize, YOLOv4.Output modelOutput, int classCount, ReadOnlySpan <int> strides, Tensor <int> anchors, ReadOnlySpan <float> xyScale, float scoreThreshold) { var bboxTensors = new List <Tensor>(); var probTensors = new List <Tensor>(); foreach (var(scaleIndex, featureMap) in Tools.Enumerate(modelOutput.SSBox, modelOutput.MBBox, modelOutput.LBBox)) { var outputTensors = Decode(featureMap, outputSize: inputSize / strides[scaleIndex], classCount: classCount, strides: strides, anchors: anchors, scaleIndex: scaleIndex, xyScale: xyScale); bboxTensors.Add(outputTensors.xywh); probTensors.Add(outputTensors.prob); } var bbox = tf.concat(bboxTensors.ToArray(), axis: 1); var prob = tf.concat(probTensors.ToArray(), axis: 1); var(boxes, conf) = FilterBoxes(bbox, prob, scoreThreshold: scoreThreshold, inputShape: tf.constant(new[] { inputSize, inputSize })); return(tf.concat(new[] { boxes, conf }, axis: -1)); }
SelectBoxes(YOLOv4.Output featureMaps, int inputSize, int classCount, ReadOnlySpan <int> strides, Tensor <int> anchors, ReadOnlySpan <float> xyScale, float scoreThreshold = 0.2f) { var pred = ProcessPrediction(inputSize: inputSize, featureMaps, classCount: classCount, strides: strides, anchors: anchors, xyScale: xyScale, scoreThreshold: scoreThreshold); var boxes = pred[.., .., 0..4];
public static Model CreateSaveable(int inputSize, Tensor input, YOLOv4.Output featureMaps, int classCount, ReadOnlySpan <int> strides, Tensor <int> anchors, ReadOnlySpan <float> xyScale, float scoreThreshold) { var suppression = SelectBoxes(featureMaps, inputSize: inputSize, classCount: classCount, strides: strides, anchors: anchors, xyScale: xyScale, scoreThreshold: scoreThreshold); return(new Model(new { inputs = input, outputs = new PythonList <Tensor> { suppression.Boxes, suppression.Scores, suppression.Classes, suppression.Detections, } }.AsKwArgs())); }
public static ObjectDetectionResult[] DetectRaw(Model rawDetector, Size supportedSize, int classCount, Image <Rgb24> image, ReadOnlySpan <int> strides, Tensor <int> anchors, ReadOnlySpan <float> xyScale, float scoreThreshold = 0.2f) { if (rawDetector is null) { throw new ArgumentNullException(nameof(rawDetector)); } if (image is null) { throw new ArgumentNullException(nameof(image)); } var input = ImageTools.YoloPreprocess(new ObjectDetectionDataset.ClrEntry { Image = image.Clone(), }, supportedSize); var images = input.Image[np.newaxis, np.rest_of_the_axes].AsArray(); IList <Tensor> prediction = rawDetector.__call__(images); Debug.Assert(prediction.Count == 3); var output = new YOLOv4.Output { SSBox = prediction[0], MBBox = prediction[1], LBBox = prediction[2], }; var suppression = SelectBoxes(output, inputSize: supportedSize.Width, classCount: classCount, strides: strides, anchors: anchors, xyScale: xyScale, scoreThreshold: scoreThreshold); ndarray <float> boxs = suppression.Boxes.numpy(); ndarray <float> scores = suppression.Scores.numpy(); ndarray <long> classes = suppression.Classes.numpy(); ndarray <int> detections = suppression.Detections.numpy(); return(ObjectDetectionResult.FromCombinedNonMaxSuppressionBatch( boxs, scores, classes, detections[0].AsScalar())); }