}
程序说明:
1)CV_Assert( !img.empty() ); 检查出错警告语句。括号内是检测的内容,!img.empty() 的意思是:如果img图像为空,则返回0,否则返回1。
原型是宏定义:#define CV_Assert( expr ) if((expr)) ; else cv::error( cv::Exception(CV_StsAssert, #expr, "", __FILE__, __LINE__) )
如果条件expr为真,则不用执行什么操作,如果为假,则执行出错函数error()。error()函数调用Exception基类的对象。
而error()的原型是:CV_EXPORTS void error( const Exception& exc );这是出错提示函数,里面的参数是Exception对象的常引用。我们来看exception类。
Exception(异常处理机制),早期的C语言的异常处理机制,通常是人为的对返回结果加一些标志来进行判定。C语言的异常处理机制全是人为的定义,这样就会造成业务逻辑的主线受到异常处理的牵制,或者说是难免会将注意力转移,并且造成业务逻辑与异常处理之间有很大程度上的缠绕。
为什么要自定义自己的Exception ,Java Exception机制与传统的C语言的异常处理机制有什么不同,这种Exception机制的意义在什么地方?接下来咱就来和你一起探讨Exception 的优缺点。
早期的C语言的异常处理机制,通常是我们人为的对返回结果加一些标志来进行判定,比如发生错误返回什么标志,正常情况下我们又是返回什么标记,而这些都不是语言本身所赋予我们的,而对于C语言这种机制又有什么问题哩?为什么新一代的语言 Java Ruby C# 等都用Exception机制而不是维持C语言的老样子?这些都是我们需要思考的问题。
C语言的异常处理机制全是我们人为的定义,这样就会造成业务逻辑的主线受到异常处理的牵制,或者说是我们难免会将注意力转移,并且造成业务逻辑与异常处理之间有很大程度上的缠绕。
中止模型
假设错误非常严重,已至你无法在回到错误发生的地方,也就是说,这段程序经过判断认为,他已经没有办法挽回,于是就抛出异常,希望这个异常不要在回来,这也是Java 当前所采用的模式。
继续模型
这种模型的主旨是恢复当前的运行环境,然后希望能够重新回到错误的发生地,并希望第二次的尝试能够获得成功,这种模型通常为操作系统所应用。
Exception类是从基类exception派生出来的派生类。
class CV_EXPORTS Exception : public std::exception
{
public:
/*!Default constructor*/
Exception();
/*!
Full constructor. Normally the constuctor is not called explicitly.
Instead, the macros CV_Error(), CV_Error_() and CV_Assert()are used.
*/
Exception(int _code, const string& _err, const string& _func, const string& _file, int _line);
virtual ~Exception() throw();
/*!\return the error description and the context as a text string.*/
virtual const char *what() const throw();
void formatMessage();
string msg; ///< the formatted error message
int code; ///< error code @see CVStatus
string err; ///< error description
string func; ///< function name. Available only when the compiler supports __func__ macro
string file; ///< source file name where the error has occured
int line; ///< line number in the source file where the error has occured
};
class _CRTIMP_PURE exception
{ // base of all library exceptions
public:
_EXCEPTION_INLINE __CLR_OR_THIS_CALL exception();
_EXCEPTION_INLINE explicit __CLR_OR_THIS_CALL exception(const char * const &);
_EXCEPTION_INLINE __CLR_OR_THIS_CALL exception(const char * const &, int);
_EXCEPTION_INLINE __CLR_OR_THIS_CALL exception(const exception&);
_EXCEPTION_INLINE exception& __CLR_OR_THIS_CALL operator=(const exception&);
_EXCEPTION_INLINE virtual __CLR_OR_THIS_CALL ~exception();
_EXCEPTION_INLINE virtual const char * __CLR_OR_THIS_CALL what() const;
private:
_EXCEPTION_INLINE void __CLR_OR_THIS_CALL _Copy_str(const char *);
_EXCEPTION_INLINE void __CLR_OR_THIS_CALL _Tidy();
const char * _Mywhat;
bool _Mydofree;
};
2)mask.at<uchar>(y+1, x+1) == 0。运用at方式来操作像素元素,详细关于at函数原型如下:
template<typename _Tp> inline _Tp& Mat::at(Point pt)
{
CV_DbgAssert( dims <= 2 && data && (unsigned)pt.y < (unsigned)size.p[0] &&
(unsigned)(pt.x*DataType<_Tp>::channels) < (unsigned)(size.p[1]*channels()) &&
CV_ELEM_SIZE1(DataType<_Tp>::depth) == elemSize1());
return ((_Tp*)(data + step.p[0]*pt.y))[pt.x];
}
关键来看最后一句,return ((_Tp*)(data + step.p[0]*pt.y))[pt.x]。data是图像数据的首地址。data+的是地址的偏移量,step是步长,即是行与行像素之间的间距;而step.p[0]是一行像素元素的首地址。step.p[0]*pt.y则是每一行像素元素的首地址。括号外面的则是用于控制列变量的pt.x,其中pt.x和pt.y是at函数的Point类型的参数。分别用于控制列和行像素。
3)