【问题标题】:Issue with stitching images using openCV for iOS使用适用于 iOS 的 openCV 拼接图像的问题
【发布时间】:2015-04-20 02:12:09
【问题描述】:

我正在尝试采用此处的代码:

https://github.com/foundry/OpenCVStitch

进入我的程序。然而,我已经撞墙了。此代码将已经存在的图像拼接在一起。我正在尝试制作的程序会将用户拍摄的图像拼接在一起。我得到的错误是当我将图像传递给缝合函数时,它说它们的大小无效(0 x 0)。

这里是拼接功能:

- (IBAction)stitchImages:(UIButton *)sender {
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{


        NSArray* imageArray = [NSArray arrayWithObjects:
                               chosenImage, chosenImage2, nil];
        UIImage* stitchedImage = [CVWrapper processWithArray:imageArray]; // error occurring within processWithArray function
        dispatch_async(dispatch_get_main_queue(), ^{

            NSLog (@"stitchedImage %@",stitchedImage);
            UIImageView *imageView = [[UIImageView alloc] initWithImage:stitchedImage];
            self.imageView = imageView;
            [self.scrollView addSubview:imageView];
            self.scrollView.backgroundColor = [UIColor blackColor];
            self.scrollView.contentSize = self.imageView.bounds.size;
            self.scrollView.maximumZoomScale = 4.0;
            self.scrollView.minimumZoomScale = 0.5;
            self.scrollView.contentOffset = CGPointMake(-(self.scrollView.bounds.size.width-self.imageView.bounds.size.width)/2, -(self.scrollView.bounds.size.height-self.imageView.bounds.size.height)/2);
            [self.spinner stopAnimating];

        });


    });

}

chosenImage 和 selectedImage2 是用户使用这两个函数拍摄的图像:

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
    savedImage = info[UIImagePickerControllerOriginalImage];

    // display photo in the correct UIImageView
    switch(image_location){
        case 1:
            chosenImage = info[UIImagePickerControllerOriginalImage];
            self.imageView2.image = chosenImage;
            image_location++;
            break;
        case 2:
            chosenImage2 = info[UIImagePickerControllerOriginalImage];
            self.imageView3.image = chosenImage2;
            image_location--;
            break;

    }
    // if user clicked "take photo", it should save photo
    // if user clicked "select photo", it should not save photo
    /*if (should_save){
     UIImageWriteToSavedPhotosAlbum(chosenImage, nil, nil, nil);
     }*/
    [picker dismissViewControllerAnimated:YES completion:NULL];

}

- (IBAction)takePhoto:(UIButton *)sender {
    UIImagePickerController *picker = [[UIImagePickerController alloc] init];
    picker.delegate = self;
    picker.allowsEditing = NO;
    picker.sourceType = UIImagePickerControllerSourceTypeCamera;
    //last_pressed = 1;
    should_save = 1;
    [self presentViewController:picker animated:YES completion:NULL];
}

stitchesImages 函数将这两个图像的数组传递给该函数:

+ (UIImage*) processWithArray:(NSArray*)imageArray
{
    if ([imageArray count]==0){
        NSLog (@"imageArray is empty");
        return 0;
        }
    cv::vector<cv::Mat> matImages;

    for (id image in imageArray) {
        if ([image isKindOfClass: [UIImage class]]) {
            cv::Mat matImage = [image CVMat3];
            NSLog (@"matImage: %@",image);
            matImages.push_back(matImage);
        }
    }
    NSLog (@"stitching...");
    cv::Mat stitchedMat = stitch (matImages); // error occurring within stitch function
    UIImage* result =  [UIImage imageWithCVMat:stitchedMat];
    return result;
}

这是程序遇到问题的地方。当它传递本地保存在应用程序文件中的图像时,它工作正常。但是,当传递保存在变量(chosenImage 和 selectedImage2)中的图像时,它不起作用。

这是在 processWithArray 函数中调用并导致错误的缝合函数:

cv::Mat stitch (vector<Mat>& images)
{
    imgs = images;
    Mat pano;
    Stitcher stitcher = Stitcher::createDefault(try_use_gpu);
    Stitcher::Status status = stitcher.stitch(imgs, pano);

    if (status != Stitcher::OK)
        {
        cout << "Can't stitch images, error code = " << int(status) << endl;
            //return 0;
        }
    return pano;
}

错误是“无法拼接图像,错误代码 = 1”。

【问题讨论】:

    标签: c++ ios c image opencv


    【解决方案1】:

    您正在达到内存限制。包含的四个演示图像为 720 x 960 像素,而您使用的是来自设备摄像头的全分辨率图像。

    这是导致崩溃的仪器中的分配跟踪,拼接来自相机的两个图像...

    这个 github 示例的目的是说明一些事情...
    (1)openCV如何与iOS集成;
    (2) 如何使用包装器分离 Objective-C 和 C++ 代码;
    (3)如何实现openCV中最基本的拼接功能。

    它最好被视为 iOS+openCV 的“hello world”项目,它的设计目的不是为了与相机图像稳健地工作。如果您想按原样使用我的代码,我建议您首先将相机图像缩小到可管理的大小(例如,长边最多 1000 个)。

    无论如何,您使用的 openCV 框架与项目一样古老。感谢您的问题,我刚刚更新了它(现在对 arm64 友好),尽管内存限制仍然适用。

    V2, OpenCVSwiftStitch 可能是您实验的一个更有趣的起点 - 界面是用 Swift 编写的,它使用 cocoaPods 来跟上 openCV 版本(尽管目前固定为 2.4.9.1,因为 2.4.10 中断一切)。所以它仍然说明了这三点,并且还展示了如何使用 Swift 和 C++,使用 Objective-C 包装器作为中介。

    我也许能够改进内存处理(通过传递指针)。如果是这样,我将向 v1 和 v2 推送更新。如果可以做出任何改进,请发送拉取请求。

    更新我又看了一遍,我很确定如果不深入研究 openCV 拼接算法,就不可能改进内存处理。图像已在堆上分配,因此无需改进。我希望最好的办法是平铺和缓存 openCV 作为流程的一部分创建的中间图像。如果我对此有任何进一步的了解,我将发布更新。同时,调整相机图像的大小是可行的方法。

    更新 2
    过了一会儿,我找到了问题的根本原因。当您使用来自 iOS 相机的图像作为输入时,如果这些图像是纵向的,那么它们对于 openCV 的输入尺寸(和方向)将不正确。这是因为所有 iOS 相机照片都是原生拍摄的“风景左侧”。像素尺寸是横向的,右侧是主页按钮。要显示纵向,“imageOrientation”标志设置为 UIImageOrientationRight。这指示操作系统将图像向右旋转 90 度以进行显示。

    图像未旋转,横向存储。不正确的像素方向会导致更高的内存需求和 openCV 中不可预测/损坏的结果。

    我在最新版本的 openCVSwiftStitch 中有 fixed this:在添加到 openCV 管道之前,必要时按像素旋转图像。

    【讨论】:

    • 感谢您提供所有这些信息。我一直在尝试自己运行 Instruments,但遇到了多个“Apple Mach-O Linker Error”问题。我将尝试减少相机图像,因为老实说,我没有资格对您的代码进行重大更改。当然,如果我碰巧发现任何改进,我会发送一个拉取请求。
    • @Ryan,查看我的更新。调整相机输出的大小是目前最好的选择。
    • 好的。如果您在平铺和缓存方面取得任何进展,请告诉我!谢谢你的一切。
    猜你喜欢
    • 2021-10-03
    • 1970-01-01
    • 2012-12-01
    • 2019-01-01
    • 2011-08-26
    • 1970-01-01
    • 2011-12-26
    • 2020-03-10
    • 2013-06-12
    相关资源
    最近更新 更多