我有以下问题: 我有一个使用原生OpenCV代码的Android应用程序。在第一步中,由OpenCV编辑的帧来自相机。然后处理它们并在显示器上绘制。
但是,我的要求现在已经改变了。必须编辑的帧来自存储在SD卡上的视频文件。它们必须由openCV代码处理,然后存储在新的视频文件中。
在阅读了很多东西之后,我发现Android没有内置的东西可以逐帧正确地读取视频文件并允许在这样做时处理帧。在计算机上,OpenCV具有VideoCapture功能。但这不适用于Android,因为openCV没有附带的ffmpeg。
在阅读了更多内容之后,我发现JavaCV附带了一个FFMPEGFrameGrabber和一个FFMPEGFrameRecorder。所以,我实现了现在允许我从视频中获取单帧的所有内容,获取IplImage帧并将该帧存储在新视频中。
现在问题: 在获取和存储期间,必须使用原始OpenCV代码处理IplImage帧,因为将完整代码移植到JavaCV是不可行的。
所以首先我编写了一个小测试JNI函数,它获取MAT对象的地址并在其上绘制一个小圆圈。
extern "C" {
JNIEXPORT void JNICALL Java_de_vion_postprocessing_step2_EyeTracking_editFrame(
JNIEnv*, jobject, jlong thiz, jlong addrRgba) {
//Convert the mat addresses into the objects
Mat& rgbFrame = *(Mat*) addrRgba;
Point2i scaledSmoothPoint(100,100);
circle(rgbFrame, scaledSmoothPoint, 20, YELLOW, -1);
}
当我读到IplImage扩展CvArr时,我只需在我的代码中调用函数,如下所示:
captured_frame = grabber.grab();
if (captured_frame == null) {
// no new frames
break;
}
editFrame(captured_frame .address());
但是,我现在收到以下错误:
06-12 18:58:23.135: E/cv::error()(6498): OpenCV Error: Assertion failed (cn <= 4) in
void cv::scalarToRawData(const Scalar&, void*, int, int), file
/home/reports/ci/slave_desktop/50-SDK/opencv/modules/core/src/matrix.cpp, line 845
06-12 18:58:23.135: A/libc(6498): Fatal signal 6 (SIGABRT) at 0x00001962 (code=-6),
thread 6526 (AsyncTask #1)
最后,我提问: 如何使用nativeOpenCV处理IplImage帧,最后将此IplImage帧存储在录像机中。
我也对新的想法持开放态度,不一定需要JavaCV,只要我不必自己编写FrameGrabber和FrameRecorder。
祝你好运, 安德烈
答案 0 :(得分:3)
英特尔发布了一款名为INDE的新工具,其中包含一个名为INDE Media Pack的组件。然而,这是使用Java。 Media Pack采用Android媒体框架,并对某些功能进行了大量封装,并添加了一些内容,使视频/音频/图像处理变得非常简单。您可以从here
下载以下是如何使用INDE从特定帧开始并以帧结束(不是完整代码,只是为了给您一个想法)进行视频捕获。下载工具后,您将找到大量示例代码
public void start(String videoPath) throws IOException
{
if (isStarted())
{
throw new IllegalStateException(TAG + " already started!");
}
capturer = new GLCapture(new AndroidMediaObjectFactory());
capturer.setTargetFile(videoPath);
capturer.setTargetVideoFormat(videoFormat);
capturer.start();
isStarted = true;
isConfigured = false;
framesCaptured = 0;
}
希望这会有所帮助。