OpenCV and Processing 10

I decide to put together the OpenCV and Processing codes into a class to encapsulate the functions. In this example, I extend the original PImage class and create the CVImage class.  Besides the constructor, the following functions are the major interfaces:

  • toCV() – copy the content of the PImage pixels[] array to the internal Mat variable cvImg; the internal format for the Mat is BGRA.
  • fromCV(Mat) – convert a parameter Mat to the internal storage of Mat and pixels[] array; it accepts input of 1, 3, and 4 channels.
  • Mat getBGRA() – output the BGRA Mat from the internal Mat storage.
  • Mat getBGR() – output the BGR Mat from the internal Mat storage.
  • Mat getGrey() – out the greyscale Mat from the internal Mat storage.


Definition of the CVImage class

import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.core.CvType;
import org.opencv.core.Scalar;
import org.opencv.imgproc.Imgproc;
 
import java.nio.IntBuffer;
import java.nio.ByteBuffer;
import java.util.List;
 
public class CVImage extends PImage {
 
  private Mat cvImg;
  private int pixCnt;
 
  CVImage(int _w, int _h) {
    super(_w, _h, ARGB);
    pixCnt = _w*_h*4;
    cvImg = new Mat(_h, _w, CvType.CV_8UC4, Scalar.all(0));
  }
 
  public void toCV() {
    // copy the content in pixels[] to cvImg mat in BGRA format.
    Mat tmp = new Mat(this.height, this.width, CvType.CV_8UC4);
    byte [] bArray = new byte[pixCnt];
    ByteBuffer bb = ByteBuffer.allocate(pixCnt);
    bb.asIntBuffer().put(this.pixels);
    bb.get(bArray);
    tmp.put(0, 0, bArray);
    ArrayList ch1 = new ArrayList();
    ArrayList ch2 = new ArrayList();
    Core.split(tmp, ch1);
    ch2.add(ch1.get(3));
    ch2.add(ch1.get(2));
    ch2.add(ch1.get(1));
    ch2.add(ch1.get(0));
    Core.merge(ch2, cvImg);
    tmp.release();
    ch1.clear();
    ch2.clear();
    bb.clear();
  }
 
  public void fromCV(Mat _m) {
    // Copy the parameter mat to the cvImg and the pixels[] array. It can accept
    // 1, 3, and 4 channels.
    if (_m.rows() != this.height || _m.cols() != this.width)
      return;
    Mat mat = new Mat(cvImg.size(), cvImg.type());
    Mat out = new Mat(cvImg.size(), cvImg.type());
    Mat alpha = new Mat(cvImg.size(), CvType.CV_8UC1, Scalar.all(255));
    ArrayList ch1 = new ArrayList();
    ArrayList ch2 = new ArrayList();
    ArrayList ch3 = new ArrayList();
    Core.split(_m, ch1);
    switch (_m.channels()) {
    case 1:
      ch2.add(ch1.get(0));
      ch2.add(ch1.get(0));
      ch2.add(ch1.get(0));
      ch2.add(alpha);
      ch3.add(alpha);
      ch3.add(ch1.get(0));
      ch3.add(ch1.get(0));
      ch3.add(ch1.get(0));
      Core.merge(ch2, mat);
      Core.merge(ch3, out);
      break;
    case 3:
      ch2.add(ch1.get(0));
      ch2.add(ch1.get(1));
      ch2.add(ch1.get(2));
      ch2.add(alpha);
      ch3.add(alpha);
      ch3.add(ch1.get(2));
      ch3.add(ch1.get(1));
      ch3.add(ch1.get(0));
      Core.merge(ch2, mat);
      Core.merge(ch3, out);
      break;
    case 4:
      _m.copyTo(mat);
      ch3.add(ch1.get(3));
      ch3.add(ch1.get(2));
      ch3.add(ch1.get(1));
      ch3.add(ch1.get(0));
      Core.merge(ch3, out);
      break;
    default:
      return;
    }
    mat.copyTo(cvImg);
    byte [] bArray = new byte[pixCnt];
    out.get(0, 0, bArray);
    ByteBuffer.wrap(bArray).asIntBuffer().get(this.pixels);
    this.updatePixels();
 
    mat.release();
    out.release();
    ch1.clear();
    ch2.clear();
    ch3.clear();
  }
 
  public Mat getBGRA() {
    // Return the cvImg mat.
    Mat mat = cvImg.clone();
    return mat;
  }
 
  public Mat getBGR() {
    // Return a BGR mat from cvImg.
    Mat mat = new Mat(cvImg.size(), CvType.CV_8UC3);
    ArrayList ch1 = new ArrayList();
    ArrayList ch2 = new ArrayList();
    Core.split(cvImg, ch1);
    ch2.add(ch1.get(0));
    ch2.add(ch1.get(1));
    ch2.add(ch1.get(2));
    Core.merge(ch2, mat);
    ch1.clear();
    ch2.clear();
    return mat;
  }
 
  public Mat getGrey() {
    // Return a greyscale image from cvImg mat.
    Mat in = getBGR();
    Mat out = new Mat(cvImg.size(), CvType.CV_8UC1);
    Imgproc.cvtColor(in, out, Imgproc.COLOR_BGR2GRAY);
    in.release();
    return out;
  }
}

 
The example code demonstrates the usage of the CVImage class. It captures the live webcam image and converts into greyscale.

import processing.video.*;
 
Capture cap;
CVImage img;
PShape shp;
 
void setup() {
  size(640, 480, P3D);
  background(0);
  println(Core.VERSION);
  System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
  cap = new Capture(this, width, height);
  cap.start();
  img = new CVImage(width, height);
  shp = createShape(RECT, 0, 0, width, height);
}
 
void draw() {
  background(0);
  arrayCopy(cap.pixels, img.pixels);
  img.toCV(); // load the pixels to Mat
  Mat col = img.getGrey(); // obtain the greyscale image
  img.fromCV(col); // copy the greyscale image to img
  shp.setTexture(img);
  shape(shp, 0, 0);
  text("Frame rate: " + nf(round(frameRate), 2), 10, 20);
}
 
void captureEvent(Capture c) {
  c.read();
  c.loadPixels();
}