|
- Starting new block
- Implementing the block
- Internal parameters
- IO Types
- Available macros and methods
Starting new block
- The blocks are written in C++ and compiled and linked into a shared, dynamically linked library.
- The best way to start, is to use a perl script, available in ##blocks/util/XaiBlock2HTML## directory - ##create_block.pl##
- The script requires two things: a block specification file and a template directory. The latter can be found in ##blocks/util/BlockTemplate##. Just copy the template directory to a place where You want to work on Your block.
- The block specification file is a little more cumbersome. Here is an example specification (covering all possible options):
block IPLSmooth {
path = "/OpenCV";
description = <<"MAINDESC"
The function cvSmooth smooths image using one of several methods
MAINDESC
inputs = [
{
name = ipl_image;
description = "";
type = IOOpenCVIPL
}
];
outputs = [
{
name = ipl_image;
description = "";
type = IOOpenCVIPL
}
];
parameters = [
{
name = smoothtype;
description = "Type of the smoothing";
type = EnumParameter;
values = {
CV_BLUR_NO_SCALE = CV_BLUR_NO_SCALE;
CV_BLUR = CV_BLUR;
CV_GAUSSIAN = CV_GAUSSIAN;
CV_MEDIAN = CV_MEDIAN;
CV_BILATERAL = CV_BILATERAL;
};
default = CV_BLUR_NO_SCALE
},
{
name = param1;
description = "The first parameter of smoothing operation";
type = IntegerParameter;
default = 3;
},
{
name = param2;
description = "The second parameter of smoothing operation";
type = IntegerParameter;
default = 0;
}
];
}
|
Implementing the block
The output from the example specification above is presented below. In order to
get a functioning block, You have to implement at least the run() and reset()
methods. The first one takes the inputs and/or the parameters and updates the outputs of the block, if any.
Let's go through the resulting parts of the block one by one:
-
The constructor
This constructor was automatically generated simply from the above specification.
IPLSmooth::IPLSmooth() {
name = "IPLSmooth";
path = "/OpenCV/Image_Processing_and_Analysis/";
description = "The function cvSmooth smooths image using ...";
inputs.clear();
outputs.clear();
// Inputs
addInput(Input("ipl_image", "", new IOType<IplImage>()));
// Outputs
addOutput(Output("ipl_image", "", new IOType<IplImage>()));
// Parameters
EnumParameter* par0 = new EnumParameter("smoothtype");
par0->setValue("CV_BLUR_NO_SCALE");
par0->addValueForKey("CV_BLUR", CV_BLUR);
par0->addValueForKey("CV_BLUR_NO_SCALE", CV_BLUR_NO_SCALE);
par0->addValueForKey("CV_GAUSSIAN", CV_GAUSSIAN);
par0->addValueForKey("CV_MEDIAN", CV_MEDIAN);
par0->addValueForKey("CV_BILATERAL", CV_BILATERAL);
addParameter(par0);
IntParameter* par1 = new IntParameter("param1", 3);
addParameter(par1);
IntParameter* par2 = new IntParameter("param2", 0);
addParameter(par2);
output_image = NULL;
}
|
-
The run() method
This method is more tricky, since it contains the logic of the block. If the method needs to maintain state
between the calls (iterations of algorithm) the variables representing the state must be declared
as private fields of the class in the blocks header file.
It is best to keep the code of this method as optimal as possible. Especially such things as
memory allocation or initialization should be done only when necassary (preferably once).
For instance the first block of this method, allocates a new IplImage structure. Note, that it
cannot be done before the actual execution of the algorithm, since otherwise we wouldn't know
some of the parameters of the actual input data, such as size or depth. If the block
that provides this input is for instance a AVI file reader, this block will adapt to its resolution
and depth.
Next step is the extraction of input data from the inputs. This will be more detailed in the section
on the type system of Xai, for now, we can see that we have to take the input we want using simple index
(inputs is a std::vector object). The input has a pointer to the output that is connected to this input
and from this output we can extract the interesting information.
After we have input data, we can extract current values of internal parameters of the block.
There exists only a limited amount of parameter types, so some convienience macros are defined
to help with there extraction.
When we have the inputs and parameters we can now perform the actual operation of the block,
here it is simply the cvSmooth() method from OpenCV library.
Finally, we assign the obtained result to the proper outputs of the block. When the method is
finished, the blocks that wait on this output will be able to use it.
void IPLSmooth::run(void) {
//
// Get the input image
//
IplImage* input_image = GET_INPUT_DATA(IplImage, 0);
//
// Create new image with proper parameters depending on input image
//
if(!output_image_created) {
CvSize input_img_size;
input_img_size.width = input_image->width;
input_img_size.height = input_image->height;
int depth = input_image->depth;
int nchannel = input_image->nChannels;
output_image = cvCreateImage(input_img_size, depth, nchannel);
XAILOGCPP(XAIINFO, getName()<<": Creating output image ");
output_image_created = true;
}
//
// Get internal parameter values
//
int smoothtype = GET_ENUM_PARAM_VALUE("smoothtype");
int param1 = GET_INT_PARAM_VALUE("param1");
int param2 = GET_INT_PARAM_VALUE("param2");
//
// Perform the operation
//
cvSmooth(input_image, output_image, smoothtype, param1, param2);
//
// Assign the output data
//
SET_OUTPUT_DATA(IplImage, 0, output_image);
}
|
-
The reset() method
The reset() method is called when the algorithm is stopped. So in order to avoid memory leaks
in the blocks, each block should release all memory that he allocated in method run().
void IPLSmooth::reset() {
output_image_created = false;
if(output_image != NULL) {
cvReleaseImage(&output_image);
output_image = NULL;
}
}
|
Internal parameters
The internal parameters of the blocks can be of the following types:
Parameter type |
Description |
integer |
implemented by class xai::IntParameter |
float |
implemented by class xai::FloatParameter |
double |
implemented by class xai::DoubleParameter |
string |
implemented by class xai::StringParameter, wraps standard std::string class |
enum |
implemented by class xai::EnumParameter, contains a std::map with (name, value) mappings. |
Input and Output types
See API docs here
Available macros and methods
Accessing inputs and outputs:
Macro name |
Description |
GET_INPUT_DATA(type, io_number) |
Returns the pointer to data from input 'io_number' casted to type. |
SET_OUTPUT_DATA(type, io_number, data) |
Sets the 'io_number's output data to 'data' casted to type. |
Accessing block params:
Macro name |
Description |
GET_INT_PARAM_VALUE() |
Returns the int value for given name of the parameter (e.g. GET_INT_PARAM_VALUE("threshold") |
GET_STRING_PARAM_VALUE() |
Returns std::string value for given name |
GET_DOUBLE_PARAM_VALUE() |
Returns double value for param name |
GET_FLOAT_PARAM_VALUE() |
Returns float value for param name |
GET_ENUM_PARAM_VALUE() |
Returns current selected value of enumeration for given name |
Error handling methods:
Macro name |
Description |
XAI_REPORT_INFO() |
Reports to subscribers (e.g. the GUI) some information of low priority - XAI_REPORT_INFO("Calculated first frame") |
XAI_REPORT_WARNING() |
Reports to subscribers (e.g. the GUI) some information of higher priority - XAI_REPORT_WARNING("Processing empty image") |
XAI_REPORT_ERROR() |
Reports to subscribers (e.g. the GUI) some information of highest priority, this call stops the algorithm - XAI_REPOTR_WARNING("Cannot open input file") |
STOP_ALGORITHM() |
This macro can be called from any point in the run() method. It immediately stops the algorithm execution.
Preferably You should use XAI_REPORT_ERROR() since it also allows You to forward some meaningful message to the user.
|
|