{"id":1507,"date":"2015-06-21T23:09:09","date_gmt":"2015-06-21T15:09:09","guid":{"rendered":"http:\/\/www.magicandlove.com\/blog\/?p=1507"},"modified":"2015-07-05T22:14:58","modified_gmt":"2015-07-05T14:14:58","slug":"opencv-and-processing-10","status":"publish","type":"post","link":"http:\/\/www.magicandlove.com\/blog\/2015\/06\/21\/opencv-and-processing-10\/","title":{"rendered":"OpenCV and Processing 10"},"content":{"rendered":"<p>I decide to put together the OpenCV and Processing codes into a class to encapsulate the functions. In this example, I extend the original <a href=\"https:\/\/processing.org\/reference\/PImage.html\">PImage<\/a> class and create the <strong>CVImage <\/strong>class.\u00a0 Besides the constructor, the following functions are the major interfaces:<\/p>\n<ul>\n<li><em>toCV()<\/em> &#8211; copy the content of the PImage pixels[] array to the internal Mat variable cvImg; the internal format for the Mat is BGRA.<\/li>\n<li><em>fromCV(Mat)<\/em> &#8211; convert a parameter Mat to the internal storage of Mat and pixels[] array; it accepts input of 1, 3, and 4 channels.<\/li>\n<li><em>Mat getBGRA()<\/em> &#8211; output the BGRA Mat from the internal Mat storage.<\/li>\n<li><em>Mat getBGR()<\/em> &#8211; output the BGR Mat from the internal Mat storage.<\/li>\n<li><em>Mat getGrey()<\/em> &#8211; out the greyscale Mat from the internal Mat storage.<\/li>\n<\/ul>\n<p><!--more--><br \/>\n<strong>Definition of the CVImage class<\/strong><\/p>\n<pre lang=\"java\">import org.opencv.core.Core;\r\nimport org.opencv.core.Mat;\r\nimport org.opencv.core.CvType;\r\nimport org.opencv.core.Scalar;\r\nimport org.opencv.imgproc.Imgproc;\r\n\r\nimport java.nio.IntBuffer;\r\nimport java.nio.ByteBuffer;\r\nimport java.util.List;\r\n\r\npublic class CVImage extends PImage {\r\n\r\n  private Mat cvImg;\r\n  private int pixCnt;\r\n\r\n  CVImage(int _w, int _h) {\r\n    super(_w, _h, ARGB);\r\n    pixCnt = _w*_h*4;\r\n    cvImg = new Mat(_h, _w, CvType.CV_8UC4, Scalar.all(0));\r\n  }\r\n\r\n  public void toCV() {\r\n    \/\/ copy the content in pixels[] to cvImg mat in BGRA format.\r\n    Mat tmp = new Mat(this.height, this.width, CvType.CV_8UC4);\r\n    byte [] bArray = new byte[pixCnt];\r\n    ByteBuffer bb = ByteBuffer.allocate(pixCnt);\r\n    bb.asIntBuffer().put(this.pixels);\r\n    bb.get(bArray);\r\n    tmp.put(0, 0, bArray);\r\n    ArrayList ch1 = new ArrayList();\r\n    ArrayList ch2 = new ArrayList();\r\n    Core.split(tmp, ch1);\r\n    ch2.add(ch1.get(3));\r\n    ch2.add(ch1.get(2));\r\n    ch2.add(ch1.get(1));\r\n    ch2.add(ch1.get(0));\r\n    Core.merge(ch2, cvImg);\r\n    tmp.release();\r\n    ch1.clear();\r\n    ch2.clear();\r\n    bb.clear();\r\n  }\r\n\r\n  public void fromCV(Mat _m) {\r\n    \/\/ Copy the parameter mat to the cvImg and the pixels[] array. It can accept\r\n    \/\/ 1, 3, and 4 channels.\r\n    if (_m.rows() != this.height || _m.cols() != this.width)\r\n      return;\r\n    Mat mat = new Mat(cvImg.size(), cvImg.type());\r\n    Mat out = new Mat(cvImg.size(), cvImg.type());\r\n    Mat alpha = new Mat(cvImg.size(), CvType.CV_8UC1, Scalar.all(255));\r\n    ArrayList ch1 = new ArrayList();\r\n    ArrayList ch2 = new ArrayList();\r\n    ArrayList ch3 = new ArrayList();\r\n    Core.split(_m, ch1);\r\n    switch (_m.channels()) {\r\n    case 1:\r\n      ch2.add(ch1.get(0));\r\n      ch2.add(ch1.get(0));\r\n      ch2.add(ch1.get(0));\r\n      ch2.add(alpha);\r\n      ch3.add(alpha);\r\n      ch3.add(ch1.get(0));\r\n      ch3.add(ch1.get(0));\r\n      ch3.add(ch1.get(0));\r\n      Core.merge(ch2, mat);\r\n      Core.merge(ch3, out);\r\n      break;\r\n    case 3:\r\n      ch2.add(ch1.get(0));\r\n      ch2.add(ch1.get(1));\r\n      ch2.add(ch1.get(2));\r\n      ch2.add(alpha);\r\n      ch3.add(alpha);\r\n      ch3.add(ch1.get(2));\r\n      ch3.add(ch1.get(1));\r\n      ch3.add(ch1.get(0));\r\n      Core.merge(ch2, mat);\r\n      Core.merge(ch3, out);\r\n      break;\r\n    case 4:\r\n      _m.copyTo(mat);\r\n      ch3.add(ch1.get(3));\r\n      ch3.add(ch1.get(2));\r\n      ch3.add(ch1.get(1));\r\n      ch3.add(ch1.get(0));\r\n      Core.merge(ch3, out);\r\n      break;\r\n    default:\r\n      return;\r\n    }\r\n    mat.copyTo(cvImg);\r\n    byte [] bArray = new byte[pixCnt];\r\n    out.get(0, 0, bArray);\r\n    ByteBuffer.wrap(bArray).asIntBuffer().get(this.pixels);\r\n    this.updatePixels();\r\n\r\n    mat.release();\r\n    out.release();\r\n    ch1.clear();\r\n    ch2.clear();\r\n    ch3.clear();\r\n  }\r\n\r\n  public Mat getBGRA() {\r\n    \/\/ Return the cvImg mat.\r\n    Mat mat = cvImg.clone();\r\n    return mat;\r\n  }\r\n\r\n  public Mat getBGR() {\r\n    \/\/ Return a BGR mat from cvImg.\r\n    Mat mat = new Mat(cvImg.size(), CvType.CV_8UC3);\r\n    ArrayList ch1 = new ArrayList();\r\n    ArrayList ch2 = new ArrayList();\r\n    Core.split(cvImg, ch1);\r\n    ch2.add(ch1.get(0));\r\n    ch2.add(ch1.get(1));\r\n    ch2.add(ch1.get(2));\r\n    Core.merge(ch2, mat);\r\n    ch1.clear();\r\n    ch2.clear();\r\n    return mat;\r\n  }\r\n\r\n  public Mat getGrey() {\r\n    \/\/ Return a greyscale image from cvImg mat.\r\n    Mat in = getBGR();\r\n    Mat out = new Mat(cvImg.size(), CvType.CV_8UC1);\r\n    Imgproc.cvtColor(in, out, Imgproc.COLOR_BGR2GRAY);\r\n    in.release();\r\n    return out;\r\n  }\r\n}<\/pre>\n<p>&nbsp;<br \/>\nThe example code demonstrates the usage of the CVImage class. It captures the live webcam image and converts into greyscale.<\/p>\n<pre lang=\"java\">\r\nimport processing.video.*;\r\n\r\nCapture cap;\r\nCVImage img;\r\nPShape shp;\r\n\r\nvoid setup() {\r\n  size(640, 480, P3D);\r\n  background(0);\r\n  println(Core.VERSION);\r\n  System.loadLibrary(Core.NATIVE_LIBRARY_NAME);\r\n  cap = new Capture(this, width, height);\r\n  cap.start();\r\n  img = new CVImage(width, height);\r\n  shp = createShape(RECT, 0, 0, width, height);\r\n}\r\n\r\nvoid draw() {\r\n  background(0);\r\n  arrayCopy(cap.pixels, img.pixels);\r\n  img.toCV(); \/\/ load the pixels to Mat\r\n  Mat col = img.getGrey(); \/\/ obtain the greyscale image\r\n  img.fromCV(col); \/\/ copy the greyscale image to img\r\n  shp.setTexture(img);\r\n  shape(shp, 0, 0);\r\n  text(\"Frame rate: \" + nf(round(frameRate), 2), 10, 20);\r\n}\r\n\r\nvoid captureEvent(Capture c) {\r\n  c.read();\r\n  c.loadPixels();\r\n}\r\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>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.\u00a0 Besides the constructor, the following functions are the major interfaces: toCV() &#8211; copy the content of the PImage pixels[] array to the internal Mat [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[89,79],"tags":[3,62],"class_list":["post-1507","post","type-post","status-publish","format-standard","hentry","category-research","category-software-2","tag-opencv","tag-processing-org"],"_links":{"self":[{"href":"http:\/\/www.magicandlove.com\/blog\/wp-json\/wp\/v2\/posts\/1507","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/www.magicandlove.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.magicandlove.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.magicandlove.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.magicandlove.com\/blog\/wp-json\/wp\/v2\/comments?post=1507"}],"version-history":[{"count":5,"href":"http:\/\/www.magicandlove.com\/blog\/wp-json\/wp\/v2\/posts\/1507\/revisions"}],"predecessor-version":[{"id":1558,"href":"http:\/\/www.magicandlove.com\/blog\/wp-json\/wp\/v2\/posts\/1507\/revisions\/1558"}],"wp:attachment":[{"href":"http:\/\/www.magicandlove.com\/blog\/wp-json\/wp\/v2\/media?parent=1507"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.magicandlove.com\/blog\/wp-json\/wp\/v2\/categories?post=1507"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.magicandlove.com\/blog\/wp-json\/wp\/v2\/tags?post=1507"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}