IOS下利用OpenCV框架去除视频水印

想做个去水印的APP,第一个想到的就是CV里的inpaint图像修复技术。就想着把CV框架放在IOS中用,由于第一次接触IOS的开发,就看了两本实习时候导师大神推荐的书,很多东西都不太了解,虽然CV官网给了IOS的frame框架但做的过程中还是遇到不少坑,并且网上关于在IOS下使用OpenCV进行图像处理的资料比较少,所以就记录下做的过程中爬过的一些坑,一来由于经常搬CSND的砖,也算为D友们做点贡献。二来也是记录下自己,不然一段时间又全忘完了。由于是互联网小白纸,基本上都是靠着CSDN和GitHub各种搬砖,有写错的地方还烦请各位大佬指出来便于成长,感激不尽,话不多说上硬货。

一、OpenCV框架集成

方法1,在OpenCV官网的下载IOS pack,直接将framework拖入项目;

方法2,使用CocoaPods直接集成OpenCV。

两种方法都可以顺利集成OpenCV框架,但在编译的时候遇到了第一个坑!

坑:提示了一堆文件not found


解决方法:opencv需要执行c++编译,xcode的.m文件并不支持相应的编译条件,需要将所有直接或者间接用到opencv头文件的所有.m文件变成.mm文件后缀,告诉编译器是oc++文件执行编译。

这个坑如果不处理好是很坑的...因为所有直接或者间接用到opencv头文件的.m文件都得改文件后缀,就会形成连锁反应导致所有的.m文件都得改掉,所以正确的方法应该是将仅利用opencv的实现.mm文件进行封装,仅保留.h的接口提供外部使用。


二、图像格式转换

OpenCV的图像通用格式是Mat类型,而在IOS中经常直接使用的图像类型是UIImage,这就牵扯到图像类型转换的问题,对于类型转换官网给了直接的Demo可以使用:

-(cv::Mat)CVMat:(UIImage*)imageSrc

{

    

    CGColorSpaceRef colorSpace = CGImageGetColorSpace(imageSrc.CGImage);

    CGFloat cols = imageSrc.size.width;

    CGFloat rows = imageSrc.size.height;

    

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

    

    CGContextRef contextRef = CGBitmapContextCreate(cvMat.data,                 // Pointer to backing 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), imageSrc.CGImage);

    CGContextRelease(contextRef);

    

    return cvMat;

}

-(UIImage *)UIImageFromCVMat:(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);

    

    // Creating CGImage from cv::Mat

    CGImageRef imageRef = CGImageCreate(cvMat.cols,                                 //width

                                        cvMat.rows,                                 //height

                                        8,                                          //bits per component

                                        8 * cvMat.elemSize(),                       //bits per pixel

                                        cvMat.step[0],                            //bytesPerRow

                                        colorSpace,                                 //colorspace

                                        kCGImageAlphaNone|kCGBitmapByteOrderDefault,// bitmap info

                                        provider,                                   //CGDataProviderRef

                                        NULL,                                       //decode

                                        false,                                      //should interpolate

                                        kCGRenderingIntentDefault                   //intent

                                        );

    UIImage *finalImage = [UIImage imageWithCGImage:imageRef];

    CGImageRelease(imageRef);

    CGDataProviderRelease(provider);

    CGColorSpaceRelease(colorSpace);

    

    return finalImage;

}

但在这里使用时就遇到了第二个坑!直接使用这两个函数对一个UIImage进行处理,即先用(cv::Mat)CVMat:(UIImage*)imageSrc转换成Mat,再用(UIImage *)UIImageFromCVMat:(cv::Mat)cvMat,你会发现转换后的图像显示时跟转换前的图像方向发生了变化。分析后发现因为转换函数使用了CGImage进行类型转换,而IOS中的CGImage的坐标系跟UIImage的坐标系不一致导致的,所以可以在执行转换成Mat的函数里先根据图像方向进行旋转校正,校正函数如下:

- (UIImage *)fixOrientation {

    

    // No-op if the orientation is already correct

    if (self.imageOrientation == UIImageOrientationUp) return self;

    

    // We need to calculate the proper transformation to make the image upright.

    // We do it in 2 steps: Rotate if Left/Right/Down, and then flip if Mirrored.

    CGAffineTransform transform = CGAffineTransformIdentity;

    

    switch (self.imageOrientation) {

        case UIImageOrientationDown:

        case UIImageOrientationDownMirrored:

            transform = CGAffineTransformTranslate(transform, self.size.width, self.size.height);

            transform = CGAffineTransformRotate(transform, M_PI);

            break;

            

        case UIImageOrientationLeft:

        case UIImageOrientationLeftMirrored:

            transform = CGAffineTransformTranslate(transform, self

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值