ImageMagick库具有大量功能。本文简要介绍了最重要的入门概念。
在的Windows或OS-X上,通过CRAN最容易安装软件包。
可下载资源
install.packages("magick")
二进制CRAN包开箱即用。
library(magick)
## Linking to ImageMagick 6.9.9.39
## Enabled features: cairo, fontconfig, freetype, lcms, pango, rsvg, webp
## Disabled features: fftw, ghostscript, x11
str(magick::magick_config())
## List of 21
## $ version :Class 'numeric_version' hidden list of 1
## ..$ : int [1:4] 6 9 9 39
## $ modules : logi FALSE
## $ cairo : logi TRUE
## $ fontconfig : logi TRUE
## $ freetype : logi TRUE
## $ fftw : logi FALSE
## $ ghostscript : logi FALSE
## $ jpeg : logi TRUE
## $ lcms : logi TRUE
## $ libopenjp2 : logi TRUE
## $ lzma : logi TRUE
## $ pangocairo : logi TRUE
## $ pango : logi TRUE
## $ png : logi TRUE
## $ rsvg : logi TRUE
## $ tiff : logi TRUE
## $ webp : logi TRUE
## $ wmf : logi FALSE
## $ x11 : logi FALSE
## $ xml : logi TRUE
## $ zero-configuration: logi TRUE
图像的基本处理
在计算机视觉这一领域诞生的初期,一种普遍的研究范式,是将图像看做二维的数字信号,然后借用数字信号处理中的方法,这就是数字图像处理(digital image processing)。本节数字图像处理方面的算法进行介绍。
图像直方图与像素距离
传感器获取的图像是平面上的连续函数,将连续函数采样(sampled)为M行N列的矩阵,将每个连续样本量化(quantization)为一个整数值,即图像函数的连续范围被分成了K个区间,采样后得到的矩阵构成了离散图像,栅格中无限小的采样点对应于数字图像中的像元,即像素(pixel) 。
灰度图像中,最低值对应黑,最高值对应白;黑白之间的亮度值是灰度阶(gray-level) ,彩色图像则通过矢量函数(三阶张量)描述,可以将一幅彩色图像看做由R,G,B三种基础色进行堆叠形成,而这三种基础色又对应了三个大小相同的矩阵,矩阵的数值表征这一通道颜色的深浅。有时除了考虑RGB三种颜色外,还考虑像素的透明度a,称为RGBA描述。
色彩在人类视觉感知中极其重要,色彩与物体反射不同波长的电磁波的能力相关,一般将这三种颜色(三种不同波长的光)作为三原色:红(700nm)、绿(546.1nm)、蓝(438.5nm),灰度图像的矩阵元素数值与彩色图像间满足Y=0.299R+0.587G+0.114B;RGB数字图像中,以(0,0,0)表示黑色,(255,255,255)表示白色;灰度图像中,以0表示黑色,以255表示白色;二值图像中,以0表示黑色,1表示白色。
图像每个位置[i,j]必定对应一个[0,255]的数值,统计每个数值所对应的像素点个数可以得到图像的亮度直方图,直方图(亮度直方图,brightness histogram)给出了图像中各个亮度值出现的概率,一幅k阶图像的直方图由具有k个元素的一维数组表示。
Def.(灰度级变换) 灰度级变换是这样一种(线性)变换,它将原来在范围[p0,pk]内的亮度p变换为一个新范围[q0,qk]内的亮度。
直方图均衡化(histogram equlization)的目标是创建一幅在整个亮度范围内具有相同亮度分布的图像,输入直方图H[p],输入亮度范围为[p0,pk],直方图均衡化的目标是找到一个单调的像素亮度变换q=T(p),使输出直方图G[q]在整个输出亮度范围[q0,qk]内是均匀的;增强了靠近直方图极大值附近的亮度的对比度,减小了极小值附近的对比度。在对图像做进一步处理之前,直方图均衡化通常是对图像灰度值进行归一化的一个非常好的方法,并且可以增强图像的对比度,原先图像灰色区域的细节变得清晰。
直方图均衡化的步骤如下:
1. 对于k(256)个亮度级、大小为M × N的图像,创建长为k的数组H,初始化为0
2. 形成图像直方图H
3. 形成累计直方图Hc,Hc[p]=Hc[p-1]+H[p], Hc[0]=H[0]
4. 设置
5. 重新扫描图像,根据查找表获得变换结果
(更加详细的解释参考:说说直方图均衡化)
坐标为(m,n)和(h,k)两点之间的距离有如下定义
– [欧氏距离(Euclid distance)]
– [城区距离(曼哈顿距离,Manhattan distance)] d_4=|m-h|+|n-k|
– [棋盘距离(chess distance)] 因相当于国际象棋中王走一步能到达的位置而得名: d_8=max (|m-h|,|n-k|)
Def.[像素邻接性(adjacency)]
4-邻接:任意两像素之间的距离为D4=1
8-邻接:任意两像素之间的距离为D8=1
Def.[区域(region)] 由一些彼此邻接的像素组成的集合
Def.[连通性(continuous)] 一幅图像的两个像素之间存在一条路径;连通关系具有自反性、对称性和传递性;区域中没有孔,称为简单连通,有孔的区域称为复连通
距离变换(distance transform)给出图像中的每个像素与某个图像子集的距离,步骤如下:
1. 创建大小为M 乘 N的矩阵F,子集S初始化为0,其他位置初始化为INF
2. 按行遍历图像,从上到下,从左到右,对上方和左侧邻接像素(AL集合)计算
3. 按行遍历图像,从下到上,从右到左,对下方和右侧邻接像素(BR集合)计算
4. 返回数组F的结果
从源构建
sudo apt-get install libmagick++-dev
sudo yum install ImageMagick-c++-devel
要在OS-X上从源代码安装,您需要imagemagick@6
自制软件。
brew reinstall imagemagick@6 --with-fontconfig --with-librsvg
brew link --force imagemagick@6
自制软件中的默认imagemagick配置会禁用一系列功能。
图像IO
读和写
可以使用带有图像数据的文件路径,URL或原始向量直接读取图像image_read
。该image_info
函数显示了一些关于图像的元型态数据,类似于ImageMagick的 identify
命令行实用程序。
print(tiger)
## format width height colorspace matte filesize density
## 1 PNG 400 400 sRGB TRUE 0 72x72
使用我们image_write
以任何格式将图像导出到磁盘上的文件或内存中。
image_write(tiger, path = "tiger.png", format = "png")
转换格式
Magick以原始格式将图像保存在内存中。要指定为转换格式其他的format
参数image_write
。在应用转换之前,您还可以在内部将图像转换为其他格式。如果您的原始格式有损,这可能很有用。
tiger_png <- image_convert(tiger, "png")
image_info(tiger_png)
## format width height colorspace matte filesize density
## 1 PNG 400 400 sRGB TRUE 0 72x72
在Linux的上,您使用image_display
在X11窗口中预览图像。
# X11
image_display(tiger)
# 依赖系统
image_browse(tiger)
另一种方法是将图像转换为光栅对象并将其绘制在R的图形显示上。
转换
下面举几个例子来了解。
剪切和编辑
转换一些函数采用一个geometry
参数,该参数需要表单的特殊语法,AxB+C+D
。其中每个元素都是可选的一些例子:
image_crop(image, "100x150+50")
:裁剪width:100px
并从左侧height:150px
开始+50px
image_scale(image, "200")
:按比例调整宽度:200px
image_scale(image, "x200")
:按比例调整高度:200px
image_fill(image, "blue", "+100+200")
:从蓝点开始填充x:100, y:200
image_border(frink, "red", "20x10")
:添加左侧+右侧20像素和顶部+底部10px的的边框
print(frink)
## format width height colorspace matte filesize density
## 1 PNG 220 445 sRGB TRUE 73494 72x72
image_border(image_background(frink, "hotpink"), "#000080", "20x10")
image_trim(frink)
image_crop(frink, "100x150+50")
image_scale(frink, "300") # width: 300px
image_scale(frink, "x300") # height: 300px
image_fill
我们可以填补像素point
。fuzz
参数允许填充具有相似颜色的像素。它的值必须在0到256 ^ 2之间。
过滤器和效果
image_noise(frink)
内核卷积
image_convolve()
函数在图像上应用内核卷积意味着使用内核矩阵中定义的加权邻域来重新计算每个像素值例如:
kern <- matrix(0, ncol = 3, nrow = 3)
kern[1, 2] <- 0.25
kern[2, c(1, 3)] <- 0.25
kern[3, 2] <- 0.25
kern
## [,1] [,2] [,3]
## [1,] 0.00 0.25 0.00
## [2,] 0.25 0.00 0.25
## [3,] 0.00 0.25 0.00
此内核将每个像素更改为其水平和垂直相邻像素的平均值,这会在下面的右侧图像中产生轻微的模糊效果:
img <- image_resize(logo, "300x300")
img_blurred <- image_convolve(img, kern)
image_append(c(img, img_blurred))
使用标准内核
文本注释
最后,在图像上输出一些文本会很有用:
image_annotate(frink, "I like R!", size = 70, gravity = "southwest", color = "green")
image_annotate(frink, "The quick brown fox", font = 'Times', size = 30)
支持的大多数平台上的字体包括"sans"
,"mono"
,"serif"
,"Times"
,"Helvetica"
,"Trebuchet"
,"Georgia"
,"Palatino"
或"Comic Sans"
。
结合管道
图像每个函数变换不会影响原始图像。
## format width height colorspace matte filesize density
## 1 PNG 220 445 sRGB TRUE 73494 72x72
## format width height colorspace matte filesize density
## 1 PNG 100 202 sRGB TRUE 0 72x72
组合转换:
## format width height colorspace matte filesize density
## 1 PNG 465 240 sRGB TRUE 0 72x72
使用magrittr
管道语法使其更具可读性
图像矢量
以上示例涉及单个图像。然而,magick中的所有函数都已经过矢量化,以支持使用图层,合成或动画。
image_scale("200x") %>%
image_quantize(128)
length(earth)
## [1] 44
## format width height colorspace matte filesize density
## 1 GIF 200 200 RGB FALSE 0 72x72
## 2 GIF 200 200 RGB FALSE 0 72x72
## 3 GIF 200 200 RGB FALSE 0 72x72
## 4 GIF 200 200 RGB FALSE 0 72x72
## 5 GIF 200 200 RGB FALSE 0 72x72
## 6 GIF 200 200 RGB FALSE 0 72x72
图层
我们可以像在Photoshop中中一样将图层堆叠在一起:
## format width height colorspace matte filesize density
## 1 JPEG 300 225 sRGB FALSE 0 72x72
## 2 PNG 300 232 sRGB TRUE 0 72x72
## 3 PNG 148 300 sRGB TRUE 0 72x72
结合
附加简单地将框架彼此相邻:
用于stack = TRUE
将它们放在彼此的顶部:
网页
在阅读PDF文档时,每个页面都成为向量的元素。
## format width height colorspace matte filesize density
## 1 PNG 612 792 sRGB TRUE 0 72x72
## 2 PNG 612 792 sRGB TRUE 0 72x72
## 3 PNG 612 792 sRGB TRUE 0 72x72
## 4 PNG 612 792 sRGB TRUE 0 72x72
## 5 PNG 612 792 sRGB TRUE 0 72x72
## 6 PNG 612 792 sRGB TRUE 0 72x72
## 7 PNG 612 792 sRGB TRUE 0 72x72
## 8 PNG 612 792 sRGB TRUE 0 72x72
## 9 PNG 612 792 sRGB TRUE 0 72x72
## 10 PNG 612 792 sRGB TRUE 0 72x72
## 11 PNG 612 792 sRGB TRUE 0 72x72
## 12 PNG 612 792 sRGB TRUE 0 72x72
## 13 PNG 612 792 sRGB TRUE 0 72x72
## 14 PNG 612 792 sRGB TRUE 0 72x72
## 15 PNG 612 792 sRGB TRUE 0 72x72
## 16 PNG 612 792 sRGB TRUE 0 72x72
## 17 PNG 612 792 sRGB TRUE 0 72x72
## 18 PNG 612 792 sRGB TRUE 0 72x72
## 19 PNG 612 792 sRGB TRUE 0 72x72
## 20 PNG 612 792 sRGB TRUE 0 72x72
## 21 PNG 612 792 sRGB TRUE 0 72x72
## 22 PNG 612 792 sRGB TRUE 0 72x72
## 23 PNG 612 792 sRGB TRUE 0 72x72
## 24 PNG 612 792 sRGB TRUE 0 72x72
## 25 PNG 612 792 sRGB TRUE 0 72x72
## 26 PNG 612 792 sRGB TRUE 0 72x72
## 27 PNG 612 792 sRGB TRUE 0 72x72
## 28 PNG 612 792 sRGB TRUE 0 72x72
## 29 PNG 612 792 sRGB TRUE 0 72x72
动画
我们也可以在动画中制作帧,而不是将矢量元素视为图层。
创建³³变形一系列n
图像,逐渐将一个图像变换为另一个图像。
如果您读入现有的GIF或视频文件,则每个帧都会成为一个图层:
## format width height colorspace matte filesize density
## 1 GIF 150 148 sRGB TRUE 0 72x72
## 2 GIF 150 148 sRGB TRUE 0 72x72
## 3 GIF 150 148 sRGB TRUE 0 72x72
## 4 GIF 150 148 sRGB TRUE 0 72x72
## 5 GIF 150 148 sRGB TRUE 0 72x72
## 6 GIF 150 148 sRGB TRUE 0 72x72
## 7 GIF 150 148 sRGB TRUE 0 72x72
## 8 GIF 150 148 sRGB TRUE 0 72x72
操纵各个帧并将它们放回动画中:
## format width height colorspace matte filesize density
## 1 gif 200 155 sRGB TRUE 0 72x72
## 2 gif 200 155 sRGB TRUE 0 72x72
## 3 gif 200 155 sRGB TRUE 0 72x72
## 4 gif 200 155 sRGB TRUE 0 72x72
## 5 gif 200 155 sRGB TRUE 0 72x72
## 6 gif 200 155 sRGB TRUE 0 72x72
## 7 gif 200 155 sRGB TRUE 0 72x72
## 8 gif 200 155 sRGB TRUE 0 72x72
动画可以保存为MPEG文件的GIF:
绘图和图形
该软件包的它产生一个magick图像对象。
图形设备
该image_graph()
功能打开一个类似于png()
或新的图形设备x11()
。它返回将要写入绘图的图像对象。
我们可以使用常规图像操作轻松地对图形进行后处理。
## format width height colorspace matte filesize density
## 1 PNG 400 400 sRGB TRUE 0 72x72
绘图设备
使用图形设备的另一种方式是使用像素坐标在现有图像上绘制。
## format width height colorspace matte filesize density
## 1 PNG 220 445 sRGB TRUE 0 72x72
默认情况下,image_draw()
将所有边距设置为0,并使用图形坐标匹配图像大小(以像素为单位)(宽度X高度),其中(0,0)是左上角。
动画图形
图形设备支持多个帧,可以轻松创建动画图形。下面的代码显示了如何使用magick图形设备从gganimate包中实现该示例。
## format width height colorspace matte filesize density
## 1 gif 600 340 sRGB TRUE 0 72x72
## 2 gif 600 340 sRGB TRUE 0 72x72
## 3 gif 600 340 sRGB TRUE 0 72x72
## 4 gif 600 340 sRGB TRUE 0 72x72
## 5 gif 600 340 sRGB TRUE 0 72x72
## 6 gif 600 340 sRGB TRUE 0 72x72
## 7 gif 600 340 sRGB TRUE 0 72x72
## 8 gif 600 340 sRGB TRUE 0 72x72
## 9 gif 600 340 sRGB TRUE 0 72x72
## 10 gif 600 340 sRGB TRUE 0 72x72
## 11 gif 600 340 sRGB TRUE 0 72x72
## 12 gif 600 340 sRGB TRUE 0 72x72
要将其写入文件,您只需执行以下操作:
OCR文本提取
该软件包的最新成员是使用OCR从图像中提取文本:
## format width height colorspace matte filesize density
## 1 PNG 640 480 sRGB TRUE 23359 72x72
可下载资源
关于作者
Kaizong Ye是拓端研究室(TRL)的研究员。在此对他对本文所作的贡献表示诚挚感谢,他在上海财经大学完成了统计学专业的硕士学位,专注人工智能领域。擅长Python.Matlab仿真、视觉处理、神经网络、数据分析。
本文借鉴了作者最近为《R语言数据分析挖掘必知必会 》课堂做的准备。
非常感谢您阅读本文,如需帮助请联系我们!