【问题标题】:Convert PImage to Mat - Java OpenCV in Processing IDE P3D (OpenGL) renderer将 PImage 转换为 Mat - 处理 IDE P3D (OpenGL) 渲染器中的 Java OpenCV
【发布时间】:2020-03-09 12:32:58
【问题描述】:

我编写了一个代码来在 OpenCV Mat 和 PImage (ARGB) 之间进行转换。我使用网络摄像头作为输入,并由处理视频库捕获。它适用于 Java2D 渲染器,但不适用于 P2D 或 P3D 渲染器。可能是什么问题?

它尝试使用 loadPixels()updatePixels() 语句 - 它不起作用。还有一个特别的地方是,P3D 渲染器中的相机图像不能用pimage = cam.copy();pimage = cam.get(); 复制到 PImage,但它必须像 pimage = cam;我不明白这是为什么?

我使用的是原生 Opencv Java 3.4。

import processing.video.*; Capture cam; import java.nio.*; //to convert Mat PImage byte [] bArray; int [] iArray; int pixCnt1, pixCnt2; PImage camStream;// camera frame //---------------------- void setup() { size(640, 480); //PImage to mat does not work with P2D for some reason? //size(640,480,P3D);// this does NOT WORK String[] cameras = Capture.list(); if (cameras == null) { println("Failed to retrieve the list of available cameras, will try the default..."); cam = new Capture(this, 640, 480); } if (cameras.length == 0) { println("There are no cameras available for capture."); exit(); } else { println("Available cameras:"); //printArray(cameras); cam = new Capture(this, cameras[0]); //cam = new Capture(this, 1280, 720, "c922 Pro Stream Webcam", 5); cam.start(); } System.loadLibrary(Core.NATIVE_LIBRARY_NAME); println(Core.VERSION); pixCnt1 = width*height*4;// number of bytes in the pixel buffer. pixCnt2 = width*height;//number of integers in the PImage pixels buffer. bArray = new byte[pixCnt1]; //temporary byte array buffer for OpenCV cv::Mat. iArray = new int[pixCnt2];//temporary integer array buffer for PImage pixels. camStream = createImage(640, 480, ARGB); } void draw() { background(0); if (cam.available() == true) { cam.read(); camStream = cam; Mat frame = toMat(camStream ); //CvType=CV_8UC4 //Mat undistorted = frame.clone(); camStream = toPImage(frame); } image(camStream, 0, 0, 640, 480); } //-------------------------------------------------------------------------- // Convert PImage (ARGB) to Mat (CvType = CV_8UC4) Mat toMat(PImage image) { //image.loadPixels(); //??? int w = image.width; int h = image.height; Mat mat = new Mat(h, w, CvType.CV_8UC4); byte[] data8 = new byte[w*h*4]; int[] data32 = new int[w*h]; arrayCopy(image.pixels, data32); ByteBuffer bBuf = ByteBuffer.allocate(w*h*4); IntBuffer iBuf = bBuf.asIntBuffer(); iBuf.put(data32); bBuf.get(data8); mat.put(0, 0, data8); //image.updatePixels(); return mat; } //--------------------------------------------------------------------------- // Convert Mat (CvType=CV_8UC4) to PImage (ARGB) PImage toPImage(Mat mat) { int w = mat.width(); int h = mat.height(); PImage image = createImage(w, h, ARGB); //image.loadPixels(); //??? byte[] data8 = new byte[w*h*4]; int[] data32 = new int[w*h]; mat.get(0, 0, data8); ByteBuffer.wrap(data8).asIntBuffer().get(data32); arrayCopy(data32, image.pixels); //image.updatePixels(); //??? return image; }

【问题讨论】:

    标签: java image opencv processing


    【解决方案1】:

    有趣的问题。它可能与时间和像素数据访问(2D 渲染器可能隐藏)有关。

    您可以通过使用get() 显式复制数据来绕过它:

    void draw() {
      Mat frame = toMat(camStream ); //CvType=CV_8UC4
      camStream = toPImage(frame);
      image(camStream, 0, 0, 640, 480);
    }
    
    void captureEvent(Capture cam){
      cam.read();
      // make copy of the data
      camStream = cam.get();
    }
    

    【讨论】:

    • 非常感谢!它就像一个魅力。在使用简单的“=”重新声明 PVectors 变量时,我也发现了一些问题,有时需要使用 .copy() 或提到 .get() 但我没有考虑在这种情况下使用它。还是我不明白它背后的逻辑……你对它背后的逻辑有一些见解吗?
    • @doku 关于 PVector .copy() 这听起来像是一个场景,当您需要独立的数据副本时,您将操纵对 PVector 的引用。想象一下,由于不同的原因(渲染/模拟管道的阶段等)对同一条数据有两个或多个引用:如果您在一个地方更改该引用:它将影响其他地方。在这里,您可以将管道拆分到数据相同的地方,然后复制数据,以便两个独立的功能可以运行而不会相互影响。 HTH
    • @doku 我也想我会给你指点OpenCV Processing library: 可能会很方便。 (例如opencv.loadImage(camStream); 然后opencv.getGray()opencv.getColor() 得到Matopencv.getOutput() 得到PImage。在两者之间你可以做过滤器/等。直接使用Mat 然后opencv.setColor()/opencv.setGray ();` 或OpenCV.toProcessing
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-27
    • 2014-03-11
    • 1970-01-01
    • 2018-09-04
    相关资源
    最近更新 更多