// TODO: The order of data in the matrix is reverse of the channel index. // m[11] => channel 0, etc. protected override void Write(ONIContextTask ctx, Arr input) { var inputMatrix = input.GetMat(); // Check dims var size = inputMatrix.Rows * inputMatrix.Cols; if (size % AnalogInputDataFrame.NumberOfChannels != 0) { throw new IndexOutOfRangeException("Source must contain a multiple of 12 elements."); } if (DataType == AnalogDataType.S16 && inputMatrix.Depth == Depth.S16) { var data = new Mat(inputMatrix.Size, Depth.U16, 1); CV.ConvertScale(inputMatrix, data, 1, 32768); ctx.Write((uint)DeviceAddress.Address, data.Data, 2 * size); } else if (DataType == AnalogDataType.Volts && (inputMatrix.Depth == Depth.F32 || inputMatrix.Depth == Depth.F64)) { var data = new Mat(inputMatrix.Size, Depth.U16, 1); CV.ConvertScale(inputMatrix, data, 3276.75, 32768); ctx.Write((uint)DeviceAddress.Address, data.Data, 2 * size); } else { throw new Bonsai.WorkflowRuntimeException("Source element depth must Depth.S16 when " + "DataType is S16 and either Depth.F32 or Depth.F64 when Datatype is Volts."); } }
private Mat GetEphysDataF32(short[,] data) { var output = new Mat(NumberOfEphysChannels, NumberOfSamples, Depth.F32, 1); using (var header = Mat.CreateMatHeader(data)) { CV.ConvertScale(header, output, 0.195); } return(output); }
protected override IObservable <IplImage> GetImageSource(IObservable <IObservable <object> > dataSource) { return(imageSource.Select(image => { if (image.Depth != IplDepth.U8) { var normalizedImage = new IplImage(image.Size, IplDepth.U8, image.Channels); var scale = byte.MaxValue / (double)ushort.MaxValue; CV.ConvertScale(image, normalizedImage, scale); image = normalizedImage; } return image; })); }
public override IObservable <IplImage> Process(IObservable <IplImage> source) { return(source.Select(input => { double min, max; Point minLoc, maxLoc; var output = new IplImage(input.Size, IplDepth.F32, input.Channels); CV.MinMaxLoc(input, out min, out max, out minLoc, out maxLoc); var range = max - min; var scale = range > 0 ? 1.0 / range : 0; var shift = range > 0 ? -min : 0; CV.ConvertScale(input, output, scale, shift); return output; })); }
public override IObservable <Mat> Process(IObservable <Mat> source) { return(source.Select(input => { var channels = Channels; var output = new Mat(input.Size, input.Depth, input.Channels); var reference = new Mat(1, input.Cols, input.Depth, input.Channels); if (channels == null || channels.Length == 0) { if (input.Depth != Depth.F32) { var temp = new Mat(reference.Rows, reference.Cols, Depth.F32, reference.Channels); CV.Reduce(input, temp, 0, ReduceOperation.Avg); CV.Convert(temp, reference); } else { CV.Reduce(input, reference, 0, ReduceOperation.Avg); } } else if (channels.Length == 1) { CV.Copy(input.GetRow(channels[0]), reference); } else { var sum = input.Depth != Depth.F32 ? new Mat(reference.Rows, reference.Cols, Depth.F32, reference.Channels) : reference; sum.SetZero(); for (int i = 0; i < channels.Length; i++) { using (var referenceChannel = input.GetRow(channels[i])) { CV.Add(sum, referenceChannel, sum); } } CV.ConvertScale(sum, reference, 1f / channels.Length); } CV.Repeat(reference, output); CV.Sub(input, output, output); return output; })); }
private Mat GetAuxiliaryData(ushort[,] data) { using (var header = Mat.CreateMatHeader(data)) { if (AuxFormat == RHD2164Configuration.AuxDataFormat.Volts) { var output = new Mat(NumberOfAuxChannels, NumberOfSamples, Depth.F32, 1); CV.ConvertScale(header, output, 0.0000374); return(output); } else { var output = new Mat(NumberOfAuxChannels, NumberOfSamples, Depth.U16, 1); CV.Convert(header, output); return(output); } } }
public override IObservable <IplImage> Process(IObservable <IplImage> source) { return(Observable.Defer(() => { int averageCount = 0; IplImage image = null; IplImage difference = null; IplImage background = null; return source.Select(input => { if (background == null || background.Size != input.Size) { averageCount = 0; image = new IplImage(input.Size, IplDepth.F32, input.Channels); difference = new IplImage(input.Size, IplDepth.F32, input.Channels); background = new IplImage(input.Size, IplDepth.F32, input.Channels); background.SetZero(); } var output = new IplImage(input.Size, IplDepth.U8, input.Channels); if (averageCount < BackgroundFrames) { averageCount++; output.SetZero(); CV.Acc(input, background); if (averageCount == BackgroundFrames) { CV.ConvertScale(background, background, 1.0 / averageCount, 0); } } else { CV.Convert(input, image); switch (SubtractionMethod) { case SubtractionMethod.Bright: CV.Sub(image, background, difference); break; case SubtractionMethod.Dark: CV.Sub(background, image, difference); break; case SubtractionMethod.Absolute: default: CV.AbsDiff(image, background, difference); break; } if (AdaptationRate > 0) { CV.RunningAvg(image, background, AdaptationRate); } CV.Threshold(difference, output, ThresholdValue, 255, ThresholdType); } return output; }); })); }
public override IObservable <Mat> Process(IObservable <Mat> source) { return(Observable.Create <Mat>(observer => { var carry = 0; var index = 0; var offset = 0; var lottery = 0; var scaleFactor = 0.0; var currentFactor = 0; var buffer = default(Mat); var carryBuffer = default(Mat); var downsampling = Downsampling; var random = downsampling == DownsamplingMethod.Dithering ? new Random() : null; var reduceOp = (ReduceOperation)(downsampling - DownsamplingMethod.Sum); if (reduceOp == ReduceOperation.Avg) { reduceOp = ReduceOperation.Sum; } var downsample = downsampling == DownsamplingMethod.LowPass ? filter.Process(source) : source; return downsample.Subscribe(input => { try { var bufferLength = BufferLength; if (bufferLength == 0) { bufferLength = input.Cols; } if (buffer == null || buffer.Rows != input.Rows || currentFactor != factor) { index = 0; currentFactor = factor; if (downsampling >= DownsamplingMethod.Sum) { carry = currentFactor; carryBuffer = new Mat(input.Rows, 1, input.Depth, input.Channels); if (downsampling == DownsamplingMethod.Avg) { scaleFactor = 1.0 / currentFactor; } else { scaleFactor = 0; } } else if (random != null) { lottery = random.Next(currentFactor); offset = lottery; } else { offset = 0; } buffer = CreateBuffer(bufferLength, input); } while (offset < input.Cols) { // Process decimation data on this buffer Rect outputRect; if (downsampling > DownsamplingMethod.LowPass) { outputRect = new Rect(index, 0, 1, input.Rows); } else { var samples = input.Cols - offset; var whole = samples / currentFactor; outputRect = new Rect(index, 0, Math.Min(buffer.Cols - index, whole), input.Rows); } if (downsampling >= DownsamplingMethod.Sum) { // Reduce decimate var inputSamples = Math.Min(input.Cols - offset, carry); var inputRect = new Rect(offset, 0, inputSamples, input.Rows); using (var inputBuffer = input.GetSubRect(inputRect)) using (var outputBuffer = buffer.GetCol(index)) { if (carry < currentFactor) { CV.Reduce(inputBuffer, carryBuffer, 1, reduceOp); switch (reduceOp) { case ReduceOperation.Sum: CV.Add(outputBuffer, carryBuffer, outputBuffer); break; case ReduceOperation.Max: CV.Max(outputBuffer, carryBuffer, outputBuffer); break; case ReduceOperation.Min: CV.Min(outputBuffer, carryBuffer, outputBuffer); break; } } else { CV.Reduce(inputBuffer, outputBuffer, 1, reduceOp); } offset += inputRect.Width; carry -= inputSamples; if (carry <= 0) { index++; carry = currentFactor; if (scaleFactor > 0) { CV.ConvertScale(outputBuffer, outputBuffer, scaleFactor); } } } } else if (outputRect.Width > 1) { // Block decimate var inputRect = new Rect(offset, 0, outputRect.Width * currentFactor, input.Rows); using (var inputBuffer = input.GetSubRect(inputRect)) using (var outputBuffer = buffer.GetSubRect(outputRect)) { CV.Resize(inputBuffer, outputBuffer, SubPixelInterpolation.NearestNeighbor); } index += outputRect.Width; offset += inputRect.Width; } else { // Decimate single time point using (var inputBuffer = input.GetCol(offset)) using (var outputBuffer = buffer.GetCol(index)) { CV.Copy(inputBuffer, outputBuffer); } index++; if (random != null) { offset += currentFactor - lottery; lottery = random.Next(currentFactor); offset += lottery; } else { offset += currentFactor; } } if (index >= buffer.Cols) { index = 0; observer.OnNext(buffer); buffer = CreateBuffer(bufferLength, input); } } offset -= input.Cols; } catch (Exception ex) { observer.OnError(ex); } }, observer.OnError, () => { // Emit pending buffer if (index > 0) { observer.OnNext(buffer.GetCols(0, index)); } buffer = null; observer.OnCompleted(); }); })); }