OpenCV videoCapture 为 iOS 应用程序文档目录中的文件提供了错误的属性

OpenCV videoCapture gives bad properties for file in iOS app documents directory

我正在开发一个 iOS 应用程序,它可以录制视频然后对该视频进行一些处理以创建另一个视频文件。不过,我从 videoCapture 得到了非常奇怪的行为。它就像文件已被打开,但 get() 调用似乎 return 1 对于我关心的所有属性(我知道它们不是 1)。我的代码如下所示:

VideoCapture cap(fileIn); // open the video file for reading

if ( !cap.isOpened() )  // if not success, exit program
  {
    cout << "Cannot open the video file" << endl;
    return -1;
  }
  else{
    cout << "File Open " << fileIn << endl;
  }

  double dFps = cap.get(CV_CAP_PROP_FPS); //get the frames per seconds of the video
  cout << "Frames per second = " << dFps << endl;

  double dWidth = cap.get(CV_CAP_PROP_FRAME_WIDTH); //get the width of frames of the video
  double dHeight = cap.get(CV_CAP_PROP_FRAME_HEIGHT); //get the height of frames of the video
  cout << "Frame Size = " << dWidth << "x" << dHeight << endl;

  Size frameSize(static_cast<int>(dWidth), static_cast<int>(dHeight));

  double dFrameCount = cap.get(CV_CAP_PROP_FRAME_COUNT);
  cout << "Frame count = " << dFrameCount << endl;

  VideoWriter oVideoWriter (fileOut, CV_FOURCC('m','p', '4', 'v'), dFps, frameSize, true); //initialize the VideoWriter object

  if ( !oVideoWriter.isOpened() ) //if not initialize the VideoWriter successfully, exit the program
  {
    cout << "ERROR: Failed to write the video" << endl;
    return -1;
  }
  else{
    cout << "Output file open." << endl;
  }

控制台输出为:

File Open /var/mobile/Containers/Data/Application/7CEE8B87-BD50-4172-8F62-A74AD7F3C45A/Documents/15318B74-07D9-43EE-932F-224EDCA9CDA7.mov
Frames per second = 1
Frame Size = 1x1
Frame count = 1
Output file open.

我尝试将文件路径更改为无效文件,以防它根本找不到该文件,但这给了我 "Cannot open the video file"。任何想法,将不胜感激。我认为这可能是一个权限问题,因为当我尝试使用此代码访问相机胶卷中的视频时,我看到了类似的行为,但此文件位于我的应用程序的文档目录中,因此我应该可以完全访问它。

这似乎是至少过去 2 年 (OpenCV on iOS - VideoCapture properties always return 1) 的一个问题,并且 iOS 版本的视频捕捉根本无法打开文件。

我找到了另一种方法来做到这一点(用 apple api 打开视频,然后将每一帧转换为 opencv Mat)但总的来说,opencv 的 iOS 端口似乎远未完成且接近完成完全没有记录。

首先,从 UIImagePickerController 对象中获取 URL 视频文件

func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
    picker.dismiss(animated: true, completion: nil)
    
    let url = info[UIImagePickerController.InfoKey.mediaURL] as? NSURL
    let asset   = AVURLAsset.init(url: url! as URL)
    
    
    let mainstoryBoard = UIStoryboard(name:"Main", bundle: nil)
    let viewcontroller = mainstoryBoard.instantiateViewController(withIdentifier:"ViewController") as! ViewController
    viewcontroller.url = url
    viewcontroller.asset = asset
    self.navigationController?.pushViewController(viewcontroller, animated: true) 
}

之后,使用此 url 发送到 cvwrapper.mm 文件,如 openVideoFile 函数所示

- (void)openVideoFile:(NSURL *)fileName {
    
    NSString *filename = fileName.path;
    std::string filePath = [filename UTF8String];
    
    cv::VideoCapture capture(filePath);
    
    if (!capture.isOpened()) {
        printf("@Error Opening video file");
        // failed, print error message
    }
    else {
        printf("File Opened");
    }
}