文档章节

iOS 中如何识别图片清晰度

哈哈8066
 哈哈8066
发布于 2016/11/30 01:08
字数 1045
阅读 1512
收藏 1

本文欢迎转载,转载请注明出处:

https://my.oschina.net/227/blog/796485

 

前言

在开发项目中,有的时候需要用户上传照片到后台服务器审核,如果照片不清晰的话,那就得用户重新上传。有没有办法在上传之前就判断照片是否清晰呢?为了解决这个问题,我们可以用到一个图像处理框架“openCV”。"openCV"非常强大,我们这里只是用了它的很小一点点。

openCV官网:http://opencv.org/

 

思路:

如果读者了解信号处理,就会知道最直接的方法就是计算图片的快速傅里叶变换,然后查看高低频的分布。如果图片有少量的高频成分,那么该图片就可以被认为是模糊的。然而,区分高频量多少的具体阈值却是十分困难的,不恰当的阈值将会导致极差的结果。

查阅了相关资料,了解到了目前比较好的方法是“拉普拉斯方差算法”。

简单来说就是只需要将图片中的某一通道(一般用灰度值)用的拉普拉斯掩模做卷积运算,得到的像素矩阵,在把矩阵中的数值求方差。如果图像越清晰,边缘越锐利,像素之间的差别越大,则方差越大。反之图像模糊,边缘之间像素差别小,那方差越小。

 

步骤一:

去openCV官网下载给iOS用的“opencv2.framework”包,并导入xcode工程中

地址: (输入浏览器回车后过几秒钟就会自动下载)

https://sourceforge.net/projects/opencvlibrary/files/opencv-ios/2.4.13/opencv2.framework.zip/download

             

 

步骤二:

在需要使用的地方添加头文件“#import <opencv2/opencv.hpp>”,并且把当前的“.m”的objective-c文件改成“.mm”的objc/c++文件,或者在PCH里添加头文件,注意在PCH里添加的时候要如下所示

#ifdef __cplusplus
#import <opencv2/opencv.hpp>
#endif

这样做的原因是openCV的库是c++文件,加入这段表明这个库只有在c++文件导入,作用和“#ifdef __OBJC__”的效果类似。上面说改成“.mm”也是这个原因。

 

步骤三:

把UIImage图像转换成cvMat类型,让openCV可以处理

+ (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;
}

+ (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
                                        );
    
    
    // Getting UIImage from CGImage
    UIImage *finalImage = [UIImage imageWithCGImage:imageRef];
    CGImageRelease(imageRef);
    CGDataProviderRelease(provider);
    CGColorSpaceRelease(colorSpace);
    
    return finalImage;
}

 

步骤四:

进行计算,代码如下

//方差参考值
const double delta = 100;

+ (BOOL) whetherTheImageBlurry:(UIImage*)image{
    
    unsigned char *data;
    int height,width,step;
    
    int Iij;
    
    double Iave = 0, Idelta = 0;
    
    cv::Mat mat = [OpenCVExtension cvMatFromUIImage:image];
    
    if(!mat.empty()){
        cv::Mat gray;
        cv::Mat outGray;
        // 将图像转换为灰度显示
        cv::cvtColor(mat,gray,CV_RGB2GRAY);
        // 用openCV的Laplacian函数做灰度图做拉普拉斯计算,得到outGray
        cv::Laplacian(gray, outGray, gray.depth());
        //将得到的outGray转化为图片信息类IplImage
        IplImage ipl_image(outGray);
        
        data   = (uchar*)ipl_image.imageData;  //图片像素信息
        height = ipl_image.height;             //图片像素高度
        width  = ipl_image.width;              //图片像素宽度
        step   = ipl_image.widthStep;          //排列的图像行大小,以字节为单位
        
        for(int i=0;i<height;i++){    //求方差
            for(int j=0;j<width;j++)
            {
                Iij	= (int) data
                [i*width+j];
                Idelta	= Idelta + (Iij-Iave)*(Iij-Iave);
            }
        }
        Idelta = Idelta/(width*height);
        
        std::cout<<"矩阵方差为:"<<Idelta<<std::endl;
    }
    
    return (Idelta > delta) ? YES : NO;
}

在实验中发现,当方差大于100的时候,图片是清晰的。

这样我们就得到了识别图像清晰度的方法。

 

代码地址

本篇文章代码的例子,可以登录github搜索TTImageBlurryEvaluation查看。

或者直接登录:https://github.com/coco227/TTImageBlurryEvaluation

 

参考文献:

《用 Opencv 和 Python 对汪星人做模糊检测》(http://python.jobbole.com/83702/

《Analysis of focus measure operators for shape-from-focus》[2013 Pertuz et al.]

 

© 著作权归作者所有

共有 人打赏支持
哈哈8066
粉丝 3
博文 43
码字总数 11632
作品 0
浦东
程序员
私信 提问
iOS简单音乐实现、React-Native完整项目、仿闲鱼京东列表分页、语音识别、网络加载过度动画等源码

iOS精选源码 iOS快速入手语音识别、听写、评测、播报 网络加载数据的过渡动画(仿简书网页) iOS 封装跑马灯和轮播效果 crash防护组件,适用常见常用的数组,字典等crash保护 iOS:高仿闲鱼、...

Code4app
2018/09/26
0
0
WebApp与Native App的区别

WebApp与Native App的区别 Native App: 1、开发成本非常大。一般使用的开发语言为JAVA、C++、Objective-C。 2、更新体验较差、同时也比较麻烦。每一次发布新的版本,都需要做版本打包,且需...

一真的鱼
2018/07/03
0
0
iOS--打包上线App Store报WARNING ITMS-90704和90717

今天更新上线,更新了系统,在上传时遇到2个问题: 1.:WARNING ITMS-90704: "Missing App Store Icon. iOS Apps must include a 1024x1024px App Store Icon in PNG format. Without provi......

指尖流年
2017/10/31
0
0
webpack中如何使用雪碧图

一、什么是雪碧图? CSS雪碧 即CSS Sprite,也有人叫它CSS精灵,是一种CSS图像合并技术,该方法是将小图标和背景图像合并到一张图片上,然后利用css的背景定位来显示需要显示的图片部分。 二...

程序员小哥哥
2018/11/10
0
0
人工智能要成精了?英伟达展示逆天修图技术

人工智能要成精了?英伟达展示逆天修图技术 2018-04-25 12:03编辑: 枣泥布丁分类:AI来源:青亭网 英伟达人工智能PS 招聘信息: C++工程师 Cocos2d-x游戏客户端开发 iOS开发工程师 京东招聘...

枣泥布丁
2018/04/25
0
0

没有更多内容

加载失败,请刷新页面

加载更多

小程序-星星评分

//UI界面 <block wx:for='{{item.rateArray}}' wx:key wx:for-item="i" > <image wx:if='{{ i==0}}' src='../../assets/xing4.png'></image> <image wx:if='{{ i==1}}' src='../../assets/xi......

lsy999
28分钟前
1
0
JavaScript与WebAssembly进行比较

本文由云+社区发表 作者:QQ音乐前端团队 在识别和描述核心元素的过程中,我们分享了构建SessionStack时使用的一些经验法则,这是一个轻量级但健壮且高性能的JavaScript应用程序,以帮助用户...

腾讯云加社区
30分钟前
4
0
如何设计一个 RPC 系统

RPC是一种方便的网络通信编程模型,由于和编程语言的高度结合,大大减少了处理网络数据的复杂度,让代码可读性也有可观的提高。但是RPC本身的构成却比较复杂,由于受到编程语言、网络模型、使...

编程SHA
31分钟前
2
0
API权限控制与安全管理

一、API权限控制范围 1、首先验证web端请求参数: (1)web请求参数:渠道、ServiceName、版本、Airline、时间戳(yyyyMMddhhmmssSSS)、reqXML、Language、签名 (2)请求不能为空,并且格式...

Jack088
31分钟前
2
0
最热门的13个Java微服务框架

曾经的服务器领域有许多不同的芯片架构和操作系统,经过长期发展,Java的“一次编译,到处运行”使得它在服务器领域找到一席之地,成为程序员们的最爱 本文,我们将和大家分享13个可靠的Jav...

java菜分享
32分钟前
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部