public IEnumerator EncodeFragments(MemoryRef <Binary> binary, TaggedInterval[] intervals, FragmentFactory factory, string fragmentTypeName, Action <ProgressInfo> progressFeedback) { progressFeedback.Invoke(new ProgressInfo() { title = $"Start {fragmentTypeName} fragment encoder", progress = 0.0f }); // // Prologue // int metricIndex = settings.metricIndex; var numFeatures = factory.GetNumFeatures(ref binary.Ref, metricIndex); var numQuantizedFeatures = factory.GetNumQuantizedFeatures(ref binary.Ref, metricIndex); var numNormalizedFeatures = factory.GetNumNormalizedFeatures(ref binary.Ref, metricIndex); var numTransformedFeatures = numFeatures - numQuantizedFeatures - numNormalizedFeatures; numFragments = 0; foreach (var interval in intervals) { numFragments += interval.numFrames; } // // Generate fragments // FragmentArray fragmentArray = FragmentArray.Create(metricIndex, numFragments, numFeatures); int writeIndex = 0; foreach (var interval in intervals) { int segmentIndex = interval.segmentIndex; Assert.IsTrue( interval.firstFrame >= interval.segment.destination.FirstFrame); Assert.IsTrue( interval.onePastLastFrame <= interval.segment.destination.OnePastLastFrame); int relativeFirstFrame = interval.firstFrame - interval.segment.destination.FirstFrame; int numFrames = interval.numFrames; for (int i = 0; i < numFrames; ++i) { int frameIndex = relativeFirstFrame + i; var timeIndex = TimeIndex.Create( segmentIndex, frameIndex); var samplingTime = SamplingTime.Create(timeIndex); fragmentArray.samplingTimes[writeIndex++] = samplingTime; } } Assert.IsTrue(writeIndex == numFragments); progressFeedback.Invoke(new ProgressInfo() { title = $"Create {fragmentTypeName} fragments", progress = 0.0f }); ICreateFragmentsJob createFragmentsJob = factory.PrepareFragmentCreateJob(ref fragmentArray, ref binary.Ref); JobHandle createFragmentsHandle = createFragmentsJob.Schedule(); yield return(null); if (bCancel) { createFragmentsHandle.Complete(); fragmentArray.Dispose(); yield break; } createFragmentsHandle.Complete(); progressFeedback.Invoke(new ProgressInfo() { title = $"Quantize {fragmentTypeName} fragments", progress = 0.0f }); // // Generate feature quantizers // quantizers = new NativeArray <Quantizer>( numQuantizedFeatures, Allocator.Persistent); ComputeQuantizersJob computeQuantizersJob = new ComputeQuantizersJob() { fragmentArray = fragmentArray, quantizers = Quantizers }; JobHandle computeQuantizersHandle = computeQuantizersJob.Schedule(numQuantizedFeatures, 1); computeQuantizersHandle.Complete(); // // Quantize magnitudes and normalize fragments // int numQuantizedValues = numFragments * numQuantizedFeatures; quantizedValues = new NativeArray <byte>( numQuantizedValues, Allocator.Persistent); NormalizeFeaturesJob normalizeFeaturesJob = new NormalizeFeaturesJob() { numQuantizedFeatures = numQuantizedFeatures, quantizers = Quantizers, quantizedValues = new MemoryArray <byte>(QuantizedValues), fragmentArray = fragmentArray }; JobHandle normalizeFeaturesHandle = normalizeFeaturesJob.Schedule(numFragments, 1); normalizeFeaturesHandle.Complete(); // // Generate bounding boxes for feature normalization // boundingBoxes = new NativeArray <BoundingBox>( numTransformedFeatures, Allocator.Persistent); ComputeBoundingBoxesJob computeBoundingBoxesJob = new ComputeBoundingBoxesJob() { fragmentArray = fragmentArray, numTransformedFeatures = numTransformedFeatures, transformedIndex = numFeatures - numTransformedFeatures, boundingBoxes = BoundingBoxes }; JobHandle computeBoundingBoxesHandle = computeBoundingBoxesJob.Schedule(numTransformedFeatures, 1); computeBoundingBoxesHandle.Complete(); // // Normalize fragments // NormalizeFragmentsJob normalizeFragmentsJob = new NormalizeFragmentsJob() { numTransformedFeatures = numTransformedFeatures, transformedIndex = numFeatures - numTransformedFeatures, boundingBoxes = BoundingBoxes, fragmentArray = fragmentArray }; JobHandle normalizeFragmentsHandle = normalizeFragmentsJob.Schedule(numFragments, 1); normalizeFragmentsHandle.Complete(); // // Product Quantization // progressFeedback.Invoke(new ProgressInfo() { title = $"Prepare training {fragmentTypeName} fragments", progress = 0.0f }); yield return(null); if (bCancel) { fragmentArray.Dispose(); yield break; } int numCodes = numFragments * numFeatures; int numCodeWords = numFeatures * Binary.CodeBook.kNumCodeValues; codes = new NativeArray <byte>(numCodes, Allocator.Persistent); codeWords = new NativeArray <float3>(numCodeWords, Allocator.Persistent); var pqs = ProductQuantizer.Settings.Default; pqs.numAttempts = settings.numAttempts; pqs.numIterations = settings.numIterations; pqs.minimumNumberSamples = settings.minimumNumberSamples; pqs.maximumNumberSamples = settings.maximumNumberSamples; using (var pq = new ProductQuantizer(numFeatures * 3, numFeatures, pqs)) { using (ProductQuantizer.TrainingData trainingData = pq.ScheduleTraining(ref fragmentArray)) { float progression = 0.0f; do { progression = trainingData.FrameUpdate(); progressFeedback.Invoke(new ProgressInfo() { title = $"Train {fragmentTypeName} fragments", progress = progression }); yield return(null); if (bCancel) { trainingData.ForceCompleteCurrentBatch(); fragmentArray.Dispose(); yield break; } }while (progression < 1.0f); trainingData.ForceCompleteCurrentBatch(); } progressFeedback.Invoke(new ProgressInfo() { title = $"Compute {fragmentTypeName} codes", progress = 0.0f }); pq.ComputeCodes(ref fragmentArray, Codes); Assert.IsTrue(pq.centroids.Length == numCodeWords * 3); for (int i = 0; i < numCodeWords; ++i) { float x = pq.centroids[i * 3 + 0]; float y = pq.centroids[i * 3 + 1]; float z = pq.centroids[i * 3 + 2]; var centroid = new float3(x, y, z); var words = CodeWords; words[i] = centroid; } } fragmentArray.Dispose(); }
public ICreateFragmentsJob PrepareFragmentCreateJob(ref FragmentArray fragmentArray, ref Binary binary) { return(CreateTrajectoryFragmentsJob.Prepare(ref fragmentArray, ref binary)); }