c++ - 平均池 C++ 错误

标签 c++ opencv pooling

#include "opencv2/core/core.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <math.h>
#include <fstream>
#include <iostream>
using namespace cv;
using namespace std;
#define ATD at<double>

Mat average_pooling2x2(Mat mat, int padding_mathed)
{
int width_remain = mat.cols % 2;
int high_remain = mat.rows % 2;

Mat mat_new;
if (width_remain == 0 && high_remain == 0)
    mat.copyTo(mat_new);
else
{
    if (padding_mathed == 1)//valid
    {
        Rect roi = Rect(0, 0, mat.cols - width_remain, mat.rows - high_remain);
        mat(roi).copyTo(mat_new);
    }
    else //same
    {
        mat.copyTo(mat_new);
        if (high_remain != 0)
        {
            Mat row_add = cv::Mat::zeros(high_remain, mat_new.cols,mat_new.type());
            mat_new.push_back(row_add);
        }
        if (width_remain != 0)
        {
            Mat col_add = cv::Mat::zeros(width_remain, mat_new.rows, mat_new.type());
            mat_new = mat_new.t();
            mat_new.push_back(col_add);
            mat_new = mat_new.t();
        }
    }
}

Mat res(mat_new.cols / 2, mat_new.rows / 2, mat_new.type(), Scalar::all(0));


if (mat_new.channels() ==3)
{  


    for (int i = 0; i < res.rows; i++)//this is where error happened
    {
        uchar *data_res = res.ptr<uchar>(i);
        uchar * data = mat_new.ptr<uchar>(2*i);
        uchar * data1 = mat_new.ptr<uchar>(2*i+1);
        for (int j = 0; j < res.cols*res.channels(); j = j + 3)
        {
            data_res[j] = (data[j*2] + data[j*2+3] + data1[j*2] + data1[j*2+3]) / 4;
            data_res[j + 1] = (data[j*2+1] + data[j*2+4] + data1[j*2+1] + data1[j*2+4]) / 4;
            data_res[j + 2] = (data[j*2+2] + data[j*2+5] + data1[j*2+2] + data1[j*2+5]) / 4;

        }
    }

}

else
{
    for (int i = 0; i<res.rows; i++)
    {
        for (int j = 0; j<res.cols; j++)
        {
            Mat temp;
            Rect roi = Rect(j * 2, i * 2, 2, 2);
            mat_new(roi).copyTo(temp);
            double val;
            val = sum(temp)[0] / (2 * 2);
            res.ATD(i, j) = val;
        }
    }

}

return res;


}


int main(int argc, char** argv)
{
    Mat image = imread("C://Users//Administrator//Desktop//11.jpg");
    imshow("???", image);
    Mat pooling_image;
    average_pooling2x2(image, 2).copyTo(pooling_image);
    imshow("???", pooling_image);
    waitKey();
    return 0;
}

OpenCV Error: Assertion failed (y == 0 || (data && dims >= 1 && (unsigned)y < (unsigned)size.p[0])) in cv::Mat::ptr, file d:\opencv\build\include\opencv2\core\mat.inl.hpp, line 827

最近我尝试用C++实现平均池,这是我运行代码时的错误,看起来可能是ptr指针超出了范围。但我就是想不通问题出在哪里。真的需要一些帮助

最佳答案

如果您打开错误消息引用的文件,您会看到 ptr() 方法定义如下:

template<typename _Tp> inline _Tp* Mat::ptr(int y)
{
    CV_DbgAssert( y == 0 || (data && dims >= 1 && (unsigned)y < (unsigned)size.p[0]) );
    return (_Tp*)(data + step.p[0]*y);
}

CV_DbgAssert() 中的所有内容都必须评估为 true - 否则程序将在运行时崩溃。从这种情况来看,很明显您指的是程序中位于 Mat 边界之外的行(上面的变量 y)。

在您的情况下,我可以看到程序将要崩溃的几行。

在这些行中,当 i 等于或大于 res.rows/2 时发生崩溃(如果 res.rows 是奇数,第一个将崩溃):

uchar * data = mat_new.ptr<uchar>(2*i);
uchar * data1 = mat_new.ptr<uchar>(2*i+1);

这个循环也会崩溃,因为 data_res 只有 res.cols 列,而你允许 j 到达 res.cols*res.channels() -1:

for (int j = 0; j < res.cols*res.channels(); j = j + 3)
        {
            data_res[j] = (data[j*2] + data[j*2+3] + data1[j*2] + data1[j*2+3]) / 4;
            data_res[j + 1] = (data[j*2+1] + data[j*2+4] + data1[j*2+1] + data1[j*2+4]) / 4;
            data_res[j + 2] = (data[j*2+2] + data[j*2+5] + data1[j*2+2] + data1[j*2+5]) / 4;

        }

此外,我相信这里:

Mat res(mat_new.cols / 2, mat_new.rows / 2, mat_new.type(), Scalar::all(0));

您可能不小心交换了参数 - resmat_new.cols/2 行,而我认为您希望它是 mat_new.rows/2.

关于c++ - 平均池 C++ 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44542312/

相关文章:

python matplotlib图像-默认反转白色和黑色

java - 线程池与许多单独的线程

c# - StreamWriter.WriteLine 磁盘 I/O 是否发生池化?

c++ - MeasureCharacterRanges 不适合字符?

python - 从python-opencv中的图像获取x,y点

c++ - 如何将矩阵提升为具有多个线程的幂?

python - Python-OpenCV手写顺序数字识别与提取

mysql - tomcat 7.0.42池化,hibernate 4.2,mysql坚如磐石的自动重新连接解决方​​案

c++ - 绘制具有多纹理的对象和具有单一纹理的其他对象

c++ - 使用 Lua/C++ 设置文件路径