Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在iOS上使用openCV进行高动态范围成像会产生乱码输出_Ios_Swift_Opencv_Hdr - Fatal编程技术网

在iOS上使用openCV进行高动态范围成像会产生乱码输出

在iOS上使用openCV进行高动态范围成像会产生乱码输出,ios,swift,opencv,hdr,Ios,Swift,Opencv,Hdr,我正试图在iOS上使用openCV 3从多次曝光中生成HDR图像,最终输出为EXR文件。当我试图创建HDR图像时,我注意到我的输出被篡改了。我认为尝试创建相机响应是一个错误,于是从零开始,将openCV上的HDR成像教程材料改编为iOS,但它产生了类似的结果。下面的C++代码返回一个混乱的图像: cv::Mat mergeToHDR (vector<Mat>& images, vector<float>& times) { imgs = image

我正试图在iOS上使用openCV 3从多次曝光中生成HDR图像,最终输出为EXR文件。当我试图创建HDR图像时,我注意到我的输出被篡改了。我认为尝试创建相机响应是一个错误,于是从零开始,将openCV上的HDR成像教程材料改编为iOS,但它产生了类似的结果。下面的C++代码返回一个混乱的图像:

cv::Mat mergeToHDR (vector<Mat>& images, vector<float>& times)
{
    imgs = images;
    Mat response;
    //Ptr<CalibrateDebevec> calibrate = createCalibrateDebevec();
    //calibrate->process(images, response, times);

    Ptr<CalibrateRobertson> calibrate = createCalibrateRobertson();
    calibrate->process(images, response, times);

    // create HDR
    Mat hdr;
    Ptr<MergeDebevec> merge_debevec = createMergeDebevec();
    merge_debevec->process(images, hdr, times, response);

    // create LDR
    Mat ldr;
    Ptr<TonemapDurand> tonemap = createTonemapDurand(2.2f);
    tonemap->process(hdr, ldr);

    // create fusion
    Mat fusion;
    Ptr<MergeMertens> merge_mertens = createMergeMertens();
    merge_mertens->process(images, fusion);

    /*
    Uncomment what kind of tonemapped image or hdr to return
    Returning one of the images in the array produces ungarbled output
    so we know the problem is unlikely with the openCV to UIImage conversion
    */

    //give back one of the images from the image array
    //return images[0];

    //give back one of the hdr images
    return fusion * 255;
    //return ldr * 255;
    //return hdr
}
cv::Mat mergeToHDR(向量和图像、向量和时间)
{
imgs=图像;
Mat响应;
//Ptr calibrate=createCalibrateDebevec();
//校准->过程(图像、响应、时间);
Ptr calibrate=createCalibrateRobertson();
校准->过程(图像、响应、时间);
//创建HDR
Mat-hdr;
Ptr merge_debevec=createMergeDebevec();
merge_debevec->process(图像、hdr、时间、响应);
//创建LDR
Mat-ldr;
Ptr tonemap=createTonemapDurand(2.2f);
音调映射->过程(hdr、ldr);
//创造融合
席状融合;
Ptr merge_mertens=createMergeMertens();
合并->处理(图像、融合);
/*
取消注释要返回的色调映射图像或hdr的类型
返回数组中的一个图像将生成未仲裁的输出
因此,我们知道openCV到UIImage转换不太可能出现问题
*/
//从图像阵列中返回一个图像
//返回图像[0];
//返回一个hdr图像
返回融合*255;
//返回ldr*255;
//返回hdr
}
这是图像的外观:

我分析了图像,尝试了各种颜色空间转换,但数据似乎是垃圾

openCV框架是openCV.org网站上最新编译的3.0.0版本。RC和alpha产生相同的结果,并且当前版本不会生成(对于iOS或OSX)。我想我的下一步将是尝试让框架从头开始编译,或者让示例在另一个平台下工作,看看问题是平台特定的还是openCV HDR函数本身。但在我这么做之前,我想我会在堆栈溢出上抛出这个问题,看看是否有人遇到过同样的问题,或者我是否遗漏了一些显而易见的东西

我已将示例xcode项目上载到此处:


让openCV与swift协同工作需要Github上用户foundry的帮助

感谢foundry为我指明了正确的方向。UIImage+OpenCV类扩展预期每个颜色通道8位,但是HDR函数每个通道32位(这实际上是我想要的)。在将图像矩阵转换为UIImage之前,将其转换回每个通道8位以用于显示目的,可以解决此问题

以下是生成的图像:

以下是固定函数:

cv::Mat mergeToHDR (vector<Mat>& images, vector<float>& times)
{
    imgs = images;
    Mat response;
    //Ptr<CalibrateDebevec> calibrate = createCalibrateDebevec();
    //calibrate->process(images, response, times);

    Ptr<CalibrateRobertson> calibrate = createCalibrateRobertson();
    calibrate->process(images, response, times);

    // create HDR
    Mat hdr;
    Ptr<MergeDebevec> merge_debevec = createMergeDebevec();
    merge_debevec->process(images, hdr, times, response);

    // create LDR
    Mat ldr;
    Ptr<TonemapDurand> tonemap = createTonemapDurand(2.2f);
    tonemap->process(hdr, ldr);

    // create fusion
    Mat fusion;
    Ptr<MergeMertens> merge_mertens = createMergeMertens();
    merge_mertens->process(images, fusion);

    /*
     Uncomment what kind of tonemapped image or hdr to return
     Convert back to 8-bits per channel because that is what
     the UIImage+OpenCV class extension is expecting
    */


    // tone mapped
    /*
    Mat ldr8bit;
    ldr = ldr * 255;
    ldr.convertTo(ldr8bit, CV_8U);
    return ldr8bit;
    */

    // fusion
    Mat fusion8bit;
    fusion = fusion * 255;
    fusion.convertTo(fusion8bit, CV_8U);
    return fusion8bit;

    // hdr
    /*
    Mat hdr8bit;
    hdr = hdr * 255;
    hdr.convertTo(hdr8bit, CV_8U);
    return hdr8bit;
    */
}

我可以确认示例代码在OSX下运行良好,而您的项目版本没有卸载iOS。这将问题缩小了一点。对前面注释的更正-代码在OSX上的工作原理相同,但使用imshow()可以正确地转换格式。在iOS上,通过包装器返回,有一个格式转换问题…谢谢@foundry。我重建了框架只是为了确定,遇到了同样的问题。回顾UIImage+OpenCV,initWithCVMat希望每个像素有一个硬编码的8位通道,所以我想问题可以在这里解决,或者我可以在将图像移交给UIKit之前将其转换为OpenCV中的8位。您捕获了多少图像,时间是捕获每个图像的时间。它是?
- (id)initWithCVMat:(const cv::Mat&)cvMat
{
    NSData *data = [NSData dataWithBytes:cvMat.data length:cvMat.elemSize() * cvMat.total()];
    CGColorSpaceRef colorSpace;

    size_t elemSize = cvMat.elemSize();
    size_t elemSize1 = cvMat.elemSize1();

    size_t channelCount = elemSize/elemSize1;
    size_t bitsPerChannel = 8 * elemSize1;
    size_t bitsPerPixel = bitsPerChannel * channelCount;

    if (channelCount == 1) {
        colorSpace = CGColorSpaceCreateDeviceGray();
    } else {
        colorSpace = CGColorSpaceCreateDeviceRGB();
    }

    // Tell CGIImageRef different bitmap info if handed 32-bit
    uint32_t bitmapInfo = kCGImageAlphaNone | kCGBitmapByteOrderDefault;

    if (bitsPerChannel == 32 ){
        bitmapInfo = kCGImageAlphaNoneSkipLast | kCGBitmapFloatComponents | kCGBitmapByteOrder32Little;
    }

    CGDataProviderRef provider = CGDataProviderCreateWithCFData((__bridge CFDataRef)data);

    // Creating CGImage from cv::Mat
    CGImageRef imageRef = CGImageCreate(cvMat.cols,                                 //width
                                        cvMat.rows,                                 //height
                                        bitsPerChannel,                             //bits per component
                                        bitsPerPixel,                               //bits per pixel
                                        cvMat.step[0],                              //bytesPerRow
                                        colorSpace,                                 //colorspace
                                        bitmapInfo,                                 // bitmap info
                                        provider,                                   //CGDataProviderRef
                                        NULL,                                       //decode
                                        false,                                      //should interpolate
                                        kCGRenderingIntentDefault                   //intent
                                        );                     

    // Getting UIImage from CGImage
    self = [self initWithCGImage:imageRef];
    CGImageRelease(imageRef);
    CGDataProviderRelease(provider);
    CGColorSpaceRelease(colorSpace);

    return self;
}