小编Jas*_*son的帖子

有效实现Java Native Interface Webcam Feed

我正在开发一个项目,该项目从网络摄像头获取视频输入并向用户显示运动区域.我在这个项目中的"beta"尝试是使用Java Media Framework来检索网络摄像头源.通过一些实用功能,JMF可以方便地将网络摄像头帧作为BufferedImages返回,我构建了大量的框架来处理.但是,我很快意识到JMF不再受Sun/Oracle的支持,并且一些较高的网络摄像头分辨率(720p)无法通过JMF接口访问.

我想继续像BufferedImages一样处理帧,并使用OpenCV(C++)来获取视频源.单独使用OpenCV的框架,我发现OpenCV可以很好地有效地返回高清摄像头帧并将它们绘制到屏幕上.

我认为将这些数据提供给Java并实现相同的效率非常简单.我刚刚编写了JNI DLL,将这些数据复制到BufferedImage中并将其返回给Java.但是,我发现我正在进行的数据复制实际上是在阻碍性能.我的目标是30 FPS,但是只需要大约100毫秒就可以将OpenCV返回的char数组中的数据复制到Java BufferedImage中.相反,我看到大约2-5 FPS.

返回帧捕获时,OpenCV提供指向1D char数组的指针.这些数据需要提供给Java,显然我没有时间复制任何数据.

我需要一个更好的解决方案来将这些帧捕获到BufferedImage中.我正在考虑的一些解决方案,我认为其中没有一个非常好(相当肯定它们也会表现不佳):

(1)覆盖BufferedImage,并通过对DLL进行本机调用,从各种BufferedImage方法返回像素数据.(而不是一次进行数组复制,我按照调用代码的请求返回单个像素).请注意,调用代码通常需要图像中的所有像素来绘制图像或对其进行处理,因此这个单独的像素抓取操作将在2D for循环中实现.

(2)指示BufferedImage使用java.nio.ByteBuffer以某种方式直接访问OpenCV返回的char数组中的数据.非常感谢有关如何完成此任务的任何提示.

(3)用C++做一切并忘记Java.好吧,是的,这听起来像是最合乎逻辑的解决方案,但是我没有时间从头开始这个为期数月的项目.

截至目前,我的JNI代码已被编写为返回BufferedImage,但此时我愿意接受返回1D char数组然后将其放入BufferedImage.

顺便说一句......这里的问题是:将1D char数组图像数据复制到BufferedImage的最有效方法是什么?

提供了(低效)代码,我用它从OpenCV中获取图像并复制到BufferedImage:

JNIEXPORT jobject JNICALL Java_graphicanalyzer_ImageFeedOpenCV_getFrame
  (JNIEnv * env, jobject jThis, jobject camera)
{
 //get the memory address of the CvCapture device, the value of which is encapsulated in the camera jobject
 jclass cameraClass = env->FindClass("graphicanalyzer/Camera");
 jfieldID fid = env->GetFieldID(cameraClass,"pCvCapture","I");

 //get the address of the CvCapture device
 int a_pCvCapture = (int)env->GetIntField(camera, fid);

 //get a pointer to the CvCapture device
    CvCapture *capture …
Run Code Online (Sandbox Code Playgroud)

java performance webcam java-native-interface opencv

10
推荐指数
1
解决办法
2515
查看次数

按值返回std :: string是否安全?

在以下代码中,字符串封装在类Foo中.

对Foo :: getText()的调用按值返回字符串.这将创建字符串对象的第二个实例,但现在两个字符串对象都指向堆上的相同char缓冲区.

删除Foo实例时,将自动销毁封装的字符串,因此将删除堆上的char缓冲区.

即使getText()按值返回字符串,生成的字符串对象仍依赖于原始字符串对象的生命周期,以便保留它们相互指向的char缓冲区.

这是不是意味着打印retval到终端是对堆已经免费的内存的无效访问?

class Foo
{
    Foo(const char* text) :
       str(text)
    {
    }

    std::string getText()
    {
        return str;
    }

    std::string str;
};

int main()
{
    Foo pFoo = new Foo("text");
    std::string retval = foo.getText();
    delete pFoo;
    cout << retval;  // invalid memory access to char buffer?
}
Run Code Online (Sandbox Code Playgroud)

我想很多人都认为,因为字符串是按值返回的,所以不需要关心Foo中原始字符串的生命周期.这个问题与字符串没有严格的关系,但实际上适用于任何具有封装指针的类,这些指针在销毁时是免费的.但是在弦乐方面,最好的做法是什么?

  1. 永远不要按值返回字符串?
  2. 如果保证原始字符串的生命周期,只按值返回字符串?
  3. 总是复制一下这个字符串? return std::string(retval.c_str());
  4. 与来电者签订合同getText()

编辑:

我想我被RVO误导了.此示例中的所有三个字符串都在同一地址返回c_str.RVO应该受到指责吗?

class Obj
{
public:
    Obj() : s("text")
    {
        std::printf("%p\n", s.c_str());
    }

    std::string getText() { …
Run Code Online (Sandbox Code Playgroud)

c++ string memory-management return-by-value

-2
推荐指数
2
解决办法
1639
查看次数