简体   繁体   English

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

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

I am working on an iOS app that records video then does some processing on that video to create another video file.我正在开发一个录制视频的 iOS 应用程序,然后对该视频进行一些处理以创建另一个视频文件。 I'm getting really odd behavior from videoCapture though.不过,我从 videoCapture 得到了非常奇怪的行为。 It acts like the file has been opened but get() calls seem to return 1 for all the properties I care about (and I know they are not 1).它就像文件已经打开一样,但 get() 调用似乎为我关心的所有属性返回 1(我知道它们不是 1)。 My code looks like this:我的代码如下所示:

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;
  }

and the console output is:控制台输出是:

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.

I tried changing the file path to an invalid file in case it wasn't finding the file at all but that gave me "Cannot open the video file".我尝试将文件路径更改为无效文件,以防它根本找不到文件,但这给了我“无法打开视频文件”。 Any ideas would be appreciated.任何想法将不胜感激。 I'm thinking it could possibly be a permissions issue because I saw similar behavior when I tried to access a video in the camera roll with this code but this file is in my app's documents directory so I should have full access to it.我认为这可能是权限问题,因为当我尝试使用此代码访问相机胶卷中的视频时,我看到了类似的行为,但此文件位于我的应用程序的文档目录中,因此我应该拥有对它的完全访问权限。

It appears that this has been an issue for at least the last 2 years ( OpenCV on iOS - VideoCapture properties always return 1 ) and that the iOS version of videocapture simply doesn't work for opening files.看来这至少在过去 2 年一直是一个问题( iOS 上的 OpenCV - VideoCapture 属性总是返回 1 )并且视频捕获的 iOS 版本根本不适用于打开文件。

I found an alternate way to do this (opening the video with apple apis then converting each frame to an opencv Mat) but in general it seems that the iOS port of opencv is far from complete and nearly completely undocumented.我找到了另一种方法来做到这一点(用苹果 apis 打开视频,然后将每一帧转换为 opencv Mat),但总的来说,opencv 的 iOS 端口似乎远未完成,几乎完全没有记录。

First, get the URL of video file from UIImagePickerController object首先,从 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) 
}

After that, use this url to send to cvwrapper.mm file as shown in openVideoFile function之后,使用此 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");
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM