For this chapter, our goal is to add several image filters to Second Sight
. These filters rely on various OpenCV functions for manipulating matrices through splitting, merging, arithmetic operations, or applying lookup tables for complex functions. Certain filters also rely on a mathematics library called Apache Commons Math
.
The completed Eclipse project for this chapter can be downloaded from my website at http://nummist.com/opencv/5206_03.zip.
We need to add several files to our Eclipse project in order to create new types (that is, interfaces and classes) and to link to a new library, Apache Commons Math
. The following are the new types that we want to create:
com.nummist.secondsight.filters.Filter
: It is an interface representing a filter that can be applied to an image.com.nummist.secondsight.filters.NoneFilter
: It is a class representing a filter that does nothing. It implements the Filter
interface.com.nummist.secondsight.filters.convolution.StrokeEdgesFilter
: It is a class representing a filter that draws heavy-black lines atop edge regions. It implements the Filter
interface.com.nummist.secondsight.filters.curve.CurveFilter
: It is a class representing a filter that may apply a separate curvilinear transformation to each color channel in an image. (It is like Curves in Photoshop or Gimp.) It implements the Filter
interface.com.nummist.secondsight.filters.curve.CrossProcessCurveFilter
: It is a subclass of CurveFilter
. It emulates a photo film processing technique called cross-processing.com.nummist.secondsight.filters.curve.PortraCurveFilter
: It is a subclass of CurveFilter
. It emulates a brand of photo film called Kodak Portra.com.nummist.secondsight.filters.curve.ProviaCurveFilter
: It is a subclass of CurveFilter
. It emulates a brand of photo film called Fuji Provia.com.nummist.secondsight.filters.curve.VelviaCurveFilter
: It is a subclass of CurveFilter
. It emulates a brand of photo film called Fuji Velvia.com.nummist.secondsight.filters.curve.RecolorCMVFilter
: It is a class representing a filter that linearly combines color channels, such that the image appears to be mixed from a limited palette of cyan, magenta, and white. (It is like a specialization of Channel Mixer in Photoshop or Gimp.) It implements the Filter
interface.com.nummist.secondsight.filters.curve.RecolorRCFilter
: It is a class representing a filter that linearly combines color channels, such that the image appears to be mixed from a limited palette of red and cyan. (It is like a specialization of Channel Mixer in Photoshop or Gimp.) It implements the Filter
interface.com.nummist.secondsight.filters.curve.RecolorRGVFilter
: It is a class representing a filter that linearly combines color channels, such that the image appears to be mixed from a limited palette of red, green, and white. (It is like a specialization of Channel Mixer in Photoshop or Gimp.) It implements the Filter
interface.Create the appropriate packages and Java files under the src
directory in the Package Explorer pane. (Right-click on the src
directory and then choose New | Package, New | Interface, or New | Class from the context menu.)
Now, let's get the Apache Commons Math
library. Download the latest version from http://commons.apache.org/proper/commons-math/download_math.cgi. Unzip the download file. Inside the unzipped folder, find a file with a name such as commons-math3-3.2.jar
. (The version numbers may differ.) Copy this file into the libs
folder of the Eclipse project.
After all the necessary files are added, your Package Explorer pane should look similar to the one in the following screenshot:
For our purposes, a filter is any transformation that can be applied to a source image and destination image. (The source and destination may be the same image or different images.) Our application needs to treat the filters interchangeably, so it is a good idea to formalize this definition of a filter's interface. Let's edit Filter.java
so that the Filter
interface is defined as follows:
public interface Filter { public abstract void apply(final Mat src, final Mat dst); }
As far as our app is concerned, the apply
method is the only thing that our filters must have in common. Everything else is the implementation details.
The most basic implementation of the Filter
interface is the NoneFilter
class. As the name suggests, NoneFilter
does no filtering at all. Let's implement it as follows:
public class NoneFilter implements Filter { @Override public void apply(final Mat src, final Mat dst) { // Do nothing. } }
NoneFilter
is just a convenient stand-in for other filters. We use it when we want to turn off filtering but still have an object that conforms to the Filter
interface.