Source paper:
Efficient Graph-Based Image Segmentation.
(with Daniel Huttenlocher)
International Journal of Computer Vision, Vol. 59, No. 2, September 2004.
[PDF text]
Project Code:
Rebecca-E-0.10.1.jar
Rebecca-E-0.10.1
This Pipe is a compilation of the JMF examples provided by David Fischer (http://www.mutong.com/fischer/java/usbcam/) and the sun.com.
The Pipe performs fast image capturing from web-camera.
The process contains next steps:
- Init camera
- Capture the last frame from a camera to a BufferedImage, put it to the output slot every time you run the Execute() method;
- Shutdown camera
Shortcoming: provides empty frames for 2-3 seconds after start.
Code:
CameraCapture.java
There is an example of a simple image processing code.
The process contains next steps:
- loading image,
- cloning it,
- performing some operations with the first copy
- and showing results on the user screen.
Project files: Rebecca-E-0.9.zip
Project dir: Rebecca-E-0.9
ImageLoaderDialog.java
…
the pipeline’s scheme:
the pipeline’s code:
package Run;
import java.awt.image.BufferedImage;
import rebecca.e9.core.*;
import rebecca.e9.pipes.*;
public class SimpleImageProcessingPipeline extends PipeLine {
public SimpleImageProcessingPipeline() {
super(“Simple image processing pipeline”);
//Load image—————————————————–
Slot bi = new Slot();
Pipe imageLoader=new ImageLoaderDialog(bi);
//Clone image—————————————————–
Slot bi1 = new Slot();
Slot bi2 = new Slot();
Pipe clone=new ImageClone(bi,bi1,bi2);
//Convert it to vector-function implemented by ObrazC3 (3 channels)
Slot c31 = new Slot();
Pipe convert2obrazC3=new Image2ObrazC3(bi1,c31);
//Do some code we provided in our “DoSomeImageOperations” pipe—
Slot c33 = new Slot();
Pipe MyTestPipe=new DoSomeImageOperations(c31,c33);
//Convert image back———————————————
Slot ib = new Slot();
Pipe C2=new Obraz2Image(c33,ib);
//Plug in user screen to see the results————————–
Pipe S=new Screen(“After”,ib);
Pipe D=new Screen(“Before”,bi2);
//Register all pipes———————————————-
this.registerPipe(imageLoader);
this.registerPipe(clone);
this.registerPipe(convert2obrazC3);
this.registerPipe(MyTestPipe);
this.registerPipe(C2);
this.registerPipe(S);
this.registerPipe(D);
}
}
image processing code:
package rebecca.e9.pipes;
import rebecca.e9.core.*;
public class DoSomeImageOperations extends Pipe {
private ObrazC3 tempO1=null;
private ObrazC3 tempO2=null;
private Slot in;
private Slot out;
public DoSomeImageOperations(Slot input,Slot output) {
super(“Image Processing…”);
if (input!=null&output!=null)
{
this.in=input;
this.out=output;
this.registerInSlot(input);
this.registerOutSlot(output);
}else{this.setDamage();}
}
public void Init() {
}
public void ShutDown() {
}
public void Execute() {
tempO2 = in.GetDATA(this);
int H=tempO2.getHeight();
int W=tempO2.getWidth();
tempO1 = new ObrazC3(H,W);
char r=0;
char g=0;
char b=0;
char w=0;
for(int i=0;i
for(int j=0;j
r=tempO2.getR(i, j);
g=tempO2.getG(i, j);
b=tempO2.getB(i, j);
tempO1.setR(i, j, 255-r);
tempO1.setG(i, j, 0);
tempO1.setB(i, j, (g+b)/2);
}}
this.out.PushDATA(tempO1, this);
}
}
The Rebecca-E project has been awarded the first prize of the XLVI International Scientific Student’s Conference, 2008, Novosibirsk State University.
package rebecca.e9.standart.pipes;
import rebecca.e9.core.*;
public class EmptyPipe extends Pipe {
public EmptyPipe() {
super(“Do nothing.”);
}
public void Execute() {
}
public void Init() {
}
public void ShutDown() {
}
}
The Rebecca-Е Framework Project is currently being developed using Java and C# programming languages. The framework provides virtual pipeline architecture. Every Pipe performs its task in separate process (thread). The Pipes organize connected pipe structures called “Pipelines” and perform combined tasks. The Pipelines correspond to combined-tasks and organize groups called “Factories”. Each Factory implements a robot control pattern. Each Factory and Pipeline can be rebuilt during run-time. Such program architecture provides continuous data transporting during runtime. It enables possibility to distribute data-processing to different computers (with different operation systems). The pipelines provide ability to transport not only images; it’s possible to work with all data types determined in the project language.
Currently the Framework’s library includes minimal set of Pipes which performs simple operations like: image loading, camera frame capture, the Sobel operator, converting image to numeric array and back, median filtration and etc. The process of algorithm realization and developing new pipes is very simple; user needs just a basic knowledge of Java (C#) language. One of the main reasons for developing the Rebecca-Е Framework was necessity to reduce the process of real-time image processing algorithms developing to mathematical bases; to escape solving of attend program tasks. Also the Rebecca-Е Framework has no Graphical User Interface; therefore the process of building and configuring Pipelines is performed manually. In spite of this, it presents no difficulties and now I will provide next example.
How to build simple Pipe and plug it into a Pipeline.
As an example I’ll demonstrate the process of creating a Pipe performing image decolorizing. First of all we need to design our future Pipeline. Let’s imagine the scheme of the Pipeline:
The Pipeline consists of five parts represented with Pipes where each of them performs one of the next operations:
- load image from file
- convert image to byte-array
- decolorize image
- convert array to image
- show result on screen
The ObrazC3 is a special class for representing images as a vector function (F:(x,y) →z). This is just a byte array with defined methods like: char getR(int i,int j); Color getPixel(int i,int j); and etc. Also there are other classes: ObrazC1, ObrazC2 and ObrazC4 which are used to represent one-, two- and four channel images (Red-Green-Blue-Alpha).
After determining necessary Pipes we can see that there are four of them already in the framework library: «ImageLoader», «Image2ObrazC3», «ObrazC1Image», «Screen». So we need to build new pipe: «Decolorizer». To perform this we need to copy «EmptyPipe» class and to change it:

First of all we need to determine input and output slots. For this we change the class constructor adding new slots and registering them:
The blue marker marks the internal variables we need. The orange marker points at changes in the constructor. The violet marker – we performs registration for input and output slots of our Pipe. The red marker calls damage function in case we try to plug the Pipe into bad slots.
If necessary we can modify the process of initialization and shutting down of our pipe inside the Init() and ShutDown() methods bodies. Now we need to modify the Execute() method body, which the Pipeline calls every time it detects that all output slots have old data (marked “not fresh”) and all input slots have new data to process (marked as “fresh”):

The orange marker shows code where we operate with data: our pipe gets data from input slot, processes it, and puts result into output slot. The “fresh/not-fresh” marking performs automatically. So our Decolorizer Pipe is complete, now we need to construct the Pipeline; here we analogously use the EmptyPipeLine class as a pattern:

We define input argument for our pipeline: the slot which stores file path string. The Pipe and Pipelines are divided into three groups: Producers, Consumers and Executors.
Producer – the pipeline or pipe which has output slots only
Consumer – the pipeline or pipe which has input slots only
Executer – the pipeline or pipe which has both input and output slots
In our case we are building a consumer Pipeline which “eats” file-path argument. We have no producer Pipeline, therefore we need to define slot which will store out path string. Well, let’s build the Pipeline, now we need define and register all slots and pipes:

And then we need to build a Factory:
The orange marker shows the code where we mark the input slot as “fresh”. By default all slots are marked as “not fresh”, therefore during runtime: the first Pipe of our Pipeline would be in awaiting mode, until slot become “fresh”. We need a producer for that slot – to put new fresh data; as we’ve already mentioned, there is no produces, so we need to mark the slot as fresh manually.
The SetFresh() method marks the slot as fresh; the pipeline will load image using the string path in the slot, mark it as “not fresh” and switch itself to awaiting mode.
The SetAlwaysFresh() method marks the slot as fresh for the all further requests; therefore the pipeline will load image again and again;
Now we need to start our factory, let’s do it:

The code defines the Factory, starts it and stops it after 20 seconds. Don’t forget to put any image to the “C:/1.bpm” path! If the configuring and building were right performed, you’ll see something like this:
The orange marker shows times in milliseconds for each execution.
Results:
Thereby we have instrument to perform image processing, to realize, to test, to teach and to demonstrate algorithms.
By the way we can organize computational task distribution. To perform this we need to build a set of Factories (one factory per each computer we use) and create two Pipes:
- Pipe-consumer which would get data from its Factory and send it to other computer via network (or in any other way).
- Pipe-producer which would receive data from the first pipe, and to pass it on to its Factory
Currently the Rebecca-Е Framework does not include such pipes (receiver/transmitter), but it’s easy to make them. (Probably I’ll do it later.)






