探索iOS之CoreImage框架

news2024/11/22 14:38:27

CoreImage提供图像处理、人脸识别、图像增强、图像滤镜、图像转场。它操作的数据来自Core Graphics、Core Video、Image IO,使用CPU或GPU进行渲染。CoreImage对底层实现进行封装,为上层提供简单易用的API。

一、CoreImage框架

CoreImage框架分为:渲染层、处理层、API层。其中,渲染层包括GPU渲染(OpenGL和Metal)、CPU渲染(Grand Central Dispatch);处理层有Built-in Filters内建滤镜;API层有Core Graphics、Core Video、Image IO。如下图所示:

二、图像处理

1、图像处理流程

图像处理主要包括三个类:CIContext、CIFilter、CIImage。处理流程示例如下:

import CoreImage

// 1、创建CIContext
let context = CIContext()
// 2、创建CIFilter
let filter = CIFilter(name: "CISepiaTone")!
filter.setValue(0.8, forKey: kCIInputIntensityKey)
// 3、创建CIImage
let image = CIImage(contentsOfURL: mURL)
// 4、image应用到filter滤镜
filter.setValue(image, forKey: kCIInputImageKey)
let result = filter.outputImage!
// 5、使用context创建CGImage(用于管理image以及对象复用)
let cgImage = context.createCGImage(result, from: result.extent)
// 6、显示滤镜结果
imageView.image = UIImage(CIImage: result)

2、图像数据类型

图像作为输入输出的Filter,包括数据类型如下:

图像文件的URL或图像数据的NSData;

CGImageRef、UIImage、NSBitmapImageRep对象;

Metal、OpenGl纹理;

CVImageBufferRef、CVPixelBufferRef;

跨进程共享数据的IOSurfaceRef;

内存的Bitmap数据或CIImageProvider;

3、创建Filter Chain

Filter Chain滤镜链的创建,示例代码如下:

func applyFilterChain(to image: CIImage) -> CIImage {
    // 创建CIFilter,并且设置color滤镜
    let colorFilter = CIFilter(name: "CIPhotoEffectProcess", withInputParameters:
        [kCIInputImageKey: image])!
    
    // 应用bloom滤镜
    let bloomImage = colorFilter.outputImage!.applyingFilter("CIBloom",
                                                             withInputParameters: [
                                                                kCIInputRadiusKey: 10.0,
                                                                kCIInputIntensityKey: 1.0
        ])
    
    // 图像裁剪
    let cropRect = CGRect(x: 350, y: 350, width: 150, height: 150)
    let croppedImage = bloomImage.cropping(to: cropRect)
    
    return croppedImage
}

4、应用滤镜到视频

以高斯模糊滤镜应用到视频为例,相关代码如下:

// 创建高斯模糊filter
let filter = CIFilter(name: "CIGaussianBlur")!
let composition = AVVideoComposition(asset: asset, applyingCIFiltersWithHandler: { request in

    let source = request.sourceImage.clampingToExtent()
    filter.setValue(source, forKey: kCIInputImageKey)
    
    // 根据时间戳设置模糊系数
    let seconds = CMTimeGetSeconds(request.compositionTime)
    filter.setValue(seconds * 10.0, forKey: kCIInputRadiusKey)
    
    // 裁剪
    let output = filter.outputImage!.cropping(to: request.sourceImage.extent)
    
    // 应用滤镜结果到视频
    request.finish(with: output, context: nil)
})

5、使用Metal实时滤镜

首先创建Metal view用于图像渲染:

class ViewController: UIViewController, MTKViewDelegate {
    
    // Metal设备、纹理、队列
    var device: MTLDevice!
    var commandQueue: MTLCommandQueue!
    var sourceTexture: MTLTexture!
    
    // 高斯模糊
    var context: CIContext!
    let filter = CIFilter(name: "CIGaussianBlur")!
    let colorSpace = CGColorSpaceCreateDeviceRGB()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // 创建设备、命令队列
        device = MTLCreateSystemDefaultDevice()
        commandQueue = device.newCommandQueue()
        
        let view = self.view as! MTKView
        view.delegate = self
        view.device = device
        view.framebufferOnly = false
        // 创建CIContext
        context = CIContext(mtlDevice: device)
    }
}

实时滤镜渲染流程,示例代码如下:

public func draw(in view: MTKView) {
    if let currentDrawable = view.currentDrawable {
        let commandBuffer = commandQueue.commandBuffer()
        // 1、使用纹理创建UIImage,并且进行滤镜
        let inputImage = CIImage(mtlTexture: sourceTexture)!
        filter.setValue(inputImage, forKey: kCIInputImageKey)
        filter.setValue(20.0, forKey: kCIInputRadiusKey)
        // 2、使用context进行渲染
        context.render(filter.outputImage!,
            to: currentDrawable.texture,
            commandBuffer: commandBuffer,
            bounds: inputImage.extent,
            colorSpace: colorSpace)
        // 3、使用buffer显示结果
        commandBuffer.present(currentDrawable)
        commandBuffer.commit()
    }
}

三、人脸识别

iOS提供CIDetector进行人脸识别,示例代码如下:

// 1、创建CIContext
CIContext *context = [CIContext context];
// 2、创建options,指定识别精度
NSDictionary *opts = @{ CIDetectorAccuracy : CIDetectorAccuracyHigh };
// 3、创建检测器,指定识别类型
CIDetector *detector = [CIDetector detectorOfType:CIDetectorTypeFace
                                          context:context
                                          options:opts];
// 4、指定图像方向
opts = @{ CIDetectorImageOrientation :
          [[mImage properties] valueForKey:kCGImagePropertyOrientation] };
// 5、获取识别结果
NSArray *features = [detector featuresInImage:mImage options:opts];

人脸识别结果包含:左眼、右眼、嘴巴的位置,结果判断如下:

for (CIFaceFeature *f in features) {
    NSLog(@"%@", NSStringFromRect(f.bounds));
 
    if (f.hasLeftEyePosition) {
        NSLog(@"Left eye x=%g y=%g", f.leftEyePosition.x, f.leftEyePosition.y);
    }
    if (f.hasRightEyePosition) {
        NSLog(@"Right eye x=%g y=%g", f.rightEyePosition.x, f.rightEyePosition.y);
    }
    if (f.hasMouthPosition) {
        NSLog(@"Mouth x=%g y=%g", f.mouthPosition.x, f.mouthPosition.y);
    }
}

我们来看下人脸识别效果:

四、图像增强

iOS提供的图像增强包括:红眼矫正、脸部平衡、色彩增强、阴影突出,如下表所示:

Filter描述
CIRedEyeCorrection修复摄像头闪光引起的红眼
CIFaceBalance根据肤色调整脸部颜色
CIVibrance增强饱和度
CIToneCurve调整对比度
CIHighlightShadowAdjust调整阴影细节

图像增强的使用示例如下:

NSDictionary *options = @{ CIDetectorImageOrientation :
                 [[image properties] valueForKey:kCGImagePropertyOrientation] };
NSArray *adjustments = [image autoAdjustmentFiltersWithOptions:options];
for (CIFilter *filter in adjustments) {
     [filter setValue:image forKey:kCIInputImageKey];
     myImage = filter.outputImage;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/575668.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

计算机电脑中了勒索病毒,如何提高windows系统预防faust勒索病毒的能力

当今社会互联网技术迅猛发展,但随之而来的网络安全问题开始引起人们的重视,其中,勒索软件是当前网络安全领域中最具破坏性和危害性的恶意软件之一,而Faust勒索软件就是其中一种。 Faust勒索病毒是一种很可怕的恶意软件,能够破坏并…

计算机网络 - 网络层的数据平面

Overview 首先Network Layer负责的是host to host的传输, 然后可以分为两个平面, 控制平面以及数据平面. 数据平面: 负责forward datagrams from input to output links 决定路由器从input到output 转发功能: 基于目标地址 转发表 SDN方式基于多个字段流表 控制平面: 调…

第10届蓝桥杯Scratch省赛真题集锦

编程题 第 1 题 问答题 击鼓游戏 题目说明 准备工作: 将复台背景设置为“spotight-stage”,添加一个“Belerina"角色、两个“Drum1"角色和两个“Drum2”角色,并按照图 7-1 的位置摆放。角色“Beleina"的造型和颜色的设置须如图 7-1所示&a…

美女放电还是整形-从《人月神话》误译谈状态机图

DDD领域驱动设计批评文集 欢迎加入“软件方法建模师”群 《软件方法》各章合集 在重审《人月神话》中译本的过程中,发现一处较严重的误译。 原文是: the first milepost is not reached until two months have elapsed. 原译为: 两个月…

Java中常量基础知识

1 问题 什么是字面常量? 2 方法 拿第一行输出语句来说,这行代码输出了 “hello” 这个字符串,无论何时何地运行程序,输出的这个字符串都不会变,这就是字面常量。 定义:常量即程序运行期间,固定不…

chatgpt网站优选集合

目录 chatGpt 国内镜像网站集合 chatgpt接入微信 chatgpt接入谷歌浏览器 chatgptAI绘画 最后 chatGpt 这个说实话,不用我介绍大家也都懂。不如玩一个有意思的,这里我让chatGpt自己介绍一下他自己: 嗨,大家好,我是…

C++ [STL之vector模拟实现]

本文已收录至《C语言和高级数据结构》专栏! 作者:ARMCSKGT STL之vector模拟实现 前言正文空间结构默认成员函数构造函数拷贝构造函数赋值重载析构函数关于数据拷贝问题 迭代器容量操作查询容量容量操作 数据访问下标访问头尾数据访问 数据增删尾插尾删重…

学懂缓存雪崩,缓存击穿,缓存穿透仅需一篇,基于Redis讲解

在了解缓存雪崩、击穿、穿透这三个问题前,我们需要知道为什么我们需要缓存。在了解这三个问题后,我们也必须知道使用Redis时,如何解决这些问题。 所以我将按照"为什么我们需要缓存"、"什么是缓存雪崩、击穿、穿透"、&qu…

Linux学习笔记 --- Linux基础命令Part1

一. Linux的目录结构 目标:1. 掌握Linux系统的目录结构 2. 掌握Linux系统的路径表达形式 1.1 Linux系统的目录结构 我们知道,在操作系统中,文件系统的目录结构一般都是树形结构。Linux的目录结构是一个树型结构Windows 系统可以拥有多…

如何使用wireShark抓取还原文件

简介 WireShark的追踪流功能可以帮我们抓取从网络上下载的各种文件,接下来就演示下如何抓取并且进行还原。 使用Nginx搭建文件存储服务器 只要是通过http网站下载的包,都可以通过追踪流工具进行抓取。这里为了演示,临时搭建一个Nginx文件存…

Yolov8涨点技巧:MobileViTAttention助力小目标检测,涨点显著,MobileViT移动端轻量通用视觉transformer

在​crack缺陷检测项目原始0.739提升至 0.772 ,涨点明显,博主多个数据集亲测有效,实现暴力涨点; 现有博客都是将MobileViT作为backbone引入Yolov5,因此存在的问题点是训练显存要求巨大,本文引入自注意力的Vision Transformer(ViTs):MobileViTAttention 1. MobileViT介绍…

English Learning - L3 作业打卡 Lesson3 Day18 2023.5.22 周一

English Learning - L3 作业打卡 Lesson3 Day18 2023.5.22 周一 引言🍉句1: People said my mother was “a good egg”.成分划分弱读连读语调 🍉句2: She would always help anyone in need.成分划分连读语调 🍉句3: We never had to “walk…

1、MQTT协议入门以及mosquitto示例

1.什么是MQTT MQTT(Message Queuing Telemetry Transport,消息队列遥测传输协议),是一种基于发布/订阅(publish/subscribe)模式的"轻量级"通讯协议,该协议构建于TCP/IP协议上&#xf…

一款好看的markdown编辑器:md-editor-v3

文章目录 md-eidtor-v3地址其它markdown编辑器🎄 md-editor-v3⭐️ 功能一览📦 安装💡 用法✍🏻 编辑器模式📖 仅预览模式 🗺 预览图🎁 Apis🔖 MdPreivew Props🔩 MdEdit…

c++基础概念,const与指针、引用的关系,auto,decltype关键字能干啥总得了解吧。总得按照需求自定义创建实体类,自己编写头文件吧

const限定符 有时我们希望定义这样一种变量,它的值不能被改变。例如,用一个变量来表示缓冲区的大小。使用变量的好处是当我们觉得缓冲区大小不再合适时,很容易对其进行调整。另一方面,也应随时警惕防止程序一不小心改变了这个值。…

邂逅Webpack和打包过程

1 认识webpack工具 2 webpack基本打包 3 webpack配置文件 4 编写和打包CSS文件 5 编写和打包LESS文件 6 postcss工具处理CSS 从脚手架打包成普通的htmlcssjs文件 内置模块path: 拼接路径 const path require("path")const filepath "C://abc/…

Systrace系列9 —— MainThread 和 RenderThread 解读

本文是介绍 Android App 中的 MainThread 和 RenderThread,也就是大家熟悉的主线程和渲染线程。文章会从 Systrace 的角度来看 MainThread 和 RenderThread 的工作流程,以及涉及到的相关知识:卡顿、软件渲染、掉帧计算等。 这里以滑动列表为例 ,我们截取主线程和渲染线程一…

InnoDB 在可重复读 RR 隔离级别下,能解决幻读问题吗?

InnoDB 在可重复读 RR 隔离级别下,能解决幻读问题吗? MySQL 在「可重复读」隔离级别下,可以很大程度上避免幻读现象的发生(注意是很大程度避免,并不是彻底避免),所以 MySQL 并不会使用「串行化」…

Pycharm中配置不了conda解释器

我安装的是pytorch的CPU版本,在Pycharm中配置conda环境时,每次添加完都不显示,搜遍了很多方法都没用。最后成功解决,这里将一些方法进行总结,方便大家解决问题。 我的情况和解决 问题情况以及显示 1.在Pycharm的日志…

GATK最佳实践之数据预处理SnakeMake流程

<~生~信~交~流~与~合~作~请~关~注~公~众~号生信探索> 写的数据预处理snakemake流程其实包括在每个单独的分析中比如种系遗传变异和肿瘤变异流程中&#xff0c;这里单独拿出来做演示用&#xff0c;因为数据预处理是通用的&#xff0c;在call变异之前需要处理好数据。 数据…