How to accumulate images with C# with opencv?

I would like to accumulate grayscale images in C# with opencv. Therefore I used this code so far:

// Convert to gray image first
Mat dst = new Mat();
Cv2.CvtColor(imageMat, dst, ColorConversionCodes.BGR2GRAY);

var numOfAverage = 5;   
for (int i = 0; i < numOfAverage; i++)
{
     Cv2.Accumulate(dst, acc, 1);
}

Here I get an exception which says:

OpenCvSharp.OpenCVException: '_mask.empty() || (_src.sameSize(_mask) && _mask.type() == CV_8U)'

I assume there is something wrong with the “mask” in Cv2.Accumulate I used. Could someone what is incorrect and how to solve that?

Thanks!

what is the 1 doing there ?
(it’s getting interpreted as a ‘mask’, which you probably did not want …)

here’s c++ docs for it.

in the end, what are you trying to achieve with it ?

I think the problem is exactly the “1” which stands for mask. I thought it is an optional parameter but I do get an error if I do not use it.
So how would you set this parameter?

I would simply average over a number n images and get the averaged image back.

mask
Type: OpenCvSharp.InputArray
Optional operation mask.

seems optional to me.

if it isn’t, bug report to OpenCVSharp. They are their own project. Issues you have with OpenCVSharp should first to go them.

in any case, 1 is a number, not an array. there need be no logic that expands a scalar to an array.

unfortunately, this IS a problem specific to your 3rdparty c# wrapper. please lookup, how to apply masks from c#. (it’s probably like ‘new Mat()’ )

this returns the sum image, you still nee to divide by N for the average.

With:

Mat bmAccu = new Mat();
Mat mask = new Mat();

var numOfAverage = 5;
for (int i = 0; i < numOfAverage; i++)
    Cv2.Accumulate(bmDenoise, bmAccu, mask);

bmAccu = bmAccu / numOfAverage;

I do get following error:

OpenCvSharp.OpenCVException: '_src.sameSize(_dst) && dcn == scn'

Although “mask” is documented as optional it has to be used. But there is also no docu explaining what “mask” is doing or needed.

I simply would like to average over n images and display the averaged image again.

bmDenoise and bmAccu still need to have same size & num channels

So when changing the dst to the same size as src like this:

Mat bmAccu = new Mat(bmDenoise.Rows, bmDenoise.Cols, MatType.CV_8UC1);
Mat mask = new Mat();


var numOfAverage = 5;
for (int i = 0; i < numOfAverage; i++)
    Cv2.Accumulate(bmDenoise, bmAccu, mask);

I get following error message:

OpenCvSharp.OpenCVException: 'func != 0'

Is this because of the “mask” (I still do not understand this parameter) or something else?

OpenCV docs say:

dst: Accumulator image with the same number of channels as input image, and a depth of CV_32F or CV_64F.

there is probably no “accumulation function” to accumulate into 8UC1. I can see why they’d focus on 32F and 64F accumulators only but it’s slightly disappointing.

So when changing that format I can run it but the bmAccu is a pure white image. I am wondering if the mask is correct like this:

deb

In the documentation it is stated as optional which does not work either. So what is the correct format of that mask??

as determined how?

what is the max value in the accumulator?

how many images did you accumulate?

I accumulate 5 images. Here is the result of the input image (bmDenoise) and the accumulated image:

deb

// Accumulate images
Mat bmAccu = new Mat(bmDenoise.Rows, bmDenoise.Cols, MatType.CV_32F);
Mat mask = new Mat();

var numOfAverage = 5;
for (int i = 0; i < numOfAverage; i++)
    Cv2.Accumulate(bmDenoise, bmAccu, mask);

bmAccu = bmAccu / numOfAverage;

know this about imshow: given uint8, 0 is black and 255 is white. given float, 0 is black and 1.0 is white.

you can convert to uint8, or divide by 255.

also:

try

Mat bmAccu = Mat.Zeros(bmDenoise.Rows, bmDenoise.Cols, MatType.CV_32F);

(as a plain new Mat does not preinitialize memory)

Changed the code accordingly. With dividing by 255 I do get an image but I can not see any averaging at all. Here the comparison between the incoming (Original) image and the averaged image:

The code behind is:

 // Accumulate images
 Mat bmAccu = Mat.Zeros(640, 512, (MatType)MatType.CV_32F);
 Mat mask = new Mat();

 for (int i = 0; i < numOfAverage; i++)
     Cv2.Accumulate(imageMat, bmAccu, mask);

 bmAccu /= numOfAverage;      // average by 20

 Cv2.ImShow("Original", imageMat); 
 Cv2.ImShow("Average", bmAccu / 255);
 Cv2.WaitKey(1);

no wonder, given your setup.
5 times the same, divide by 5, should be original image
(minus numerical instabilities)

At this point, you should pursue structured learning materials, perhaps take a class with a teacher. This self-directed ad hoc approach is not appropriate for your current level of expertise.