先贴源代码,及问题;
// 转换为灰度图像
cvtColor( src, src_gray, CV_RGB2GRAY );
// 创建X、Y方向梯度图像变量
Mat grad_x, grad_y;
Mat abs_grad_x, abs_grad_y; // 梯度绝对值
// X方向梯度 并取绝对值
Sobel( src_gray, grad_x, ddepth, 1, 0, 3, scale, delta, BORDER_DEFAULT );
convertScaleAbs( grad_x, abs_grad_x );
// Y方向梯度 并取绝对值
Sobel( src_gray, grad_y, ddepth, 0, 1, 3, scale, delta, BORDER_DEFAULT );
convertScaleAbs( grad_y, abs_grad_y );
Mat result(Size(512,512), CV_32F);
/*
采用cv函数计算梯度值
*/
cv::pow(abs_grad_x, 2.0f,abs_grad_x);
cv::pow(abs_grad_y, 2.0f,abs_grad_y);
cv::add(abs_grad_x,abs_grad_y,result); //问题代码所在
cv::pow(result, 0.5f,result); // 出错的地方
waitKey( 0);
return 0;
上述代码,基础部分参见opencv sobel_demo代码,2范数梯度计算部分为新加,原始代码是加权求和计算梯度;上述代码运行出错,错误信息如下:
what(): /http://www.cnblogs.com/OpenCV-2.3.1/modules/core/src/mathfuncs.cpp:1898: error: (-215) depth == CV_32F || depth == CV_64F in function pow
内容是指pow函数参数的类型不对,pow中指数为小数或者负数的时候要求图像类型为float或double。
但是明明上面声明result变量时,类型是CV_32F ;问题很诡异。
调试策略:为了搞清楚result变量的类型,首先在创建对象前输出了result.type()的值,结果很正确是5(即CV_32F) ;
同时监视,代码出错时变量的类型,发现是1;
猜想,应该是出错前执行的操作改变了result变量的type;
通过排查发现,唯一设计操作result变量的代码:cv::add(abs_grad_x,abs_grad_y,result);
问题就应该在这里了。
查看手册及函数原型:
CV_EXPORTS_W void add(InputArray src1, InputArray src2, OutputArray dst,
InputArray mask=noArray(), int dtype=-1);
原始调用时,两个缺省值没有改变,这两个值颇有嫌疑;下面为手册中的变量说明:
mask – Optional operation mask, 8-bit single channel array, that specifies elements of the
destination array to be changed. //这个可以不关心
dtype – Optional depth of the output array. 输出图像的深度depth就是由该变量定义的。
……略
手册中提到,如果两幅原图像的深度相同的话, dtype缺省为-1,并且输出图像与原图像深度相同。(关于深度与type之间的关系,还有待深入考究)
从而导致执行add操作后,result的type值就变化了,导致后面执行pow操作异常。
修正代码
代码运行正常了,ok。
另:问题总是很细小,很惹人纠结。