Reputation: 25928
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
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