Skip to content

cisstStereoVision tutorial 5

Anton Deguet edited this page May 6, 2014 · 5 revisions

cisstStereoVision Architecture

Example 5 - Filters with multithreaded processing

List of files

  • CMakeLists.txt: CMake script for creating compiler dependent projects
  • CMyFilter2.h: Custom filter 2 class declaration
  • CMyFilter2.cpp: Custom filter 2 class definition
  • CMyFilter3.h: Custom filter 3 class declaration
  • CMyFilter3.cpp: Custom filter 3 class definition
  • main.cpp: Application entry point (main() function)

All files can be found under cisstStereoVision/examples/tutorial2.

Source code

CMake

PROJECT(svlTutorial4)

FIND_PACKAGE(cisst REQUIRED)

IF(cisst_FOUND)

    INCLUDE(${CISST_USE_FILE})

    ADD_EXECUTABLE(${PROJECT_NAME}
                   CMyFilter2.h
                   CMyFilter2.cpp
                   CMyFilter3.h
                   CMyFilter3.cpp
                   main.cpp
                   )

    CISST_TARGET_LINK_LIBRARIES(${PROJECT_NAME} cisstCommon cisstVector cisstOSAbstraction cisstMultiTask cisstStereoVision)

ENDIF(cisst_FOUND)

Custom filter 2 class declaration

#include <cisstStereoVision/svlFilterBase.h>

class CMyFilter2 : public svlFilterBase
{
public:
    CMyFilter2();

protected:
    int Initialize(svlSample* syncInput, svlSample* &syncOutput);
    int Process(svlProcInfo* procInfo, svlSample* syncInput, svlSample* &syncOutput);
};

Custom filter 2 class implementation

#include "CMyFilter2.h"

CMyFilter2::CMyFilter2() :
    svlFilterBase()                                                         // Call baseclass' constructor
{                                                                           //
    AddInput("input", true);                                                // Create synchronous input connector
    AddInputType("input", svlTypeImageRGB);                                 // Set sample type for input connector
                                                                            //
    AddOutput("output", true);                                              // Create synchronous output connector
    SetAutomaticOutputType(true);                                           // Set output sample type the same as input sample type
}

int CMyFilter2::Initialize(svlSample* syncInput, svlSample* &syncOutput)
{
    syncOutput = syncInput;                                                 // Pass the input sample forward to the output
    return SVL_OK;                                                          //
}

int CMyFilter2::Process(svlProcInfo* procInfo, svlSample* syncInput, svlSample* &syncOutput)
{
    svlSampleImageRGB* image = dynamic_cast<svlSampleImageRGB*>(syncInput); // Cast input sample to RGB image type
    svlRGB* pixel = reinterpret_cast<svlRGB*>(image->GetUCharPointer());    // Get RGB pixel buffer for in-place modifications
    unsigned int pixelcount = image->GetWidth() * image->GetHeight();       // Get number of pixels in image
    unsigned int i, res;                                                    //
                                                                            //
    _ParallelLoop(procInfo, i, pixelcount)                                  //
    {                                                                       //
        res  = pixel[i].r;                                                  // process data
        res += pixel[i].g;                                                  //
        res += pixel[i].b;                                                  //
        res /= 3;                                                           //
        pixel[i].r = pixel[i].g = pixel[i].b = res;                         //
    }                                                                       //
                                                                            //
    syncOutput = syncInput;                                                 // Pass the modified sample forward to the output
                                                                            //
    return SVL_OK;                                                          //
}

Custom filter 3 class declaration

#include <cisstStereoVision/svlFilterBase.h>

class CMyFilter3 : public svlFilterBase
{
public:
    CMyFilter3();

protected:
    int Initialize(svlSample* syncInput, svlSample* &syncOutput);
    int Process(svlProcInfo* procInfo, svlSample* syncInput, svlSample* &syncOutput);
    
private:
    unsigned int MaxVal;
};

Custom filter 3 class implementation

#include "CMyFilter3.h"

CMyFilter3::CMyFilter3() :
    svlFilterBase()                                                         // Call baseclass' constructor
{                                                                           //
    AddInput("input", true);                                                // Create synchronous input connector
    AddInputType("input", svlTypeImageRGB);                                 // Set sample type for input connector
                                                                            //
    AddOutput("output", true);                                              // Create synchronous ouput connector
    SetAutomaticOutputType(true);                                           // Set output sample type the same as input sample type
}

int CMyFilter3::Initialize(svlSample* syncInput, svlSample* &syncOutput)
{
    syncOutput = syncInput;                                                 // Pass the input sample forward to the output
    return SVL_OK;                                                          //
}

int CMyFilter3::Process(svlProcInfo* procInfo, svlSample* syncInput, svlSample* &syncOutput)
{
    svlSampleImageRGB* image = dynamic_cast<svlSampleImageRGB*>(syncInput); // Cast input sample to RGB image type
    svlRGB* pixel = reinterpret_cast<svlRGB*>(image->GetUCharPointer());    // Get RGB pixel buffer for in-place modifications
    unsigned int pixelcount = image->GetWidth() * image->GetHeight();       // Get number of pixels in image
    unsigned int i, val;                                                    //
                                                                            //
    _OnSingleThread(procInfo)                                               // Execute the following block on one thread only
    {                                                                       //
        MaxVal = 0;                                                         // Find highest intensity pixel
        for (i = 0; i < pixelcount; i ++) {                                 //
            val = (unsigned int)pixel[i].r + pixel[i].g + pixel[i].b;       //
            if (val >= MaxVal) MaxVal = val;                                //
        }                                                                   //
        MaxVal /= 3;                                                        //
    }                                                                       //
                                                                            //
    _SynchronizeThreads(procInfo);                                          // All threads wait until finished
                                                                            //
    if (MaxVal > 0) {                                                       //
        _ParallelLoop(procInfo, i, pixelcount)                              // Parallelized loop, executed on all threads
        {                                                                   //
            val = 255 * pixel[i].r / MaxVal;                                // Normalize image intensity to 255,
            if (val > 255) val = 255;                                       //   saturate color component if needed
            pixel[i].r = val;                                               //
                                                                            //
            val = 255 * pixel[i].g / MaxVal;                                //
            if (val > 255) val = 255;                                       //
            pixel[i].g = val;                                               //
                                                                            //
            val = 255 * pixel[i].b / MaxVal;                                //
            if (val > 255) val = 255;                                       //
            pixel[i].b = val;                                               //
        }                                                                   //
    }                                                                       //
                                                                            //
    syncOutput = syncInput;                                                 // Pass the modified sample forward to the output
                                                                            //
    return SVL_OK;                                                          //
}

Main program

#include <cisstStereoVision.h>
#include "CMyFilter2.h"
#include "CMyFilter3.h"

int main()
{
    svlInitialize();                                                // Discover supported devices and codecs
                                                                    //
    svlStreamManager stream(2);                                     // Instantiate SVL Stream
    svlFilterSourceVideoCapture source(1);                          // Instantiate video capture filter
    svlFilterSplitter splitter;                                     // Instantiate splitter filter
    CMyFilter2 filter2;                                             // Instantiate user-implemented filter #2
    CMyFilter3 filter3;                                             // Instantiate user-implemented filter #3
    svlFilterImageWindow window1;                                   // Instantiate image window filter #1
    svlFilterImageWindow window2;                                   // Instantiate image window filter #2
                                                                    //
    source.SetDevice(0);                                            // Select first available capture device
                                                                    //
    splitter.AddOutput("asyncbranch", 2, 3);                        // Add second output (async) to splitter
                                                                    //
    window1.SetTitle("Main branch");                                // Assign title text to window filter #1
    window2.SetTitle("Side branch");                                // Assign title text to window filter #2
                                                                    //
    stream.SetSourceFilter(&source);                                // Assign source filter to stream
    source.GetOutput()->Connect(splitter.GetInput());               // Connect source filter to splitter filter
    splitter.GetOutput()->Connect(filter2.GetInput());              // Connect splitter filter to filter #2
    splitter.GetOutput("asyncbranch")->Connect(filter3.GetInput()); // Connect splitter filter to filter #3
    filter2.GetOutput()->Connect(window1.GetInput());               // Connect filter #2 to window #1
    filter3.GetOutput()->Connect(window2.GetInput());               // Connect filter #3 to window #2
                                                                    //
    stream.Play();                                                  // Initialize and Play video stream
                                                                    //
    char ch;                                                        //
    std::cin >> ch;                                                 // (Wait for key-press)
                                                                    //
    stream.Release();                                               // Release stream
                                                                    //
    return 0;                                                       //
}
Clone this wiki locally