简体   繁体   English

OpenCV 断言失败 ((unsigned)(i1 * DataType<_Tp>::channels) < (unsigned)(size.p[1] * channels())) 在 cv::Mat::at

[英]OpenCV Assertion failed ((unsigned)(i1 * DataType<_Tp>::channels) < (unsigned)(size.p[1] * channels())) in cv::Mat::at

I'm trying to do the smoothing of an RGB image using OpenCV.我正在尝试使用 OpenCV 对 RGB 图像进行平滑处理。 I'm using spatial correlation formula:我正在使用空间相关公式:

空间相关公式

Here's the code:这是代码:

#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/highgui.hpp>
#include <iostream>

using namespace cv;
using namespace std;

int main(int argc, char** argv) {
    if (argc < 2) {
        cout << "usage: " << argv[0] << " image_name" << endl;
        exit(0);
    }

    String imageName = argv[1];

    Mat image;

    image = imread(imageName, IMREAD_COLOR);

    if (image.empty()) {
        cout << "Could not open or find the image" << std::endl;
        return -1;
    }

    int padding = 2;
    int padding2 = padding / 2;

    Mat copy = Mat::zeros(image.rows + padding, image.cols + padding, image.type());

    image.copyTo(copy(Rect(padding2, padding2, image.cols, image.rows)));
    //image.copyTo(copy(Range(padding2,image.rows+padding2),Range(padding2,image.cols+padding2)));

    cout << "rows: " << image.rows << " cols: " << image.cols << endl;
    for (int i = 0; i < image.rows + 1; i++) {
        for (int j = 0; j < image.cols + 1; j++) {
            int sumB = 0;
            int sumG = 0;
            int sumR = 0;
            for (int r = -1; r <= 1; r++) {
                for (int c = -1; c <= 1; c++) {
                    sumB += image.at<Vec3b>(i + 1 + r, j + 1 + c)[0];
                    sumG += image.at<Vec3b>(i + 1 + r, j + 1 + c)[1];
                    sumR += image.at<Vec3b>(i + 1 + r, j + 1 + c)[2];
                }
            }
            cout << "i: " << i << " j: " << j << endl;
            copy.at<Vec3b>(i + 1, j + 1)[0] = sumB / 9;
            copy.at<Vec3b>(i + 1, j + 1)[1] = sumG / 9;
            copy.at<Vec3b>(i + 1, j + 1)[2] = sumR / 9;
        }
    }

    imshow("Original", image);
    imshow("Copy", copy);
    waitKey(0);
    return 0;
}

When I'm trying to execute it, I get this error:当我尝试执行它时,我收到此错误:

OpenCV(3.4.9) Error: Assertion failed ((unsigned)(i1 * DataType<_Tp>::channels) < (unsigned)(size.p[1] * channels())) in cv::Mat::at, file C:\opencv\build\include\opencv2\core\mat.inl.hpp, line 1179 

I'm using OpenCV 3.4.9 with Visual Studio 2022 in Windows 11.我在 Windows 11 中使用 OpenCV 3.4.9 和 Visual Studio 2022。

The cause for the assert : assert的原因:

Trying to access a cv::Mat out of its bound.试图访问超出其界限的cv::Mat
In these lines:在这些行中:

sumB += image.at<Vec3b>(i + 1 + r, j + 1 + c)[0];
sumG += image.at<Vec3b>(i + 1 + r, j + 1 + c)[1];
sumR += image.at<Vec3b>(i + 1 + r, j + 1 + c)[2];

i can be up to image.rows , and j can be up to image.cols (see the for loops above). i可以达到image.rowsj可以达到image.cols (参见上面的for循环)。 Then r and c can be up to 1. It means the .at method will be called with out-of-bound indices.那么rc最多可以为 1。这意味着将使用超出范围的索引调用.at方法。

You could change your for loops to do 2 less iterations.您可以更改您的for循环以减少 2 次迭代。 But another related issue is that in each (i,j) iteration you actually handle the ((i+1),(j+1)) pixel which is a bit missleading.但另一个相关问题是,在每次(i,j)迭代中,您实际上处理的是((i+1),(j+1))像素,这有点误导。

I advise to change it to be more straightforward (see the code below).我建议将其更改为更直接(请参见下面的代码)。

Another issue is that calling .at is quite expensive (due to its implementation containing a lot of checks - one of them caused the assert ).另一个问题是调用.at非常昂贵(由于它的实现包含大量检查 - 其中一个导致了assert )。 I reduced the number of calls by a factor of 3 by getting a reference to the pixel once, and then using this reference to access the 3 channels.我通过一次获取对像素的引用,然后使用该引用访问 3 个通道,将调用次数减少了 3 倍。

A few more comments:还有一些评论:

  1. Better to avoid using namespace std - see here Why is "using namespace std;"最好避免using namespace std - 请参阅此处为什么“使用命名空间 std;” considered bad practice? 被认为是不好的做法? I also believe using namespace cv should be avoided for similar (even if less strong) reasons.我也相信出于类似(即使不那么强烈)的原因,应该避免using namespace cv

  2. This code can be further optimized, by using direct access to cv::Mat data using pointers.通过使用指针直接访问cv::Mat数据,可以进一步优化此代码。 But I think this optimization can be subject of another stackoverflow entry.但我认为这种优化可能是另一个 stackoverflow 条目的主题。

Here is the code:这是代码:

#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/highgui.hpp>
#include <iostream>


int main(int argc, char** argv) {
    if (argc < 2) {
        std::cout << "usage: " << argv[0] << " image_name" << std::endl;
        exit(0);
    }

    cv::String imageName = argv[1];
    cv::Mat image = cv::imread(imageName, cv::IMREAD_COLOR);
    if (image.empty()) {
        std::cout << "Could not open or find the image" << std::endl;
        return -1;
    }

    int padding = 2;
    int padding2 = padding / 2;
    cv::Mat copy = cv::Mat::zeros(image.rows + padding, image.cols + padding, image.type());
    image.copyTo(copy(cv::Rect(padding2, padding2, image.cols, image.rows)));

    std::cout << "rows: " << image.rows << " cols: " << image.cols << std::endl;
    for (int i = 1; i < image.rows - 1; i++) {
        for (int j = 1; j < image.cols - 1; j++) {
            int sumB = 0;
            int sumG = 0;
            int sumR = 0;
            for (int r = -1; r <= 1; r++) {
                for (int c = -1; c <= 1; c++) {
                    auto const & srcPixel = image.at<cv::Vec3b>(i + r, j + c);
                    sumB += srcPixel[0];
                    sumG += srcPixel[1];
                    sumR += srcPixel[2];
                }
            }
            //cout << "i: " << i << " j: " << j << endl;
            auto & dstPixel = copy.at<cv::Vec3b>(i, j);
            dstPixel[0] = sumB / 9;
            dstPixel[1] = sumG / 9;
            dstPixel[2] = sumR / 9;
        }
    }

    cv::imshow("Original", image);
    cv::imshow("Copy", copy);
    cv::waitKey(0);
    return 0;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM