在处理IDEP3D(OpenGL)渲染器中将PImage转换为Mat-JavaOpenCV

在处理IDEP3D(OpenGL)渲染器中将PImage转换为Mat-JavaOpenCV,java,image,opencv,processing,Java,Image,Opencv,Processing,我编写了一个代码,在OpenCV Mat到PImage(ARGB)和返回之间进行转换。我使用网络摄像机作为输入,通过处理视频库捕获。它适用于Java2D渲染器,但不适用于P2D或P3D渲染器。可能是什么问题 它尝试使用loadPixels()和updatePixels()语句-它不起作用。另外,P3D渲染器中的相机图像无法通过PImage=cam.copy()复制到PImage或pimage=cam.get()但必须像pimage=cam那样分配;我不明白这是为什么 我使用的是原生Opencv

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

它尝试使用
loadPixels()
updatePixels()
语句-它不起作用。另外,P3D渲染器中的相机图像无法通过
PImage=cam.copy()复制到PImage
pimage=cam.get()但必须像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;
    }


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

您可以通过使用以下方法显式复制数据来解决此问题:


非常感谢你!它就像一个符咒。在用简单的“=”重新说明PVectors变量时,我也发现了一些问题,有时需要使用.copy()或提到.get(),但我没有想到在这个场景中使用它。我仍然不明白背后的逻辑…你对背后的逻辑有什么见解吗?@doku关于PVector
.copy()
这听起来像是一个场景,当你需要独立复制数据时,你会操纵对PVector的引用。想象一下,由于不同的原因(渲染/模拟管线的阶段等),对同一数据段有两个或多个引用:如果在一个位置更改该引用,将影响其他位置。在这种情况下,您可以拆分管道,其中最多有一个点的数据是相同的,然后复制数据,以便两个独立的功能可以运行而不会相互影响。HTH@doku我想我会给你指出:可能很方便。(例如,
opencv.loadImage(camStream);
然后
opencv.getGray()
opencv.getColor()
以获取
Mat
opencv.getOutput()
以获取
PImage
。在这两者之间,您可以进行筛选/等操作。然后直接使用Mat
opencv.setColor()
/opencv.setGray();`or
OpenCV.toProcessing
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();
}