[英]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.rows
, j
可以达到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.那么
r
和c
最多可以为 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:还有一些评论:
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
。
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.