繁体   English   中英

使用iOS版openCV拼接图像的问题

[英]Issue with stitching images using openCV for iOS

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

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

        });


    });

}

selectedImage和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函数中被调用并导致错误的stitch函数:

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”。

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

这是导致崩溃的仪器中的分配轨迹,它拼接了相机中的两个图像...

在此处输入图片说明

这个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破坏了所有功能)。 因此,它仍然说明了这三点,并且还说明了如何使用Objective-C包装器作为中介,在C ++中使用Swift。

我也许能够改善内存处理(通过传递指针)。 如果是这样,我会将更新同时推送到v1和v2。 如果 可以进行任何改进,请发送请求请求。

更新我已经有了另一种外观,我相当确定如果不更深入地了解openCV拼接算法,就不可能改善内存处理。 映像已经分配在堆上,因此没有任何改进。 我希望最好的选择是平铺和缓存似乎是openCV作为过程一部分创建的中间图像。 如果对此有任何进一步的了解,我将发布更新。 同时,调整摄像机图像的大小是必经之路。

更新2
稍后,我发现了问题的根本原因。 当您使用iOS相机的图像作为输入时,如果这些图像是纵向的,则openCV的输入尺寸(和方向)将不正确。 这是因为所有iOS相机的照片都是本地拍摄的(“左向风景”)。 像素尺寸为横向,主页按钮在右侧。 为了显示肖像,将“ imageOrientation”标志设置为UIImageOrientationRight。 表示操作系统将图像向右旋转90度以进行显示。

图像未旋转地存储,向左横​​向移动。 错误的像素方向会导致更高的内存要求,并且openCV中的结果无法预测/损坏。

我已经在最新版本的openCVSwiftStitch中修复了此问题:在添加到openCV管道之前,必要时将图像按像素方向旋转。

暂无
暂无

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

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