The OpenCV Coding Style Guide

The source of this document is here.

1. Foreword

The document is a short guide on code style, used in OpenCV. The core libraries (cv, cvaux) are written in C/C++, so the document concerns only the codes written in C/C++.

2. File Names

All the file names of cv and cvaux libraries must obey the following rules:

3. File Structure

Every file starts with BSD-compatible license, which template can be found in Contributors_BSD_License.htm file. Other rules for both header and implementation files include:

Header files must use guarding macros, protecting the files from repeated inclusion.

Mixed C/C++ interface header files contain extern "C"{}, surrounding C definitions.

Source files must include precomp.h header before other headers, in order to make precompiled headers mechanism in Visual C++ work properly.

Also, look at the samples of header file and implementation file.

4. Naming conventions

OpenCV uses mixed-case style identifiers for external functions, types and class methods.

Macros are written with all capital letters, words are separated by underscore.

All the external names or internal names, visible across several files, must have prefixes:

5. Designing function interfaces

It is important to design function interface is such a way, consistent with the rest of the library. The elements of function interface include:

Functionality must be well defined and non-redundant. The function should be easy embedded into different processing pipelines that use other OpenCV and IPL functions. Name should be simple to derive it from what the function does. There are a few common naming patterns in OpenCV:

Return value should be chosen to simplify function usage. Generally, a function that creates an object should return it. It is the good practice to do so for the functions, producing dynamic data structures or scalar values. However, in case of image processing function it would lead to often allocation/deallocation of large memory blocks, so the image processing functions don't create and return result images rather than modify an output image, passed as a parameter.

Functions should not use return value for signaling about critical errors, such as null pointers, division by zero, bad argument range, unsupported image format etc. There is a special error handling mechanism, similar to that used in IPL, for this purpose. And vice versa, it is better to use return value for signalizing about expected run-time situations (e.g. tracked object goes beyond the screen etc.)

Argument types are preferably chosen from the already existing set of OpenCV types: IplImage for raster images, CvMat for matrices, CvSeq for contours etc. It is not recommended to use plain pointers and counters, because it lowers library interface and makes programs harder to read, because of numerous function parameters.

A consistent argument order is important because it becomes easier to remember the order and it helps programmer to avoid errors, connecting with wrong argument order.

Input parameters usually have const qualifiers. Optional arguments often simplify function usage. Because C++ allows optional arguments in the end of parameters list only, it also may affect decisions on argument order—the most important flags go first and less important—after. In function declaration use CV_DEFAULT macro for specifying default values of optional arguments. It makes the declaration compatible with C.

For example function declaration look at cvexample.h, as well as cv.h and cvaux.h.

6. Implementing functions

The section concerns the following topics:

As it was said in the previous section, OpenCV functions extensively use high- level data types for passing/returning parameters. It simplifies functions use, but increases probability of calling a function with wrong combination of arguments (e.g. floating-point image instead of byte-depth image, or two images with unmatched sizes). There exist standard methods for checking arguments of one of standard types.

An IplImage image can be checked via CV_CHECK_IMAGE macro. The macro checks that the passed pointer to IplImage and underlying image data pointer are not NULL, image has pixel order, does not have mask ROI or tiling information.

CV_CHECK_MASK_IMAGE is useful for checking mask images, binary or grayscale images. Besides the conditions CV_CHECK_IMAGE checks, it also ensures that image has 8bit depth and a single channel.

Further, all input and output images should be checked for allowed combinations of depths, channel numbers, sizes. The latter may be checked after calling cvGetImageRawData function that returns an image ROI size.

Input contours and other dynamical data structures can be checked using CV_IS_CONTOUR and related macros.

Whenever bad argument is passed to the function or other critical error happened during the function execution, it should raise an error via function cvError. There is a standard error handling mechanism in OpenCV, similar to IPL the most of all and to the standard C library in less degree. That is, instead of returning error code there exists global error status that can be:

Besides setting the error status to the specified value, cvError can take some additional actions, depending on error processing mode, that can be adjusted via cvSetErrorMode. In silent mode or parent mode cvError returns immediately. In child mode it prints out an error message and then terminate the application.

Instead of above functions one can use macros, which are more convenient to use:

CV_* macros require "FuncName" string variable and "exit" label be defined in the function, OPENCV_* don't. Temporary buffers in OpenCV are allocated using cvAlloc and cvFree functions. The functions take care of proper alignment, keep track on unreleased memory, check buffer overflow. cvAlloc raises an error when the program runs out of memory. The functions call lower level functions that can be set by the user to give him a full control over memory allocation. So, it is strongly recommended to use these functions. The said above refers only to simple buffers. Temporary images, memory storages and other structures that are created/released using their cvCreate<Object>/cvRelease<Object> should be allocated/deallocated this way (the Create/Release functions call cvAlloc/cvFree internally).

If error occurs and one of the macros CV_ERROR or CV_CALL is used, the control is passed to exit label. The same can be done in the normal program flow by the EXIT macro. The label can be defined either manually or via __BEGIN__ and __END__ macros. The label is introduced for resource deallocation. Memory leaks usually happen when program flow passes though rarely executed branches. One of these cases is connected with using a return statement in one of branches.

The technique, used in the library, helps programmer to avoid most of memory leaks. In the beginning of a function all the pointers are cleared (usually during the initialization). After "exit" label cvFree is called for every pointer. cvFree handles null pointers safely. Inside the function return statement is replaced with EXIT. Thus, we guarantee that memory is deallocated. Of course, we can forget to call cvFree for some blocks, but then leak will happen each time the function executed and thus easy to catch.

Low-level functions in OpenCV are mostly C implementations of primitive operations that present in IPP as well. They differ from previously discussed high-level functions in level of the interface (they take plain pointers and counters, almost no structures) and error processing methodology (they return error code instead of setting global error status). The convenient and safe way to call the function is to use IPPI_CALL macro.

For example function implementation look at cvexample.cpp file.

7. Code Layout

There is a single string rule in OpenCV about code layout: every file must use consistent formatting style.

Currently used in OpenCV and recommended formatting style looks as follows:

   1     if( a > 5 )
   2     {
   3         int b = a*a;
   4         c = c > b ? c : b + 1;
   5     }
   6     else if( abs(a) < 5 )
   7     {
   8         c--;
   9     }
  10     else
  11     {
  12         printf( "a=%d is far to negative\n", a );
  13     }

Other styles might be also accepted if only the above rule is met. That is, if one changes written by others code, he (she) should use the same coding style.

8. Portability

All the codes must be compliant with the following standards:

One should get rid of compiler-dependent or platform-dependent constructions and system calls, such as:

9. Writing documentation on functions

The documentation for contributed functions is written in HTML, because the format provides text formatting capabilities and hyperlinks, and at the same time it is pretty simple to use and to maintain. Documentation for each function or for group of related functions is placed into separate file, which is referenced from the main page.

Here is an prototype of the main page that contains link to example documentation on the function, implemented in cvexample.cpp

Take a look at these pages and at the corresponding HTML code, containing comments about formatting details. You may make a copy of function documentation HTML, change it appropriately and add a link to it into the index page.

The basic elements of function documentation HTML file include (in that order):

10. Implementing tests for functions

Each test is implemented as C/C++ function that inputs data from text file and outputs results to another text file. Thus, the function has the following interface:

bool <TestName>( const char* inputfile, const char* output file );

Format of input and output files is not defined. However, if the test system functions are used to read/write high-level data (matrices, filenames, contours etc.) from files, the format of the files should be compatible with the functions.

The external or "master" test function executes all or selected tests and compares their output with etalon results, that can be created by other programs or by the same tests in one of the previous executions.

Using this scheme it is possible to implement as tests that check a function on several particular data sets, as well as tests that compare function output with output of etalon function on arbitrary data. In this case output file can be formed as a difference between the two outputs and "etalon results" from the previous paragraph will be all zeros.

There is a test system API that makes test implementation easier. This includes:

Here is step-by-step description of how to implement test with examples:

Create a file with test body:

That is it. After that the test system may be executed in different modes.

11. Useful Tips

Some of OpenCV functions take small structures on input. Let's name of the structure type be CvSomething. Then cvSomething is usually an inline function, constructing the object from the list of arguments. Use of these inline constructors makes the code easier to write and read.

Use cvRound, cvFloor and cvCeil for fast conversion floating point number to integer with rounding to the nearest, to minus infinity, to plus infinity. On x86 architecture the functions are much faster than simple cast operations. There are standard functions in C9X standard to do the same thing, but they are poorly supported right now. When it happens, the above functions will turn to just one-line macros.

12. Appendixes

Appendix A. References The document is not a complete style guide. Far more detailed and well-written papers on this topic are listed below:

Appendix B. The brief list of rules

Appendix C. The list of examples and references

CodingStyleGuide (last edited 2008-02-29 23:49:19 by GuyKloss)

SourceForge.net Logo