sazr
sazr

Reputation: 25928

Calculate Mean: different result for masked image vs ROI

I have a weird problem where my average gradient magnitude result is different if I use a mask as opposed to creating a new Mat of that small ROI. I'll explain the 2 different ways I do this and 2 different average gradient magnitude results I get. I thought I should get the same average gradient magnitude result?

Scenario: Image A is my source/original image of a landscape. I want to get the average gradient magnitude in the region A (10,100), (100,100), (100,150), (10,150).

Technique 1:
- Create a ROI Mat that just shows region A. So its dimensions are 90 by 50.
- Perform cv::Sobel(), cv::magnitude() then cv::meanStdDev()
- My average gradient magnitude result is 11.34.

Technique 2:
- Create a new Mat that is a mask. The mat is the same dimensions as Image A and has a white area where Region A is. Then create a new Mat that just shows that region of Image A and the rest of the Mat is black - hopefully this makes sense.
- Perform cv::Sobel(), cv::magnitude() (but use the mask) then cv::meanStdDev()
- My average gradient magnitude result is 43.76.

Why the different result?

Below is my code:

static Mat backupSrc;
static Mat curSrc;

// Technique 1
void inspectRegion(const Point& strt, const Point& end) {

    curSrc = Mat(backupSrc.size(), CV_8UC3);
    cvtColor(backupSrc, curSrc, CV_GRAY2RGB);

    Rect region = Rect(strt, end);
    Mat regionImg = Mat(curSrc, region);

    // Calculate the average gradient magnitude/strength across the image
    Mat dX, dY, mag;
    Sobel(regionImg, dX, CV_32F, 1, 0);
    Sobel(regionImg, dY, CV_32F, 0, 1);
    magnitude(dX, dY, mag);

    Scalar sMMean, sMStdDev;
    meanStdDev(mag, sMMean, sMStdDev);
    double magnitudeMean = sMMean[0];
    double magnitudeStdDev = sMStdDev[0];

    rectangle(curSrc, region, { 0 }, 1);

    printf("[Gradient Magnitude Mean: %.3f, Gradient Magnitude Std Dev: %.3f]\n", magnitudeMean, magnitudeStdDev);
}

// Technique 2
void inspectRegion(const std::vector<Point>& pnts) {

    curSrc = Mat(backupSrc.size(), CV_8UC3);
    cvtColor(backupSrc, curSrc, CV_GRAY2RGB);

    std::vector<std::vector<Point>> cPnts;
    cPnts.push_back(pnts);

    Mat mask = Mat::zeros(curSrc.rows, curSrc.cols, CV_8UC1);
    fillPoly(mask, cPnts, { 255 });
    Mat regionImg;
    curSrc.copyTo(regionImg, mask);


    // Calculate the average gradient magnitude/strength across the image
    Mat dX, dY, mag;
    Sobel(regionImg, dX, CV_32F, 1, 0);
    Sobel(regionImg, dY, CV_32F, 0, 1);
    magnitude(dX, dY, mag);

    Scalar sMMean, sMStdDev;
    meanStdDev(mag, sMMean, sMStdDev, mask);
    double magnitudeMean = sMMean[0];
    double magnitudeStdDev = sMStdDev[0];

    polylines(curSrc, pnts, true, { 255 }, 3);

    printf("[Gradient Magnitude Mean: %.3f, Gradient Magnitude Std Dev: %.3f]\n", magnitudeMean, magnitudeStdDev);
}

Upvotes: 0

Views: 203

Answers (1)

Geoff
Geoff

Reputation: 8135

In technique 2 the gradients around the boarders of your rectangle will be very high and will corrupt the calculation.

Consider dilating your mask before computing the gradients so that this spike is outside of the non-dilated mask that you send into the meanStdDev function.

Upvotes: 1

Related Questions