ios - 使用 Open CV iOS 自动旋转和拉伸(stretch)图像。怎么修?

标签 ios xcode opencv

我正在使用 OpenCV 3。我已经使用 POD 在我的 Xcode 项目中安装了该框架。为了将图像(由相机拍摄)转换为黑白图像,我使用了自适应高斯阈值。下面是我用过的代码

@implementation MyClass

+(UIImage *)toBlackAndWhite:(UIImage *)s {    
        cv::Mat input;
cv::Mat output;
input = [MyClass cvMatFromUIImage:s];
cv::cvtColor(input, input, cv::COLOR_BGR2GRAY);
output = cv::Mat(input.cols, input.rows, IPL_DEPTH_8U, 1);
cv::adaptiveThreshold(input, output, 255,CV_ADAPTIVE_THRESH_GAUSSIAN_C,CV_THRESH_BINARY, 75, 25);
return [MyClass imageWithCVMat:output];    
}
//Ref:Open CV documentation
+ (cv::Mat)cvMatFromUIImage:(UIImage *)image
{
    CGColorSpaceRef colorSpace = CGImageGetColorSpace(image.CGImage);
    CGFloat cols = image.size.width;
    CGFloat rows = image.size.height;

    cv::Mat cvMat(rows, cols, CV_8UC4); // 8 bits per component, 4 channels (color channels + alpha)

    CGContextRef contextRef = CGBitmapContextCreate(cvMat.data,                 // Pointer to  data
                                                    cols,                       // Width of bitmap
                                                    rows,                       // Height of bitmap
                                                    8,                          // Bits per component
                                                    cvMat.step[0],              // Bytes per row
                                                    colorSpace,                 // Colorspace
                                                    kCGImageAlphaNoneSkipLast |
                                                    kCGBitmapByteOrderDefault); // Bitmap info flags

    CGContextDrawImage(contextRef, CGRectMake(0, 0, cols, rows), image.CGImage);
    CGContextRelease(contextRef);

    return cvMat;
}

//Ref:Open CV documentation
+ (UIImage *)imageWithCVMat:(const cv::Mat&)cvMat
{
    NSData *data = [NSData dataWithBytes:cvMat.data length:cvMat.elemSize() * cvMat.total()];

    CGColorSpaceRef colorSpace;

    if (cvMat.elemSize() == 1) {
        colorSpace = CGColorSpaceCreateDeviceGray();
    } else {
        colorSpace = CGColorSpaceCreateDeviceRGB();
    }

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

    CGImageRef imageRef = CGImageCreate(cvMat.cols,                                     // Width
                                        cvMat.rows,                                     // Height
                                        8,                                              // Bits per component
                                        8 * cvMat.elemSize(),                           // Bits per pixel
                                        cvMat.step[0],                                  // Bytes per row
                                        colorSpace,                                     // Colorspace
                                        kCGImageAlphaNone | kCGBitmapByteOrderDefault,  // Bitmap info flags
                                        provider,                                       // CGDataProviderRef
                                        NULL,                                           // Decode
                                        false,                                          // Should interpolate
                                        kCGRenderingIntentDefault);                     // Intent

    UIImage *image = [[UIImage alloc] initWithCGImage:imageRef];
    CGImageRelease(imageRef);
    CGDataProviderRelease(provider);
    CGColorSpaceRelease(colorSpace);

    return image;
}


@end

问题:我得到的图像逆时针旋转了 90° 并且被拉伸(stretch)了。请提出一些建议,我该如何解决。请看

Original Image

Processed Image

最佳答案

问题是由于 UIImageUIImageOrientation 引起的。

背景:
当您将 iPhone 置于横向模式(右侧的主页按钮)时,拍照时,该照片具有“向上”方向(是的,这是默认设置)。因此,当您以人像模式拍照时,方向为“右”。对于“右”方向的照片(肖像),它们实际上仍以横向模式保存。当您查看照片时,照片看起来不错,因为“UIImage”自动将其从横向模式旋转为纵向模式。 (向右旋转 90 度,宽度 -> 高度,高度 -> 宽度)

拉伸(stretch)问题是怎么产生的?
对于具有“右”和“左”方向的照片,旋转后的 UIImage 数据将被转换为 OpenCV Mat 对象,这使得“宽度”和“高度”<强>交换
解决方案:我们需要将原始的'width'和'height'赋给横向模式的MatUIImageCGImage 属性有原始'width'和'height'的图像数据,我们可以使用它。

‘旋转90°’问题是怎么产生的?
OpenCV Mat 对象不保留方向信息,因此在我们将 UIImage 转换为 Mat 并将其转换回来后,方向会丢失。
解决方案:保持方向并将其应用于结果 UIImage 对象。

问题相关代码:

+(UIImage *)toBlackAndWhite:(UIImage *)s {
     //Create an image with original width and height  
     UIImage *imageUp = [UIImage imageWithCGImage:[s CGImage]];
     //......
     input = [MyClass cvMatFromUIImage:imageUp];

     //......

     UIImage *handledImage = [MyClass imageWithCVMat:output];  
     //Set orientation to the result image
     UIImage *finalImage = [UIImage imageWithCGImage:[handledImage CGImage] scale:[s scale] orientation: s.imageOrientation];
     return finalImage;
}

关于ios - 使用 Open CV iOS 自动旋转和拉伸(stretch)图像。怎么修?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36010735/

相关文章:

ios - 是否可以使用 ABPersonViewController 从我的 iOS 应用更新链接的联系人?

iOS11 视觉框架映射所有面部特征点

swift - Swift 中 "<-"的含义

ios - Xcode:多个目录和子目录

python - OpenCV 图像校正以填充图像中的空白空间和孔洞

ios - 离线查询数据-实时数据库的实现及功能

iOS:对 iCarousel 中未选择 View 的约束

swift - 我需要帮助快速使用陀螺仪

python - opencv中与flann的特征匹配

c++ - OpenCV VideoCapture 输出图像剪切到左上四分之一