public override IObservable <Mat> Process(IObservable <Mat> source) { return(Observable.Create <Mat>(observer => { var skipCount = 0; var count = Count; var skip = Skip.GetValueOrDefault(count); var activeBuffers = new List <SampleBuffer>(); return source.Subscribe(input => { try { // Update pending windows activeBuffers.RemoveAll(buffer => { buffer.Update(input, 0); if (buffer.Completed) { // Window is ready, emit observer.OnNext(buffer.Samples); return true; } return false; }); var index = 0; while ((index + skipCount) < input.Cols) { // Create new window and reset skip counter index += skipCount; skipCount = skip; var buffer = new SampleBuffer(input, count, index); buffer.Update(input, index); if (buffer.Completed) { // Window is ready, emit observer.OnNext(buffer.Samples); } // Window is missing data, add to list else { activeBuffers.Add(buffer); } } // Remove remainder of input samples from skip counter skipCount -= input.Cols - index; } catch (Exception ex) { observer.OnError(ex); } }, error => observer.OnError(error), () => observer.OnCompleted()); })); }
static SampleBuffer UpdateBuffer(SampleBuffer buffer, Mat source, int index, int delay, double threshold) { var samplesTaken = buffer.Update(source, index); if (buffer.Completed && !buffer.Refined) { double min, max; Point minLoc, maxLoc; var waveform = buffer.Samples; CV.MinMaxLoc(waveform, out min, out max, out minLoc, out maxLoc); var offset = threshold > 0 ? maxLoc.X - delay : minLoc.X - delay; if (offset > 0) { var offsetBuffer = new SampleBuffer(waveform, waveform.Cols, buffer.SampleIndex + offset); offsetBuffer.Refined = true; offsetBuffer.Update(waveform, offset); offsetBuffer.Update(source, index + samplesTaken + offset); return(offsetBuffer); } } return(buffer); }
public override IObservable <Mat> Process(IObservable <Tuple <Mat, Mat> > source) { return(Observable.Create <Mat>(observer => { bool active = false; var activeBuffers = new List <SampleBuffer>(); return source.Subscribe(input => { try { var data = input.Item1; var trigger = input.Item2; // Update pending windows activeBuffers.RemoveAll(buffer => { buffer.Update(data, 0); if (buffer.Completed) { // Window is ready, emit observer.OnNext(buffer.Samples); return true; } return false; }); // Check if new triggers have arrived var nonZero = CV.CountNonZero(trigger); if (nonZero <= 0) { active = false; } else { var triggerBuffer = new byte[trigger.Cols]; var triggerHandle = GCHandle.Alloc(triggerBuffer, GCHandleType.Pinned); using (var triggerHeader = new Mat(1, triggerBuffer.Length, Depth.U8, 1, triggerHandle.AddrOfPinnedObject())) { CV.Convert(trigger, triggerHeader); triggerHandle.Free(); } for (int i = 0; i < triggerBuffer.Length; i++) { var triggerHigh = triggerBuffer[i] > 0; if (triggerHigh && !active) { var buffer = new SampleBuffer(data, Count, i); buffer.Update(data, i); if (buffer.Completed) { // Window is ready, emit observer.OnNext(buffer.Samples); } // Window is missing data, add to list else { activeBuffers.Add(buffer); } } active = triggerHigh; } } } catch (Exception ex) { observer.OnError(ex); } }, error => observer.OnError(error), () => observer.OnCompleted()); })); }
public override IObservable <SpikeWaveformCollection> Process(IObservable <Mat> source) { return(Observable.Defer(() => { byte[] triggerBuffer = null; bool[] activeChannels = null; int[] refractoryChannels = null; SampleBuffer[] activeSpikes = null; var ioff = 0L; return source.Publish(ps => ps.Zip(delay.Process(ps), (input, delayed) => { var spikes = new SpikeWaveformCollection(input.Size); if (activeSpikes == null) { triggerBuffer = new byte[input.Cols]; activeChannels = new bool[input.Rows]; refractoryChannels = new int[input.Rows]; activeSpikes = new SampleBuffer[input.Rows]; } var thresholdValues = Threshold ?? DefaultThreshold; if (thresholdValues.Length == 0) { thresholdValues = DefaultThreshold; } for (int i = 0; i < activeSpikes.Length; i++) { using (var channel = input.GetRow(i)) using (var delayedChannel = delayed.GetRow(i)) { var threshold = thresholdValues.Length > 1 ? thresholdValues[i] : thresholdValues[0]; if (activeSpikes[i] != null) { var buffer = activeSpikes[i]; buffer = UpdateBuffer(buffer, delayedChannel, 0, delay.Count, threshold); activeSpikes[i] = buffer; if (buffer.Completed) { spikes.Add(new SpikeWaveform { ChannelIndex = i, SampleIndex = buffer.SampleIndex, Waveform = buffer.Samples }); activeSpikes[i] = null; } else { continue; } } using (var triggerHeader = Mat.CreateMatHeader(triggerBuffer)) { CV.Threshold( channel, triggerHeader, threshold, 1, threshold < 0 ? ThresholdTypes.BinaryInv : ThresholdTypes.Binary); } for (int j = 0; j < triggerBuffer.Length; j++) { var triggerHigh = triggerBuffer[j] > 0; if (triggerHigh && !activeChannels[i] && refractoryChannels[i] == 0 && activeSpikes[i] == null) { var length = Length; refractoryChannels[i] = length; var buffer = new SampleBuffer(channel, length, j + ioff); buffer.Refined |= WaveformRefinement == SpikeWaveformRefinement.None; buffer = UpdateBuffer(buffer, delayedChannel, j, delay.Count, threshold); if (buffer.Completed) { spikes.Add(new SpikeWaveform { ChannelIndex = i, SampleIndex = buffer.SampleIndex, Waveform = buffer.Samples }); } else { activeSpikes[i] = buffer; } } activeChannels[i] = triggerHigh; if (refractoryChannels[i] > 0) { refractoryChannels[i]--; } } } } ioff += input.Cols; return spikes; })); })); }