14.2.6 实现模糊效果

728 篇文章 1 订阅
26 篇文章 0 订阅

14.2.6 实现模糊效果

 

    我们最终的效果不只是一个颜色滤镜。模糊图像的过程依赖于计算新的像素值,基于多个原始像素。我们仍然可以执行逐个像素转换图像。不过,转型需要访问整个图像,以及我们想要转换的像素坐标。

    我们把 RunEffect 和 RunEffectParallel 的实现留下作为练习,但它是相当简单的;这是只需改变循环的具体内容,给转换函数更多的信息。从序列到并行形式的转换,与这个至于效果颜色滤镜是相同的。如果你被卡住,去本书的网站上看看完整的源代码。

    模糊转型本身是很有趣,如清单 14.19 中所示。它并不特别困难,它提供了一个很好的声明性编程的示范。

 

Listing 14.19 Implementing the Blur effect (F#)

 

let blur(arr:SimpleColor[,], x, y) =
  let height, width = arr.GetLength(0) - 1, arr.GetLength(1) – 1
  let checkW x = max 0 (min width x)
  let checkH y = max 0 (min height y)

  [ for dy in -2 .. 2 do
    for dx in -2 .. 2 do
      yield arr.[checkH(y + dy), checkW(x + dx)] ]
  |> List.average

 

    blur 函数取三个参数,指定的图像,我们想要计算像素的 X,Y 坐标。如果以命令式风格实现 blur,就需要创建一个变量,将其初始化为 0,把附近所有的像素的颜色加起来,再把结果除以像素数,以获得平的均颜色。

    在 F# 中,我们可以使用更加声明式的方法,来写平均颜色的计算。我们首先声明一些工具函数,用来检查该索引在数组的范围中。接下来,要使用序列表达式,来创建一个列表,包含所有邻近像素的颜色, 用 List.average 计算平均值。

 

探索 List.average

 

    要计算值的平均值,List.average 函数需要知道三件事:

    ■ 对于特定的类型,"零"值是什么。

    ■ 如何将值相加。

    ■ 如何将特定类型的值除以整数。

    前两项对于计算这个列表的和是足够的。然后,需要把结果除以列表中的元素的个数,就是这里的第三项。在我们的效果中,我们将处理 SimpleColor 类型的值,这个类型实现了加法运算符。我们还添加了特殊成员,Zero 和  DivideByInt。average 函数使用这些成员,它是一个泛型函数,但它需要这个类型实现适当的成员。像这样的约束并不能用 .NET 的泛型表示。可用于泛型类型的约束,可能要求无参数构造函数或接口,但不是特定的成员。

    为此,F# 实现了自己的编译时成员约束的机制。在这种情况下,该约束由 F# 编译器在编译时解决(相对于 .NET 泛型的约束,也是由 .NET 的运行时检查)。下面的示例演示了如何使用此功能,来定义一个函数,计算任何值的一半,这个值支持除以整数:

 

> let inline half (num: ^a) : ^a =
      LanguagePrimitives.DivideByInt< (^a) > num 2
;;
val inline half : ^a -> ^a
when ^a : (static member DivideByInt : ^a * int -> ^a)

> half(42.0);;
val it : float = 21.0

> half(SimpleColor(255, 128, 0));;
val it : SimpleColor = SimpleColor {B = 0; G = 64; R = 127;}

> half("hello");;
error FS0001: The type 'string' does not
support any operators named 'DivideByInt'

 

    这个函数叫 half,我们使用显式类型注释,来指定参数 num 的类型,结果的类型是泛型参数 ^a。注意,我们将使用的类型参数,以(^) 开头,而不是使用惯常的撇号(')。在函数体中,我们调用来自 LanguagePrimitives 模块的 DivideByInt 函数。这是一个有成员约束的基元函数,它把数值类型除以整数,或者,使用 DivideByInt 成员,如果可用的话。

    正如你所看到的,成员约束表现为推导出的类型签名。现在,我们有了这个函数,可以将它用于各种数值类型,而且,也可以处理我们的 SimpleColor 类型。如果我们尝试调用它,用不支持 DivideByInt 操作的参数值,就会发生编译时错误。

 

    在这个示例中,我们已经研究了一个大型应用程序的关键部分。可以从本书的网站上获得完整的源代码,看到我们这一章中实现的部分如何相连。虽然这个应用程序的最重要的部分使用了可变数组,但是,设计的整个应用程序还是函数式的,包括第 11 章中所述的以函数式风格使用数组。这种方法让我们轻松和安全地并行化核心算法。

    这是一个以行为为中心的应用程序的示例。我们主要关心的是如何并行化单独的行为。并行化以行为为中心的应用程序的另一种方式,是以并行的方式运行不同的行为。我们可能想要批处理一系列的图像,并每个图像应用多个效果。在下一节中,我们会把注意力转向以数据为中心的应用程序。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
前言 10 场景说明 11 基础知识简介 14 Linux 14 Linux产生与发展 14 Linux特点和优势 15 Shell 16 Shell脚本语言与编译型语言的差异 17 Shell分类 18 Shell使用 19 项目一 初识Linux Shell 20 [学习目标] 20 任务1.1 构建开发环境 22 任务1.2 vi/vim编辑器 33 1.2.1 vim使用实例 34 1.2.2 vim按键说明 36 任务1.3 Shell常用命令 41 1.3.1 基础命令 41 1.3.2 文件、目录操作命令 42 1.3.3 系统管理命令 52 1.3.4 关机/重启/退出 53 1.3.5 安装操作命令 53 1.3.6 用户操作命令 54 1.3.7 网络下载命令 55 1.3.8 服务操作命令 57 任务1.4 Shell脚本 58 1.4.1 第一个shell脚本:Hello World 58 1.4.2 脚本介绍 59 1.4.3 shell程序结构 59 1.4.4 shell脚本运行 60 任务1.5 Shell案例:打印有色彩的文本 61 任务1.6 Shell案例:图案打印 62 练习(每题10分,共计100分) 66 项目二 Shell变量 67 [学习目标] 67 任务2.1 Linux环境变量 68 2.1.1 查看环境变量 69 任务2.2 Shell变量 70 2.2.1 定义变量 70 2.2.2 使用变量 70 2.2.3 只读变量 71 2.2.4 删除变量 72 任务2.3 特殊符号 72 任务2.4 Shell案例:显示系统信息: 78 练习(每题12.5分,共计100分) 80 项目三 Shell传递参数 81 [学习目标] 81 任务3.1 Shell传递参数 82 任务3.2 Shell案例:参数比较 85 任务3.3Shell案例:通过参数描述变量 86 练习(前两题每题30分,第三题40分,共计100分) 87 项目四 Shell数组 89 [学习目标] 89 任务4.1 定义数组 90 任务4.2 使用数组 90 任务4.3 Shell案例:数组的使用 92 练习(100分) 95 项目五 Shell运算符 96 [学习目标] 96 任务5.1 Shell基本运算符 97 5.1.1 运算符 97 5.1.2 算术运算符 97 5.1.3 关系运算符 99 5.1.4 布尔运算符 101 5.1.5 逻辑运算符 103 5.1.6 字符串运算符 104 5.1.7 文件测试运算符 106 任务5.2 Shell案例:计算器 109 练习(每题25分,共计100分) 111 项目六 Shell命令输出 112 [学习目标] 112 任务6.1 Shell echo命令 113 任务6.2 Shell printf命令 116 任务6.3 Shell test命令 119 任务6.4 Shell案例:查看系统资源使用情况 122 练习(每题20分,共计100分) 125 项目七 Shell流程控制 126 [学习目标] 126 任务7.1 Shell流程控制 127 7.1.1 if 判断语句 127 7.1.2 for 循环语句 130 7.1.3 while 循环语句 131 7.1.4 until 循环语句 134 7.1.5 case多选语句 135 7.1.6 跳出循环体 137 任务7.2 Shell案例:重复执行命令和简单计算器 139 任务7.3 Shell案例:使用三种循环结构打印九九乘法表 141 练习(前两题每题30分,第三题40分,共计100分) 144 项目八 Shell函数 146 [学习目标] 146 任务8.1 Shell函数 147 8.1.1 Shell中函数的定义 147 8.1.2 函数参数 150 任务8.2 Shell案例 151 8.2.1 指定多个文件的行数 151 8.2.2 当前目录的所有文件 153 练习(每题50分,共计100分) 156 项目九 Shell输入/输出重定向 158 [学习目标] 158 任务9.1 linux文件描述符 159 任务9.2 Shell输入/输出重定向 160 9.2.1 输出重定向 160 9.2.2 输入重定向 163 9.2.3 重定向深入讲解 164 任务9.2 Shell案例:通过重定向测试批量添加ip 166 练习(每题25分,共计100分) 169 项目十 Shell文件包含 171 [学习目标] 171 任务10.1 Shell文件包含 172 任务10.2 Shell案例:查找最大文件 172 练习(每题50分,共计100分) 174 项目十一 Shell文本处理命令 175 [学习目标] 175 任务11.1 学习和使用grep 176 任务11.2 学习和使用sed 179 任务11.3 学习和使用cut 183 任务11.4 学习和使用awk 185 练习(第一题10分,第2-7每题15分,共计100分) 188 项目十二 Shell的调试 189 [学习目标] 189 任务12.1 使用trap命令 190 任务12.2 使用tee命令 192 任务12.3 使用“调试钩子” 193 任务12.4 使用Shell的执行选项 194 练习(每题50分,共计100分) 196 项目十三 Shell综合案例一(lnmp+wordpress) 197 [学习目标] 197 任务13.1 手动安装Linux Nginx Mysql PHP和WordPress 198 13.1.1 准备工作 198 13.1.2 安装Mysql5.6.29 199 13.1.3 安装PHP5.5.12 202 13.1.4 安装Nginx1.10 205 13.1.5 安装WordPress 206 13.1.6 启动网页 207 任务13.2 脚本安装Linux Nginx Mysql PHP 和WordPress 207 13.2.1 初始化安装脚本编写 207 13.2.2 Mysql安装脚本的编写 209 13.2.3 PHP安装脚本的编写 211 13.2.4 Nginx安装脚本的编写 213 13.2.5 WordPress安装脚本的编写 214 13.2.6 验证wordpress 216 练习(每题50分,共计100分) 218 项目十四 shell综合案例二(安装Openstack) 219 [学习目标] 219 任务14.1 手动安装Openstack 220 什么是Openstack 220 14.1.1基本环境准备 222 14.1.2 安装mysql数据库服务 225 14.1.3 安装keystone认证服务 226 14.1.4 安装glance镜像服务 230 14.1.5 安装nova计算服务 233 14.1.6 安装neutron网络服务 238 14.1.7 安装dashboard服务 248 任务14.2 脚本安装openstack 250 14.2.1 基本环境脚本的编写 255 14.2.2 mysql脚本的编写 256 14.2.3 keystone脚本的编写 258 14.2.4 glance脚本的编写 263 14.2.5 nova脚本的编写 266 14.2.6 neutron脚本的编写 270 14.2.7 dashboard脚本的编写 279 14.2.8 验证登录,使用openstack 280 附录Shell编码规范说明 295 1. 什么时候使用shell 295 2.Shell文件和解释器调用 295 3.环境 296 4.注释 296 5.格式 298 6.特性及错误 304 7.命名转换 308 8.调用命令 311

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值