RobotVisionCAD or in short RvCAD is a computer aided design for Image Processing and Computer Vision, designed to take full advantage of multi-cpu(SMP)/multi-core and distributed computing environment. The idea is to divide a image processing tasks into smaller tasks(so called divide and conquer) called "Processor", each of these processors are connected together by FIFO queue called "Link", to form a "Pipeline" or Image Processing Pipeline. For example the pipeline in picture#0 below has 7 processors, each has number of input (represented with red circle) and output ports (represented with green circle), connected with link(blue line).
Picture#0 shows a pipeline
running. The pipeline finds moving objects from a sequence of images,
in this case from avi files.
Processor: A
Processor is abstract black box system, it has number of input ports
and output ports. A basic requirement of a Processor is to have at
least one input or output port. At the operating system level, a
Processor is a Thread. A Processor can be executed on an remote machine
in a TCP/IP network, while remains connected in a pipeline on a main
workstation machine.
-InputPort is where the sink end
of a Link connected to a Processor. An InputPort consumes Image
from a connected Link.
-OutputPort is where the source
end of a Link connected to a Processor. An OutputPort produces Image to
a connected Link
Link: A Link is a
FIFO queue of images, it connects Processors together to form a
Pipeline. Inside a Link is a collection of Images which are put in by
an OutputPort of a Processor. Image exits from a Link when an InputPort
of a Processor where the Link is connected, requests for a next Image
to be processed by the Processor. A Link can be setted have a limit or
a number of Images at one time.
-Source End is where Image enter to a Link.
-Sink End is where Image exits from a Link.
Pipeline: A Pipeline is a collection of Processors and Links which connect the Processors to form an Image Processing Pipeline. A Pipeline is said to be "Completed " when all in and output ports of all Processors in the Pipeline is connected correctly according to the following rules:
A Pipeline is said to be "Runable
" when the pipeline is completed.
A Pipeline can also be executed from a remote machine while remain
connected with a main pipeline on a main workstation machine.
RvCAD's GUI presents users with a view where users drag and drop Image Processor Elements, and visually connecting them to form Image Processing Pipeline. RvCAD's design window consist of 2 views: Processors Tree View on the left and Pipeline View on the right hand side. Processors in the left hand tree view are organized according to their Library(dynamic load library).
Using RvCAD is similar to using an electonic logic gate simulation program. Basically, you just drag and drop Processor from the left tree view, to the right pipeline view, then start connecting them by clicking at the Input(red triangle)or Output Pin(blue triangle) and draging link line to other RvCadProcessor input or output pin. To Remove a link just right clicking on one of the Port where the link is connected, then you will get a context menu, select "Delete Link Attached with this Port". To Remove all links from a Processor , right clicking on the processor then select "Delete All Links connected with this Processor".
Picture#1 shows context menu when right
clicking on output port number 0 of AviFileReader Processor.
Some processors need to be configured before running. For example AviFileReader needs to know the path to an avi file. To config a configurable processor, right clicking on the processor, select "Config this Processor" from the context menu, the processor will show its config dialog.
picture#2 shows context menu when right
clicking on AviFileReader processor.
gcc 3.3.x or higher on *Nix, XCode development tools on MacOS X.3.4 andVisual C++ 7.2 on Win32 Platform(NT4, W2K and XP).
A good programming knowledge of C++ and OOP.
A little knowledge of api on the target platforms(Win32, MacOS X and *Nix) is helpful.
General understand of Multithreaded Programming.
1)About Rv2::Image, Rv2::Pixel, Rv2::MetaData and Rv2::OverlayOfAnImage
1.1) Type Of Image
Image in Rv2 has multi channels pixel, and each channel is byte, long or float wide. There are 6 predefined type of image in Rv2 : Rv2::BinaryImage, Rv2::GrayScaleImage, Rv2::RgbColorImage, Rv2::IntegerImage, Rv2::RealImage and Rv2::ComplexImage. Rv2::Image itself is an abstract class and cannot be initiated.
Type Of Image |
Number Of Channel(s) per Pixel |
Channel Size |
Possible Value in each Channel |
| Rv2::BinaryImage | 1 | byte | 1, 0 (1 is black and 0 and white) |
| Rv2::GrayScaleImage | 1 | byte | 0 -> 255 (0 is white and 255 is black) |
| Rv2::RgbColorImage | 3 | byte | 0 <-> 255 |
| Rv2::IntegerImage | 1 | long | -XXX <-> max of long int |
| Rv2::RealImage | 1 | float | -XXX <-> max of float |
| Rv2::ComplexImage | 2 | float | -XXX <-> max of float |
1.2) Access and Manipulate Image
Accessing and manipulating pixel can be done by using method PixelAt(int iLinearPosition) or PixelAt(int x, int y) where iLinearPosition is a row major linear position of the pixel and x, y is column and row of the pixel. Generally using PixelAt(int iLinearPosition) is faster than PixelAt(int x, int y). Both methods returns reference to class Rv2::Pixel when you can use its public methods Get(..) and Set(..), for more infomation please look at class reference of the Rv2::Image and Rv2::Pixel. Code below is an example.
int main(intargc,char**argv)
{
Rv2::RgbColorImage RgbImage;
RgbImage.Allocate(80,60);// allocate RgbColorImage with width == 80 and
height == 60
//access it linearly
for(unsignedinti=0;i<RgbImage.LinearSize();i++)
{
//set pixel at position i to blue color
RgbImage.PixelAt(i).Set(0,0,255); // first channel is Red, Green and blue
repectively
//get pixel at position i;
Rv2::byter,g,b;
RgbImage.PixelAt(i).Get(&r,&g,&b);
}
//access it like matrix
for(unsignedintx=0;y<RgbImage.Width();x++)
{
for(unsignedinty=0;y<RgbImage.Height();y++)
{
//set pixel at position x,y to blue color
RgbImage.PixelAt(x,y).Set(0,0,255); // first channel is Red, Green and blue
repectively
//get pixel at position x,y;
Rv2::byter,g,b;
RgbImage.PixelAt(x,y).Get(&r,&g,&b);
}
}
return
0;
}
Neighborhood operations can be done using method NeighborAt(Rv2::TypeOfNeighbor iWhichNeightbor) of class Rv2::Pixel where iWhichNeighbor can be Rv2::eNorthWest, Rv2::eNorth, Rv2::eNorthEast, Rv2::eEast, Rv2::eSouthEast, Rv2::eSouth , Rv2::eSouthWest or Rv2::eWest. This method returns class Rv2::Pixel that iWhichNeighbor specifies.
int
main
( int
argc
,
char **
argv )
int r,
g, b ;
{
Rv2
:: RgbColorImage
img ,
img0 ,
img1 ,
img2 ;
img
. Allocate (
100 ,
100 );
//Setting
value of some pixels
img . PixelAt
( 9
,
9 ).
Set ( 9
,
9 ,
5
);
img
. PixelAt (
10 ,
9 ).
Set ( 10
,
9 ,
5
);
img
. PixelAt (
11 ,
9 ).
Set ( 11
,
9 ,
5
);
img
. PixelAt (
9 ,
10
). Set (
9 ,
10
,
5 );
img
. PixelAt (
11 ,
10 ). Set
( 11
,
10 ,
5 );
img
. PixelAt (
9 ,
11
). Set (
9 ,
11
,
5 );
img
. PixelAt (
10 ,
11 ). Set
( 10
,
11 ,
5 );
img
. PixelAt (
11 ,
11 ). Set
( 11
,
11 ,
5 );
///-----------------------------------
/// access it from method
NeighborOfPixelAt of class Rv2::Image
img . NeighborOfPixelAt
( 10
,
10 ,
Rv2 :: eNorthWest
). Get (&
r ,
& g ,
&
b );
::
printf ( "%d
%d %d\n" , r ,
g ,
b );
img
. NeighborOfPixelAt ( 10
,
10 ,
Rv2 :: eNorth
). Get (&
r ,
& g ,
&
b );
::
printf ( "%d
%d %d\n" , r ,
g ,
b );
img
. NeighborOfPixelAt ( 10
,
10 ,
Rv2 :: eNorthEast
). Get (&
r ,
& g ,
&
b );
::
printf ( "%d
%d %d\n" , r ,
g ,
b );
img
. NeighborOfPixelAt ( 10
,
10 ,
Rv2 :: eEast
). Get (&
r ,
& g ,
&
b );
::
printf ( "%d
%d %d\n" , r ,
g ,
b );
img
. NeighborOfPixelAt ( 10
,
10 ,
Rv2 :: eSouthEast
). Get (&
r ,
& g ,
&
b );
::
printf ( "%d
%d %d\n" , r ,
g ,
b );
img
. NeighborOfPixelAt ( 10
,
10 ,
Rv2 :: eSouth
). Get (&
r ,
& g ,
&
b );
::
printf ( "%d
%d %d\n" , r ,
g ,
b );
img
. NeighborOfPixelAt ( 10
,
10 ,
Rv2 :: eSouthWest
). Get (&
r ,
& g ,
&
b );
::
printf ( "%d
%d %d\n" , r ,
g ,
b );
img
. NeighborOfPixelAt ( 10
,
10 ,
Rv2 :: eWest
). Get (&
r ,
& g ,
&
b );
::
printf ( "%d
%d %d\n" , r ,
g ,
b );
::
printf ( "--------------\n"
);
//or
you can use method NeighborAt of class Rv2::Pixel
img . PixelAt
( 10
,
10 ). NeighborAt
( Rv2 ::
eNorthWest ). Get
(& r ,
&
g ,
& b );
::
printf ( "%d
%d %d\n" , r ,
g ,
b );
img
. PixelAt (
10 ,
10 ). NeighborAt
( Rv2 ::
eNorth ). Get
(& r ,
&
g ,
& b );
::
printf ( "%d
%d %d\n" , r ,
g ,
b );
img
. PixelAt (
10 ,
10 ). NeighborAt
( Rv2 ::
eNorthEast ). Get
(& r ,
&
g ,
& b );
::
printf ( "%d
%d %d\n" , r ,
g ,
b );
img
. PixelAt (
10 ,
10 ). NeighborAt
( Rv2 ::
eEast ). Get
(& r ,
&
g ,
& b );
::
printf ( "%d
%d %d\n" , r ,
g ,
b );
img
. PixelAt (
10 ,
10 ). NeighborAt
( Rv2 ::
eSouthEast ). Get
(& r ,
&
g ,
& b );
::
printf ( "%d
%d %d\n" , r ,
g ,
b );
img
. PixelAt (
10 ,
10 ). NeighborAt
( Rv2 ::
eSouth ). Get
(& r ,
&
g ,
& b );
::
printf ( "%d
%d %d\n" , r ,
g ,
b );
img
. PixelAt (
10 ,
10 ). NeighborAt
( Rv2 ::
eSouthWest ). Get
(& r ,
&
g ,
& b );
::
printf ( "%d
%d %d\n" , r ,
g ,
b );
img
. PixelAt (
10 ,
10 ). NeighborAt
( Rv2 ::
eWest ). Get
(& r ,
&
g ,
& b );
::
printf ( "%d
%d %d\n" , r ,
g ,
b );
::
printf ( "--------------\n"
);
return
0
;
}
When writing your own Rv2::Processor, usually you will get Image as polymorphic pointer of class Rv2::Image , the pointer needs to be casted(dynamic_cast) to correct type that your Rv2::Processor can process, for example
bool
MyProcessor
:: ProcessCode (
void )
{
// assuming that MyProcessor has 1 input and 1
output port, and MyProcessor only accepts Rv2::GrayScaleImage
Rv2 :: Image
*
pImageIn =
this
-> InputPortNumber ( 0
). Pop ();
Rv2 ::
GrayScaleImage *
pGryImg =
dynamic_cast
< Rv2 ::
GrayScaleImage *>( pImageIn
);
if (
NULL !=
pGryImg
)
{
/// good I unserstand it I can
processor this image
/// now I am going to process it
for ( unsigned
int
i
=
0
;
i
< pGryImg
-> LinearSize ();
i
++)
{
int b ;
pGryImg -> PixelAt
( i ).
Get (& b
);
pGryImg -> PixelAt
( i ).
Set ( 255
-
b
);
}
this -> OutputPort
( 0
)-> Push (
pGryImg );
}
else
{
/// show some error here
Debug :: Trace
( "MyProcessor::ProcessCode(void)
can't processor image that is not type Rv2::GrayScaleImage"
);
/// now just pass the image thru..
this -> OutputPort
( 0
)-> Push (
pImageIn );
}
return
true ;
}
1.3 Overlay
Every Rv2::Image derived classes has an overlay. The purpose of overlay is to illustrate an image without modifying the image's pixel. An overlay is a transparent layer of canvas on top of an image. It is represented by class Rv2::OverlayOfAnImage. The class has usual drawing tool methods, eg DrawText, DrawEllipse, DrawLine, DrawPixel, and etc, for more infomations please look at class reference for Rv2::OverlayOfAnImage. To use overlay, one would usually get reference of Rv2::OverlayOfAnImage by calling method Rv2::OverlayOfAnImage& Rv2::Image::Overlay(void). Example below shows how to draw on an ovelay.
| int
main
(
int argc
,
char
**
argv
)
{ Rv2 :: BinaryImage img ; img . Allocate ( 320 , 240 ); // : // : // do something meaning full with the image here // : // : // now I want draw something on overlay to // to illustrate image . Overlay (). DrawText ( 0 , 0 , "The Object is hightlighted in the circle" ); image . Overlay (). DrawEllipse ( 10 , 10 , 100 , 100 ); return 0 ; } |
picture#3 shows overlay which
"FindBlobsLocation" and "ContourFollowing" draw (the green line) onto.
1.4) MetaData
An image, normally, has curtain number of basic informations. These infomations are width, height, PixelType and number of Channels per pixel. A MetaData is infomation which describes additional details of an image. For example histogram, filename, location of interested objects on the image, and etc. MetaData is usually generated by processor, eg. HistogramGenerator processor computes histogram of the pass thru image then generates HistogramData and attachs it with the image, FindBlobsLocation generates RectangleArrayData, which contains collection of rectangles coordinate where blobs are founded. An image can have number of uniqe MetaData in its container, but not the same type. The example code below shows how to put and get MetaData from an image's MetaData container.
| // this
example shows how to put and get // MetaData to and from an image's ContainerOfMetaData int main ( int argc , char ** argv ) { // allocate a image; Rv2 :: RgbColorImage image ; image . Allocate ( 80 , 60 ); // : // : // do something meaning full with the image here. // : // : // now compute the image histogram // MetaData has to always allocate on heap, it CANNOT be on stack, // unless it can't be put onto the Rv2::ContainerOfMetaData. Rv2 :: HistogramData * pHD = new Rv2 :: HistogramData ; pHD -> Allocate ( 3 ); // allocate 3 channel for our hostogram pHD -> Color ( 0 ). Set ( 255 , 0 , 0 ); // set color for the 1st channel to red pHD -> Color ( 1 ). Set ( 0 , 255 , 0 ); // set color for the 2nd channel to green pHD -> Color ( 2 ). Set ( 0 , 0 , 255 ); // set color for the 3rd channel to blue for ( unsigned int i = 0 , j = 0 ; i < image . LinearSize (); i ++ ) { int r , g , b ; image . PixelAt ( i ). Get (& r , & g , & b ); pHD -> SetValue ( r , 0 ); // add red component to ch0 pHD -> SetValue ( g , 1 ); // add red component to ch1 pHD -> SetValue ( b , 2 ); // add red component to ch2 } // now add Rv2::HistogramData to the image ContainerOfMetaData // Rv2::Image::MetaDataContainer() returns // a reference to its instance of Rv2::ContainerOfMetaData image . MetaDataContainer (). Put ( pHD ); // now after pHD is put in the ContainerOfMetaData, // you don't need to worry delete pHD, ContainerOfMetaData will delete it // when the image is destroy; // now whatif there is already another Rv2::Histogram in the ContainerOfMetaData, // method ContainerOfMetaData::Put(Rv2::MetaData* pData) will delete the previous // ref Rv2::Histogram then put a new one in. // : // : // do something meaning full here. // : // : // now we want to get Rv2::HistogramData, we have put in previously Rv2 :: MetaData * pMetaData = image . MetaDataContainer (). Get ( typeid ( Rv2 :: HistogramData )); if ( NULL != pMetaData ) // oh! good, there is a Rv2::HistogramData in there. { Rv2 :: HistogramData * pMyHist = dynamic_cast < Rv2 :: HistogramData *>( pMetaData ); // : // do something meaning full with pMyHist here // : // when done, DO NOT delete pMyHist or pMetaData, // Rv2::ContainerOfMetaData will take care of it. } else // no, sorry Rv2::HistogramData is not in this container; { Debug :: Trace ( "there is no MetaData Rv2::HistogramData attached with this image" ); } return 0 ; } |
For most of the time, you will want to have a MetaData which is probaby not Rv2::HistogramData or Rv2::RectangleData. You will need to derive a new class from Rv2::MetaData and implement 3 methods; Rv2::MetaData* New(void), void WriteSelf(Rv2::Document& ar), void ReadSelf(Rv2::Document& ar), and set the Rv2::MetaData::m_strUUID value. And you must always register you new MetaData class with Rv2 system by calling Rv2::GlobalFactoryOfMetaData().Add(Rv2::MetaData* pNewClass); when system starts.
For more details on how to derive a new class from Rv2::MetaData, please read the sample code below. You can also look at the ExampleProcessor code here.
|
namespace
Example // should always enclosed with a name space. int
main
( int
argc
,
char **
argv |
2) About Creating Processors and package them in a Library(dll, so and bundle).
| Number of Input Ports | Number Of Output Ports | Method needs to be overided and implement function | |
| Rv2::InPlaceProcessor | 1 | 1 | void ProcessImage(Rv2::Image *pImage) |
| Rv2::OutputOfPlaceProcessor | 1 | 2 | Rv2::Image* ProcessImage(Rv2::Image* pImageIn) |
| Rv2::ImageProducer | 0 | 1 | Rv2::Image* Produce(void) |
| Rv2::ImageConsumer | 1 | 0 | void Consume(Rv2::Image* img) |
| Rv2::BinaryOperatorProcessor | 2 | 1 | Rv2::Image* ProcessImage(Rv2::Image* pLhsImage, Rv2::Image* pRhsImage) |
To create a processor, you can dervide a new processor class direct from Rv2::Processor or one of "seed" processor which provides some functionalities.
2.1) Derive from Rv2::InplaceProcessor
InPlaceProcessor is an abstract class derived from Rv2::Processor. It's actually a special version of Rv2::Processor which has a output and an input. InPlaceProcessor cannot be initiated by itself. A new class have to be derived from it and implement a pure virtual method void ProcessImage(Rv2::Image *pImage). InPlaceProcessor is for image processing algorithm that can be done inplace, eg. Negation, Threashold, and etc. Example below shows InPlaceGrayScaleNagation derived from Rv2::InplaceProcessor.
2.2) Derive from Rv2::OutOfPlaceProcessor
Rv2::OutOfPlaceProcessor has 1 input and 2 output ports; output port number 0 is just a pass thru from input port number 0, and output port number 1 is the result image. The pure virtual method Rv2::Image* ProcessImage(Rv2::Image* pImageIn) needs to be overidden and implemented., pImageIn is ptr of Rv2::Image from input port 0, the method must allocate a new Rv2::Image and return it. The return Rv2::Image is pushed out to output port 1, and pImageIn get passed thru to output port 0.
2.3) Derive from Rv2::BinaryOperatorProcessor
Some Image Processing Algorithms need 2 input images(Left Hand Side and Right Hand Side) and and produce a result, this comparable to a mathematic equation ResultImage = LeftHandSideImage % RightHandSideImage where % is an operator, eg image subtraction. If your algorithm has the same characteristic, you can derive a new class from Rv2::BinaryOperatorProcessor and implement Rv2::Image* ProcessImage(Rv2::Image* pLhsImage, Rv2::Image* pRhsImage) method. Example code below shows GrayScaleXOR which is derived from Rv2::BinaryOperator. GrayScaleXOR takes LHS image and xor it with RHS image, then returns the result.
2.4 Derive from Rv2::ImageProducer
Rv2::ImageProducer has only one output. For example AviFileReader reads an AVI file and creates Rv2::RgbColorImage of each frames in the AVI file then pushs the Rv2::RgbColorImage out to output port 0. If you intend to write a processor with similar function, the easiest way is to derive a new class from Rv2::ImageProducer and implement a virtual method Rv2::Image* Produce(void). The method must return a valid ptr to Rv2::Image.
2.5) Derive from Rv2::ImageConsumer
Rv2::ImageConsumer has configurable number of input ports but must at least has one inputs and has no output ports at all. By default Rv2::ImageConsumer always has one input port. To create Rv2::ImageConsumer with more than one input ports, call method bool Create(int nInputPort);. ImageConsumer is where Rv2::Image is destroyed in a pipeline, so a derive class must implement virtual method void Consume(Rv2::Image* img) ,then after doing whatever the derive class suppose to do, it must delete the Rv2::Image.
class Rv2::System is the integation point to your custom application.
Simplest Example shows
#include <cstdio>
#include "Rv2Headers.h"
intmain(intargc,char**argv)
{
// Main entry class to use Rv2Library
Rv2::SystemRv2Sys;
// read library(dll) listed in
RvCAD.Library.Config.xml
// When RvCAD is first loaded if this file is not
exist
// it will scan to find processor library(dll) in
the current
// directory then create this file.
if(false==Rv2Sys.ReadLibraryConfigFile("RvCAD.Library.Config.xml"))
{
return0;
}
// now create a new pipeline
Rv2::Pipeline*pMyPipeline=Rv2Sys.AllocatePipeline();
//Now we are ready, so load the popeline that we
want to run
if(true==pMyPipeline->LoadFromFile("test.pipeline.xml"))
{
//tell pipeline to run slient
pMyPipeline->SetRunSlient(true);
//now we can run in the pipeline
pMyPipeline->Run();
//
std::printf("press return to stop\n");
getc(stdin);
std::printf("stopping pipeline\n");
pMyPipeline->Stop();
// finish
// we don't and must not delete pipeline here
// Rv2::System will take care of it.
}
else
{
std::printf("fail to open pipeline test.pipeline.xml\n");
}
return0;
}
A pipeline can be executed as processor on another pipeline. Under library "RemoteConnectionProcessors", "PipelineExecutor" is able to load a pipeline from file and execute it as a processor. The purpose of InputPlate and OutputPlate are to act as input and output ports of PipelineExecutor and make the pipeline complete.
Consider the pipeline below, the purpose of this pipeline is to smooth RgbColorImage. Since GaussianSmooth processor will only accept GrayScaleImage, so RgbSeparator is needed to separate red, green and blue channel from the RgbColorImage. The outputs from RgbSeparator are gray value of red, green and blue of the RgbColorImage represented in GrayScaleImage. Once each channels has been smoothed, processor RgbCombiner is used to combine the 3 channels and produces the result RgbColorImage.

As you can see that there are 3 paths of this pipeline that perform exactly the same task which to smooth GrayScaleImage. To reduce complexity of this pipeline, we can build a sub pipeline that would Smooth GrayScaleImage like the following, then save it to file: "ex1.pipeline.xml"
In a sub-pipeline, it needs to have at least one InputPlate or OutputPlate but not more than one of each. They act as Input and Output Port(s) of PipelineExecutor.

InputPlate can be configured (right click on it and select "config") to have number of OutputPorts, the number will tell PipelineExecutor how many InputPorts does it need. So InputPlate's OutputPort number 0 is correspond to InputPort number 0 of the PipelineExecutor and so on.
OutputPlate can also be configured to have number of InputPorts, the number will tell PipelineExecutor how many OutputPorts does it need. So OutputPlate's InputPort number 0 is correspond to OutputPort number 0 of the PipelineExecutor and so on.
Now, all we need to do is, use PipelineExecutor processor to load "GrayScaleThreshold.pipeline.xml". Now our new pipeline look like a bit better.

As you can see, PipelineExecutor is comparable to subroutine in programming. To go further , by using RemotePipelineExecutor and RemoteProcessorExecutor under RemoteConnectionProcessors library, RvCAD can execute pipeline and processor on remote machines, running in local area network. This makes a group of machines act like one big powerful computer. For more infomation, please look at "Distributed Computing (Running Pipeline or Processor on a remote machine)(RpcServer)"
RvCAD has ability to run Processors and Pipelines over remote machines, to distribute load from the main pipeline. Runnning a pipeline over a remote machine is the same as running a pipeline as a processor, please read section "Running a pipeline as a processor inside another pipeline" before continue.
Requirements
1) Make sure that you have RemoteConnectionProcessors.dll in the bin directory where you've installed RvCAD, it's loaded, you should see "RemoteConnectionProcessors" on the left hand tree view.
(picture shows RemoteConnectionProcessors.dll loaded in RvCAD.)
2) Run RpcServer on all slave machines. From MainFrame window select File->"Open RpcServer Pipeline". RpcServer is listening on port 3000 by default, you can change that by right clicking on the processor then config it. Once done, execute the pipeline.

Running a processor over a remote machine.
To run a processor over a remote machine, use "RemoteProcessorExecutor" under "RemoteConnectionProcessor" library. Right Click on the processor and Select a processor and enter RpcServer host name or ip address. If the config dialog does not show the processor name that you want, you can enter the processor name directly, also please remember that processor and its library name are case sensitive.
Running a pipeline over a remote machine.
To run a pipeline over a remote machine, first the pipeline has to completed and has Input and Output plate(for more infomation, please read section "Running a pipeline as a processor inside another pipeline" . Use "RemotePipelineEcecutor" under "RemoteConnectionProcessors" Library. Right Click on the processor to get config dialog, enter RpcServer host name or address and enter the filename of the pipeline. Make sure that the pipline file is already on the remote machine where RpcServer is running.