-1

I have two videos, one of a background and one of that same background with a person sitting in the frame. I generated two images from the video of just the background: the mean image of the background video (by accumulating the frames and dividing by the number of frames) and an image of standard deviations from the mean per pixel, taken over the frames. In other words, I have two images representing the Gaussian distribution of the background video. Now, I want to threshold an image, not using one fixed threshold value for all pixels, but using the standard deviations from the image (a different threshold per pixel). However, as far as I understand, OpenCV's threshold() function only allows for one fixed threshold. Are there functions I'm missing, or is there a workaround?

1 Answers1

1

A cv::Mat provides methodology to accomplish this.

The setTo() methods takes an optional InputArray as mask.

Assuming the following:

std is your standard deviations cv::Mat, in is the cv::Mat you want to threshold and thresh is the factor for your standard deviations.

Using these values the custom thresholding could be done like this:

// Computes threshold values based on input image + std dev
cv::Mat mask = in +/- (std * thresh);
// Set in.at<>(x,y) to 0 if value is lower than mask.at<>(x,y)
in.setTo(0, in < mask);

The in < mask expression creates a new MatExpr object, a matrix which is 0 at every pixel where the predicate is false, 255 otherwise. This is a handy way to implement custom thresholding.

s1hofmann
  • 1,491
  • 1
  • 11
  • 22
  • `cv::Mat mask = in +/- (std * thresh);` is not code, it translates to: `mask.setTo(255, tmp < (tmp + bg_std_h_image * thresh)); mask.setTo(0, tmp < (tmp - bg_std_h_image * thresh));` – Amber Elferink Feb 23 '20 at 20:40