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(); } |