Ask Your Question
2

Sobel filter doesn't respect ROI

asked Aug 21 '13

mkeeter gravatar image

I'm suspicious about how the Sobel filter treats non-continuous images.

Two identical images -- one made by changing the ROI of a larger image and the other by cloning -- produce different results when run through the filter:

#include <cassert>
#include <opencv2/opencv.hpp>

using namespace std;
using namespace cv;

int main(int argc, char** argv)
{
    // Create a matrix that is all-zeros other than the last column
    Mat orig(100, 100, CV_8U, cv::Scalar(0)), copy;
    orig.col(orig.cols-1).setTo(255);

    // Crop the last column out of the matrix in two ways:
    //  a) Using colRange, which only creates a new header
    //  b) Using copyTo, which creates a new header and data
    orig = orig.colRange(0, orig.cols - 1);
    orig.copyTo(copy);

    // Assert that the matrices are the same
    assert(countNonZero(orig != copy) == 0);

    // Run a Sobel filter on both matrices
    Sobel(orig, orig, CV_16S, 1, 0);
    Sobel(copy, copy, CV_16S, 1, 0);

    // Assert that the Sobel filter results are the same
    assert(countNonZero(orig != copy) == 0);
}

This bit of sample code fails on the second assert statement.

(OpenCV 2.4.6.1 on Mac OS 10.6, 64-bit)

Preview: (hide)

Comments

You should report your bug on the bug tracker. Thanks.

Mathieu Barnachon gravatar imageMathieu Barnachon (Aug 21 '13)edit

1 answer

Sort by » oldest newest most voted
3

answered Oct 8 '14

As reported in the bug report this behaviours is completely normal.

AFAIK copyTo only couples the header of the new Mat element with the header of the original file. In memory they are still pointing to the same data. The clone() operation makes a deep copy and ensures that a pointer to new memory is created.

So basically it is normal that your code produces two different results. The first Sobel is on the original data, however the second Sobel is applied on an already Sobel applied image and thus the end result will be different.

I suggest adjusting this line

orig.copyTo(copy);

to

copy = orig.clone();

And the result will be as expected.

The logic behind is the use of smart pointers in OpenCV which try to minimize the memory print of an application but which can lead to very unexpected behaviour.

Preview: (hide)

Question Tools

1 follower

Stats

Asked: Aug 21 '13

Seen: 722 times

Last updated: Oct 08 '14