opencv图像混合报错问题

本例是在运行毛星云编著的《OpenCV3编程入门》书籍中的示例代码(P74 滑动条的创建和使用)时发现的报错问题,记录错误类型和解决办法,以供同样初学opencv并遇到此类问题的朋友参考。
如果直接使用书籍配套代码和图片资源,可能不会报错,但是我是使用自己下载的图片进行演示,然后发现一直不能成功。
报错信息:

  1. OpenCV Error: Sizes of input arguments do not match (The operation is neither ‘array op array’ (where arrays have the same size and the same number of channels), nor ‘array op scalar’, nor ‘scalar op array’) in cv::arithm_op, file …\opencv\modules\core\src\arithm.cpp, line 1287
  2. 0x76F733D2处(位于TRACKBAR.exe中)有未经处理的异常:Microsoft C++异常:cv::Exception,位于内存位置0x004EDCAC处。

书籍源码如下:

#include
#include"opencv2/highgui/highgui.hpp"
using namespace cv;
#define WINDOW_NAME "【线性混合示例】"//为窗口标题定义的宏

//全局变量声明
const int g_nMaxAlphaValue = 100;//Alpha值的最大值
int g_nAlphaValueSlider;//滑动条对应的变量
double g_dAlphaValue;
double g_dBetaValue;

//声明存储图像的变量
Mat g_srcImage1;
Mat g_srcImage2;
Mat g_dstImage;

//响应滑动条的回调函数
void on_Trackbar(int, void*)
{
    //求出当前alpha值相对于最大值的比例
	g_dAlphaValue = (double)g_nAlphaValueSlider / g_nMaxAlphaValue;
	//则beta值为1减去alpha值
	g_dBetaValue = (1 - g_dAlphaValue);
    //根据alpha和beta值进行线性混合
	addWeighted(g_srcImage1, g_dAlphaValue, g_srcImage2, g_dBetaValue, 0.0, g_dstImage);
	//显示效果图
	imshow(WINDOW_NAME, g_dstImage);
}

//主函数
int main()
{
    //加载图像(两图像尺寸需相同)
	g_srcImage1 = imread("1.jpg");
	g_srcImage2 = imread("2.jpg");
	if (!g_srcImage1.data)
	{
		printf("第一张读取错误\n");
		return -1;
	}
	if (!g_srcImage2.data)
	{
		printf("第二张读取错误\n");
		return -1;
	}
	//设置滑动条初始值为70
	g_nAlphaValueSlider = 70;
	//创建窗体
	namedWindow(WINDOW_NAME, 1);
	//在创建的窗体中创建一个滑动条控件
	char TrackbarName[50];
	sprintf(TrackbarName, "透明度%d", g_nMaxAlphaValue);
	createTrackbar(TrackbarName, WINDOW_NAME, &g_nAlphaValueSlider, g_nMaxAlphaValue, on_Trackbar);
	//结果在回调函数中显示
	on_Trackbar(g_nAlphaValueSlider, 0);
	waitKey(0);
	return 0;

}

自行下载两张图片后,改名分别为1和2,然后注意放在和此.cpp文件放在同一路径下,否则读取图片时需要提供完整的图片存放路径。运行后产生如下错误:
opencv图像混合报错问题_第1张图片

在这里插入图片描述
点击【继续】也可以出现两张图片重叠的效果图,但是会发现无法拖动滑动条,一拖动就又会弹出上面的报错窗口。而且,当把透明度设置为0时,发现并没有使得第二张图完全显示,反而变成了全灰。出现这一系列的原因在于:

两张图片像素尺寸不匹配,需要自行改变两张图片的像素尺寸使其一致。

opencv图像混合报错问题_第2张图片

OpenCV Error: Sizes of input arguments do not match (The operation is neither 'array op array' (where arrays have the same size and the same number of channels), nor 'array op scalar', nor 'scalar op array') in cv::arithm_op, file ..\..\..\..\opencv\modules\core\src\arithm.cpp, line 1287

解决办法:

改变图片像素尺寸的方式有很多,比如可以通过PS技术进行改变,但是opencv提供了各种函数接口用来处理图像,我们可以使用resize()函数来改变。
resize是opencv库中的一个函数,其函数功能是缩小或者放大图像至某一个大小。
函数原型为:

void resize( InputArray src, OutputArray dst,
                          Size(width,height), double fx = 0, double fy = 0,
                          int interpolation = INTER_LINEAR );

其中src为待改变大小的图像变量名;dst为改变大小之后的图像变量名;Size(width,height)为图像改变成为的指定像素大小;fx是width方向的缩放比例,如果它是0,那么它就会按照(double)dsize.width/src.cols来计算;fy是height方向的缩放比例,如果它是0,那么它就会按照(double)dsize.height/src.rows来计算;图像缩放之后需对像素要进行重新计算,interpolation参数来指定重新计算像素的方式,不指定时默认使用双线性插值,即INTER_LINEAR。
在读入图片后我们加上这个函数,就可以顺利运行,添加修改语句为:

	Mat img1 = imread("1.jpg");//定义两个Mat类型的存放读入图片的变量
	Mat img2 = imread("2.jpg");
	resize(img1, img1, Size(550, 320), 0, 0, CV_INTER_LINEAR);//改变读入图片的尺寸,使得两张融合图片的像素一致 否则融合会报错
	resize(img2, img2, Size(550, 320), 0, 0, CV_INTER_LINEAR);
	g_srcImage1 = img1;
	g_srcImage2 = img2;

需要注意:图片究竟尺寸改成多大还需看一下图片原始信息,改变后的像素值尽量不要和原图有过大出入,比如原图是30 * 20像素的图片,我们改成550 * 320效果可能就不太好。原始图片像素查询方法为:选中图片并右键,选择【属性】,再选择【详细信息】,就可以看到了。
opencv图像混合报错问题_第3张图片

修改后的完整代码:

#include
#include
using namespace cv;
#define WINDOW_NAME "线性混合"

const int g_nMaxAlphaValue = 100;
int g_nAlphaValueSlider;
double g_dAlphaValue;
double g_dBetaValue;

Mat g_srcImage1;
Mat g_srcImage2;
Mat g_dstImage;

void on_Trackbar(int, void*)
{
	g_dAlphaValue = (double)g_nAlphaValueSlider / g_nMaxAlphaValue;
	g_dBetaValue = (1 - g_dAlphaValue);

	addWeighted(g_srcImage1, g_dAlphaValue, g_srcImage2, g_dBetaValue, 0.0, g_dstImage);
	imshow(WINDOW_NAME, g_dstImage);
}

int main()
{
/*修改的部分*/
//............................................................................................//
	Mat img1 = imread("1.jpg");//定义两个Mat类型的存放读入图片的变量
	Mat img2 = imread("2.jpg");
	resize(img1, img1, Size(550, 320), 0, 0, CV_INTER_LINEAR);//改变读入图片的尺寸,使得两张融合图片的像素一致 否则融合会报错
	resize(img2, img2, Size(550, 320), 0, 0, CV_INTER_LINEAR);
	g_srcImage1 = img1;
	g_srcImage2 = img2;
//...........................................................................................//
	if (!g_srcImage1.data)
	{
		printf("第一张读取错误\n");
		return -1;
	}
	if (!g_srcImage2.data)
	{
		printf("第二张读取错误\n");
		return -1;
	}
	g_nAlphaValueSlider = 70;
	namedWindow(WINDOW_NAME, 1);
	char TrackbarName[50];
	sprintf(TrackbarName, "透明度%d", g_nMaxAlphaValue);
	createTrackbar(TrackbarName, WINDOW_NAME, &g_nAlphaValueSlider, g_nMaxAlphaValue, on_Trackbar);
	on_Trackbar(g_nAlphaValueSlider, 0);
	waitKey(0);
	return 0;

}

运行结果:
opencv图像混合报错问题_第4张图片
可以看到没有任何报错弹出,此时滑动条也可以通过鼠标流畅滑动。
【这张混合后的图片还蛮好看的,有种灵魂叠加的感觉~】
opencv图像混合报错问题_第5张图片
opencv图像混合报错问题_第6张图片
opencv图像混合报错问题_第7张图片
opencv图像混合报错问题_第8张图片

你可能感兴趣的:(opencv,C/C++,opencv)