【问题标题】:How to open cv::VideoWriter in Android如何在 Android 中打开 cv::VideoWriter
【发布时间】:2014-02-28 02:13:48
【问题描述】:

我正在使用 JNI 在 Android 中使用 OpenCV 2.4.8。

我用 VideoCapture 打开相机,我想录制它。我在 cv::Mat 中有图像,它正确显示在屏幕上。

但是,当我尝试打开 VideoCapture 时,它​​总是返回 false。

       // Camera resolution is 640x480 and its fine.
       _camera_resolution = calc_optimal_camera_resolution(u.name, 640, 480);  

        // Store in sdcard, I have permission in AndroidManifest.xml
        const char * videoName = "/sdcard/videoTest.avi"; 

             // Segmentation fault 11! this method doesnt work in Android?  so commented
            //const int ex = static_cast<int>(_reader.get(CV_CAP_PROP_FOURCC)); 

            // Segmentation fault 11! too!!! so commented
            //const double fps = _reader.get(CV_CAP_PROP_FPS);      

            // Try to open
            _isRecording = _writer.open(videoName, -1, 30, _camera_resolution, true); 
            // Return FALSE always
            if(!_writer.isOpened())
            {
                LOGE("rec - Error opening video writer");
            }
            else
            {
                LOGD("rec - Video writer opened in startRecording");
            }

我曾尝试用作 FOURCC:

CV_FOURCC('M', 'J', 'P', 'G') 和 CV_FOURCC('M', 'P', '4', 'V') // 不起作用!

我尝试过不同的 fps 比率,15.0、30.0...

相机分辨率似乎有效,因为当我打印时值是正确的。

为什么不能正确打开?

【问题讨论】:

  • 你有写权限吗?
  • 正如我在帖子中所说,我的AndroidManifest有权写入:
  • 可能 sdcard 位置有误,在我的应用程序中我使用的是 /mnt/sdcard/filename 之类的东西。
  • 我可以用 imwrite("/sdcard/image.jpg", mat);
  • afaik,由于缺少 ffmpeg 后端,videowriter 无法在 android 上运行

标签: opencv android-ndk java-native-interface video-capture


【解决方案1】:
cv::VideoWriter writer;
writer.open("your_mp4_file_path", cv::VideoWriter::fourcc('H', '2', '6', '4'),
                    15, //framerate
                    cv::Size(720, 1280),
                    true);
writer << mat_frame;

// remember writer.release() when finish

android opencv 4.5.2,带有 ffmpeg + openh264 的 opencv,对我来说很好用

【讨论】:

    【解决方案2】:

    ('M','J','P','G') 是android在使用.avi ext时唯一支持的。最重要的是#include stdio.h,没有这个你将无法打开VideoWriter视频

    【讨论】:

      【解决方案3】:

      据我所知,OpenCV4adnroid 不支持视频读写。 尝试使用编码器选项重建您的 Opencv: (例如: WITH_FFMPEG=YES 或 WITH_VFW=YES )

      或者尝试保存一个图像序列,然后用 java 代码从这个序列中编码一个视频 我尝试了下一个提议(ref

      public void imageToMP4(BufferedImage bi) {
          // A transform to convert RGB to YUV colorspace
          RgbToYuv420 transform = new RgbToYuv420(0, 0);
      
          // A JCodec native picture that would hold source image in YUV colorspace
          Picture toEncode = Picture.create(bi.getWidth(), bi.getHeight(), ColorSpace.YUV420);
      
          // Perform conversion
          transform.transform(AWTUtil.fromBufferedImage(bi), yuv);
      
          // Create MP4 muxer
          MP4Muxer muxer = new MP4Muxer(sink, Brand.MP4);
      
          // Add a video track
          CompressedTrack outTrack = muxer.addTrackForCompressed(TrackType.VIDEO, 25);
      
          // Create H.264 encoder
          H264Encoder encoder = new H264Encoder(rc);
      
          // Allocate a buffer that would hold an encoded frame
          ByteBuffer _out = ByteBuffer.allocate(ine.getWidth() * ine.getHeight() * 6);
      
          // Allocate storage for SPS/PPS, they need to be stored separately in a special place of MP4 file
          List<ByteBuffer> spsList = new ArrayList<ByteBuffer>();
          List<ByteBuffer> ppsList = new ArrayList<ByteBuffer>();
      
          // Encode image into H.264 frame, the result is stored in '_out' buffer
          ByteBuffer result = encoder.encodeFrame(_out, toEncode);
      
          // Based on the frame above form correct MP4 packet
          H264Utils.encodeMOVPacket(result, spsList, ppsList);
      
          // Add packet to video track
          outTrack.addFrame(new MP4Packet(result, 0, 25, 1, 0, true, null, 0, 0));
      
          // Push saved SPS/PPS to a special storage in MP4
          outTrack.addSampleEntry(H264Utils.createMOVSampleEntry(spsList, ppsList));
      
          // Write MP4 header and finalize recording
          muxer.writeHeader();
      }
      

      您可以从项目网站或通过 Maven 下载 JCodec 库,为此将以下 sn-p 添加到您的 pom.xml:

      <dependency>
          <groupId>org.jcodec</groupId>
          <artifactId>jcodec</artifactId>
          <version>0.1.3</version>
      </dependency>
      

      安卓: Android 用户可以使用以下方法将 Android Bitmap 对象转换为 JCodec 原生格式:

      public static Picture fromBitmap(Bitmap src) {
          Picture dst = Picture.create((int)src.getWidth(), (int)src.getHeight(), RGB);
          fromBitmap(src, dst);
          return dst;
      }
      
      public static void fromBitmap(Bitmap src, Picture dst) {
          int[] dstData = dst.getPlaneData(0);
          int[] packed = new int[src.getWidth() * src.getHeight()];
      
          src.getPixels(packed, 0, src.getWidth(), 0, 0, src.getWidth(), src.getHeight());
      
          for (int i = 0, srcOff = 0, dstOff = 0; i < src.getHeight(); i++) {
              for (int j = 0; j < src.getWidth(); j++, srcOff++, dstOff += 3) {
                  int rgb = packed[srcOff];
                  dstData[dstOff]     = (rgb >> 16) & 0xff;
                  dstData[dstOff + 1] = (rgb >> 8) & 0xff;
                  dstData[dstOff + 2] = rgb & 0xff;
              }
          }
      }
      

      【讨论】:

      猜你喜欢
      • 2014-08-01
      • 1970-01-01
      • 2021-04-13
      • 1970-01-01
      • 1970-01-01
      • 2018-02-23
      • 2018-07-12
      • 1970-01-01
      相关资源
      最近更新 更多