/// <summary> /// Called every time a new frame shows up from the camera /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void provider_ImageTransaction(object sender, ImageReceivedEventArgs e) { if (stopping || e == null || e.PixelData == null) { return; } if (Monitor.TryEnter(this)) { imgGPU.Scatter(e.PixelData); if (calibrating) { // compute a running mean of each pixel worker.Launch(RunningMean_Kernel, lp, e.Width, imgGPU.Ptr, meanImg.Ptr, numCalibrationSamples); numCalibrationSamples++; // compute the mean over the full mean image, using a reduction operation addReduce.Reduce(meanImg.Ptr, scalarOutput.Ptr, numPixels); var mean = scalarOutput.GatherScalar(); mean /= numPixels; // update the correction factor for each pixel worker.Launch(UpdateCorrectionFactor_Kernel, lp, e.Width, meanImg.Ptr, correctionFactor.Ptr, mean); } if (correctBrightness) { worker.Launch(ApplyCorrectionFactor_Kernel, lp, e.Width, correctionFactor.Ptr, imgGPU.Ptr); imgGPU.Gather(e.PixelData); } img.Bytes = e.PixelData; // note: have to do this last, because if you set it earlier but then modify the bytes it won't update the image // trigger a new frame event OnFrameAvailable(new VideoFrame { Image = img, ImageGPU = imgGPU, Timestamp = e.TimeStamp }); Monitor.Exit(this); } }