2

我正在开发一个使用 GStreamer 和 OpenCV 进行视频处理的应用程序。任务是从 OpenCV 源中获取图像,将它们推/拉到 GStreamer 管道中(进行转换和解码,稍后我必须流式传输视频数据)并在 Java 语言环境中处理图像。

所以我用 C 语言构建了一个本地框架来管理这个任务。现在我使用 JNI 访问我的 C-Library,并将正在执行的 GStreamer 主循环附加到 JVM。有些线程与我使用 SDL 库的图像处理无关,但没有调用任何 Java 方法。显然它到目前为止有效。我将原始图像导入 Java,我还可以使用ByteBuffer(在本机端创建的)get方法和System.err.println.

问题是在 GUI 中以某种方式显示这些图像。我将 Swing 框架用于我的图形环境。

因此,我像往常一样通过扩展 an 来制作一个快速而肮脏的图像视图,JPanel并且通常仅在我使用 Java 时才有效。

我重写了使用该方法paint绘制图像的Graphics.drawImage方法。图像是通过将原生回调传递的原始数据复制到一个整数数组中,然后将该整数数组分配给一个MemoryImageSource. 我使用createImage(JFrame 的)方法来获取Image对象。一切都返回显然有效的参考。没有异常被抛出。至少我看不到。

尝试了几种方法,并且MemoryImageSource到目前为止只对未生成的图像使用字节数组。但是数据在那里,我可以读取它!

我可以复制数据,显示字节数据,但我无法在我的自定义JPanel视图区域中显示可显示的图像。就像图像完全是黑色或透明的一样。

这个问题真的打败了我,我不知道如何说服这件事起作用。我认为这里的线程存在几个问题。但是对于这种特定情况,我没有更多资源。

我做错了什么,或者更好地如何以正确的方式去做。

附加:如果我更改窗口大小,应用程序有时也会崩溃或 GUI 冻结,所以我暂时避免这样做。因此,本机线程存在问题。

4

1 回答 1

1

我使用 OpenCV-Library 来访问安装在系统上的摄像头。我从每个抓取的帧中获取尺寸、颜色信息和 BGR-Samples,并让 GStreamer AppSrc 根据初始化整个事物的帧速率将图像拉入视频处理管道。初始管道如下所示:

OpenCV-Camera --> AppSrc --> VideoRate --> ffmpegcolorspace --> AppSink

它很快就会变得更加复杂,但现在这就是它的样子。

AppSink 在 Gstreamer“新缓冲区”信号上调用一个函数(其中一些与我的问题无关)。这些回调实现调用提供图像颜色和尺寸以及样本缓冲区的 Java 对象函数。所以这是关于我在做什么的简要信息。

现在我的问题:

看来我解决了我的问题。我现在使用另一种方式来创建我的图像,现在它可以工作了。

而不是像这样使用内存图像源:

//constructor, callback whatever
imageSource = new MemoryImageSource(data.width,data.height,rawdata,0,data.width);
...
//Paint method of a JFrame or what ever ...
...
image img = createImage(imageSource);
setBounds(100,100,img.getWidth(null),img.getHeight(null));
createBufferStrategy(2);

BufferStrategy strategy = getBufferStrategy();

Graphics gr = strategy.getDrawGraphics();           
gr.drawImage(img, 0, 0, null);
gr.dispose();

strategy.show();

我现在使用这几行适合我的行:

int[] nBits = {8, 8, 8};
ComponentSampleModel sampleModel = new ComponentSampleModel(DataBuffer.TYPE_BYTE, width, height, channels, width * channels, new int[] {2, 1, 0});
ColorSpace colorSpace = ColorSpace.getInstance(ColorSpace.CS_sRGB);
ColorModel colorModel = new ComponentColorModel(colorSpace, nBits, false, false,Transparency.OPAQUE,DataBuffer.TYPE_BYTE);

DataBufferByte db = new DataBufferByte(new byte[][] {buffer}, buffer.length);

WritableRaster raster = Raster.createWritableRaster(sampleModel, db, new Point(0, 0));
BufferedImage image = new BufferedImage(colorModel, raster, false, null);

缓冲区在这里表示我通过从本机端调用的方法获得的原始字节样本数组。

我还遇到了其他几个使用 swing 的问题,例如冻结 UI 或抛出这些错误消息的崩溃:

[xcb] Unknown request in queue while dequeuing
[xcb] Most likely this is a multi-threaded client and XInitThreads has not been called
[xcb] Aborting, sorry about that.
java: ../../src/xcb_io.c:178: dequeue_pending_request: assertion »!xcb_xlib_unknown_req_in_deq« failed.

这是因为我使用该UIManager.setLookAndFeel()方法将窗口外观设置为系统默认值。我没有将此与问题联系起来,因为如果您使用默认系统“外观和感觉”,我不知道 Swing 使用本机 UI 框架。删除它可以解决问题。我的研究将我带到了一个论坛帖子(德语),该帖子描述了这种情况仅发生在 Linux(Ubuntu)机器上的 Java(无本机部分)上,而相同的应用程序无需修改即可在 Windows 机器上运行。所以删除它解决了我的问题。我认为我的“图像未显示问题”与此有关,但我不知道,我不在乎,因为我现在工作。

于 2012-05-28T09:03:55.060 回答