关于opencv中resize报错

环境:win10 ,opencv3.4.0 , c++
今天在对切片图像resize的时候opencv提示错误:

OpenCY Error: Assertion failed (dsize.area() >0 (iny_scale-x >0 && iny_scale y > 0)) in cv::resize, file XXX\opencV3.4.0\opencv\sources\modules\imgproc\src\resize.cpp,line 4045

我的图像尺寸是12000090000;我试了50005000都没问题,这就奇怪了,于是我按照提示去看opencv源码,找到sources\modules\imgproc\src\resize.cpp文件的第4045行,resize源码下:

void cv::resize( InputArray _src, OutputArray _dst, Size dsize,
                 double inv_scale_x, double inv_scale_y, int interpolation )
{
    CV_INSTRUMENT_REGION()

    Size ssize = _src.size();

    CV_Assert( ssize.width > 0 && ssize.height > 0 );
    CV_Assert( dsize.area() > 0 || (inv_scale_x > 0 && inv_scale_y > 0) );
    if( dsize.area() == 0 )
    {
        dsize = Size(saturate_cast<int>(ssize.width*inv_scale_x),
                     saturate_cast<int>(ssize.height*inv_scale_y));
        CV_Assert( dsize.area() > 0 );
    }
    else
    {
        inv_scale_x = (double)dsize.width/ssize.width;
        inv_scale_y = (double)dsize.height/ssize.height;
    }

    if (interpolation == INTER_LINEAR_EXACT && (_src.depth() == CV_32F || _src.depth() == CV_64F))
        interpolation = INTER_LINEAR; // If depth isn't supported fallback to generic resize

    CV_OCL_RUN(_src.dims() <= 2 && _dst.isUMat() && _src.cols() > 10 && _src.rows() > 10,
               ocl_resize(_src, _dst, dsize, inv_scale_x, inv_scale_y, interpolation))

    Mat src = _src.getMat();
    _dst.create(dsize, src.type());
    Mat dst = _dst.getMat();

    if (dsize == ssize)
    {
        // Source and destination are of same size. Use simple copy.
        src.copyTo(dst);
        return;
    }

    hal::resize(src.type(), src.data, src.step, src.cols, src.rows, dst.data, dst.step, dst.cols, dst.rows, inv_scale_x, inv_scale_y, interpolation);
}

可以看到是**CV_Assert( dsize.area() > 0 || (inv_scale_x > 0 && inv_scale_y > 0) );这行代码抛出的错误,inv_scale_x 和inv_scale_y 默认是0,这里应该没问题,那就是dsize.area()出现问题,再定位area()**的实现:

template<typename _Tp> inline
_Tp Size_<_Tp>::area() const
{
    const _Tp result = width * height;
    CV_DbgAssert(!std::numeric_limits<_Tp>::is_integer
        || width == 0 || result / width == height); // make sure the result fits in the return value
    return result;
}

看到返回的是行和列的乘积,这是突然就想到难道返回值超出范围了?于是马上去看cv::resize的第三个参数cv::Size dsize.再看cv::Size的定义:

typedef Size_<int> Size2i;
typedef Size_<int64> Size2l;
typedef Size_<float> Size2f;
typedef Size_<double> Size2d;
typedef Size2i Size;

其实就是int型的,我们都知道int类型占 4byte * 8bit = 32比特,因此int范围是 -231——231-1,即-2147483648——2147483647,再看我图像尺寸乘积120000*90000=10800000000,果然超出范围了,dsize.area()得到的是一个负数,因此CV_Assert抛出了异常。

解决办法:

修改opencv源码,重新编译!
将opencV3.4.0\opencv\sources\modules\imgproc\src\resize.cpp文件中**void cv::resize( InputArray _src, OutputArray _dst, Size dsize,double inv_scale_x, double inv_scale_y, int interpolation )**函数实现修改为如下:

void cv::resize( InputArray _src, OutputArray _dst, Size dsize,
                 double inv_scale_x, double inv_scale_y, int interpolation )
{
    CV_INSTRUMENT_REGION()

	Size ssize = _src.size();

	CV_Assert(!ssize.empty());
	if (dsize.empty())
	{
		CV_Assert(inv_scale_x > 0); CV_Assert(inv_scale_y > 0);
		dsize = Size(saturate_cast<int>(ssize.width*inv_scale_x),
			saturate_cast<int>(ssize.height*inv_scale_y));
		CV_Assert(!dsize.empty());
	}
	else
	{
		inv_scale_x = (double)dsize.width / ssize.width;
		inv_scale_y = (double)dsize.height / ssize.height;
		CV_Assert(inv_scale_x > 0); CV_Assert(inv_scale_y > 0);
	}

	if (interpolation == INTER_LINEAR_EXACT && (_src.depth() == CV_32F || _src.depth() == CV_64F))
		interpolation = INTER_LINEAR; // If depth isn't supported fallback to generic resize

	CV_OCL_RUN(_src.dims() <= 2 && _dst.isUMat() && _src.cols() > 10 && _src.rows() > 10,
		ocl_resize(_src, _dst, dsize, inv_scale_x, inv_scale_y, interpolation))

	// Fake reference to source. Resolves issue 13577 in case of src == dst.
	UMat srcUMat;
	if (_src.isUMat())
		srcUMat = _src.getUMat();

	Mat src = _src.getMat();
	_dst.create(dsize, src.type());
	Mat dst = _dst.getMat();

	if (dsize == ssize)
	{
		// Source and destination are of same size. Use simple copy.
		src.copyTo(dst);
		return;
	}

	hal::resize(src.type(), src.data, src.step, src.cols, src.rows, dst.data, dst.step, dst.cols, dst.rows, inv_scale_x, inv_scale_y, interpolation);
}

文章出处登录后可见!

已经登录?立即刷新

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
社会演员多的头像社会演员多普通用户
上一篇 2023年12月7日
下一篇 2023年12月8日

相关推荐