Search code examples
c++opencvpixelroi

OpenCV pixel access pointr vs. at() - Different values


I encountered weird behaviour when trying to access pixels as shown below:

void Dbscan::regionQuery(int i, int j, std::vector<Point>* res) const {
// check rect. grid around center point
const size_t row_min = std::max(0, i-eps_);
const size_t row_max = std::min(n_rows_, i+eps_+1);
const size_t col_min = std::max(0, j-eps_);
const size_t col_max = std::min(n_cols_, j+eps_+1);
assert(masked_img_.depth() == CV_8UC1);
for (int m = row_min; m<row_max; ++m) {
    const uchar* mask_ptr = masked_img_.ptr(m);
    for (int n = col_min; n<col_max; ++n) {
        assert(*mask_ptr == masked_img_.at<uchar>(m, n));
        if (masked_img_.at<uchar>(m, n) == 255) {
            res->emplace_back(Point(m,n));
        }
        mask_ptr++;
    }
}

Basically, the second assertion as shown fails and I'm rather clueless as to what is going on. Does anyone have an idea how to best approach debugging the problem above?

Bests regards

Felix


Solution

  • cv::Mat::ptr returns a pointer to the beginning of the row from the argument, which is an address of an element in the first column of this row. cv::Mat::at returns a reference to the element in the row and column from the argument. In your code the row matches, but the column doesn't (unless your col_min evaluates to 0), thus you need to move the pointer from cv::Mat::ptr n elements to match your column as well:

    for (int m = row_min; m<row_max; ++m) {
        const uchar* mask_ptr = masked_img_.ptr(m);
        for (int n = col_min; n<col_max; ++n) {
            assert(*(mask_ptr + n) == masked_img_.at<uchar>(m, n));
            if (masked_img_.at<uchar>(m, n) == 255) {
                res->emplace_back(Point(m,n));
            }
        }
    }