首页 理论教育 magick包中的图片处理方法

magick包中的图片处理方法

时间:2023-11-19 理论教育 版权反馈
【摘要】:R中涉及图片处理的包有magick、imager、imager Extra等,此处只介绍使用起来较为方便的magick包。在jpg和png这两种格式中,我们最好选择png格式,因为它支持图片的透明度image=image_read # 课件中的图片class # "magick-image"要注意的是,不同的读取图片函数得到的对象的类型不同。image # 显示图片及图片信息# format width height…第二个参数为角度image_flip # 上下翻转image_flop # 左右翻转## 图片截取image_crop(ima

magick包中的图片处理方法

在完成可视化任务的过程中,我们有时除了需要把数据映射到图表中,还需要在图表中添加图片,因此我们在此介绍一些与图片处理有关的操作。当然,读者也可以在读到本书与添加图片相关的内容时,再回过头来学习本部分。

R中涉及图片处理的包有magick、imager、imager Extra等,此处只介绍使用起来较为方便的magick包。

一、读入图片

# install.packages(c("magick", "imager"))

library(magick)

library(imager)

library(jpeg)

## 用image_read读取图片如果图片为pdf文件可用image_read_pdf函数读取在jpg和png这两种格式中我们最好选择png格式因为它支持图片的透明度

image=image_read("read.jpg") # 课件中的图片

class(image) # "magick-image"

要注意的是,不同的读取图片函数得到的对象的类型不同。magick::image_read生成magick-image对象;imager::load.image得到的是cimage对象,jpeg::read JPEG和png::read PNG得到的是array或native Raster对象。

image # 显示图片及图片信息

# format width height…

# 1 JPEG 872 595…

图片尺寸是指图片的宽和高。例子中图片的宽和高是872和595,或者说,它的尺寸是“872×595”,这意味着图片在水平方向上每行有872个像素,在垂直方向上每列有595个像素;如果给每个像素一个序号的话,那么图片的左上角就是第一个像素,右下角就是最后一个像素(换句话说,左上角是图片像素位置的原点)。

info=image_info(image) # 用image_info函数也可以提取图片信息

class(info) # "tbl_df" "tbl" "data.frame"

as.numeric(info[1, 2: 3]) # 提取宽和高

现在我们再来看看电脑是如何储存图片的

x1=load.image("read.jpg") # imager包中的函数

x1

# Image. Width: 872 pix Height: 595 pix Depth: 1 Colour channels: 3

计算机用四个维度来储存图片:除了宽和高之外,还有一个深度(Depth),它仅在视频中代表图片出现的时间顺序;颜色通道(Colour channels)是指颜色值,每一个像素都用其红/绿/蓝色的数值来表示。

现在我们再用数组来存储同一张图片。

x2=read JPEG("read.jpg") # jpeg包中的函数

dim(x2)

# [1] 595 872 3

这个数组包含3层每一层都相当于一个有595行相当于图片的高和872列相当于图片的宽矩阵而数组的3个层分别对应着像素的红/绿/蓝值如果图片包含透明度信息那么这个数组就会有4层

R(x1)[101: 105, 101: 105] # 用imager中的R函数G函数B函数可以提取红/绿/蓝值

t(x2[, , 1])[101: 105, 101: 105]

# 以上两种方法都用来提取红值的特定部分能够得到相同的结果

下边我们继续对变量类型进行转化。

image_ra=as.raster(image) # 转化为raster对象

class(image_ra) # "raster"

image_ma=as.matrix(image_ra) # 把raster对象转化为矩阵对象

dim(image_ra) # 595 872

dim(image_ma) # 595 872

image_ma[51: 53, 101: 102] # 截取图片的一部分

# [, 1] [, 2]

# [1, ] "#f1e7b4ff" "#f2e6b2ff"

# [2, ] "#f4e8b4ff" "#f4e8b4ff"

# [3, ] "#f8edb7ff" "#f8edb7ff"

可见,raster对象可以被看成一个矩阵。一张图片原本用包含三个通道的数组来表示,而现在为什么能够用仅有两个维度的数值来表示呢?这是因为在这个矩阵中,每一个像素的红/蓝/绿值(可能还要加上透明度值)都已被合并成一个十六进制字符,因而只占用一个单元格。这个raster对象或矩阵对象的第一行第一列的单元格对应着图片的左上角。

## 用image_convert实现不同格式图片的互相转化

image_png=image_convert(image, format="png", matte=TRUE) # 转为支持透明度的png图片时务必设置matte=TRUE

## 用image_write保存图片注意文件名的后缀要跟图片本身的格式相符

# image_write(image_png, "new.png")

二、裁剪、翻转、伸缩

image=image_read("read.jpg")

## 裁剪图片边缘

## 当图片有多余的边缘特别是白边这个函数会非常有用但需要注意的是一方面有时函数会裁掉过多的部分在这种情况下我们最好还是自己手动裁剪另一方面有时我们又会觉得裁剪得还不够多此时可调大fuzz参数0至100的数值默认为0

image=image_trim(image, fuzz=8)

image_info(image) # 裁剪边缘后图片变小

## 添加边缘

image_border(image, color="cyan", geometry="20x40") # geometry用来指定边缘的宽度

## 图片旋转

image_rotate(image, degrees=-45) # 旋转第二个参数为角度

image_flip(image) # 上下翻转

image_flop(image) # 左右翻转

## 图片截取

image_crop(image, geometry="550x300+39+209") # 此处geometry参数的含义是以宽4039+1)、高210209+1的位置为将要截取出的小图片的左上角截取宽550高300的区域

image_crop(image, geometry="416x557+0+0") # 保留左半边去掉右半边也就是从"+0+0"最左边最上边开始截取宽为416高为557的区域

image_crop(image, geometry="416x278+0+279") # 裁取图片左下角占图片四分之一的区域其中"0+279"代表从最左边高是279的位置开始截取"416x278"代表截取宽为416高是278的矩形区域

image_crop(image, geometry="400x250+20+30", gravity="southeast") #设定gravity为"southeast"后坐标原点变为右下角我们从右下角向左移20,向上移30截取宽为400高为250的区域

## 注意gravity的取值为"center""north""east""south""west","northeast""northwest"默认值即左上角)、"southeast""southwest"

image_crop(image, geometry="240x120+0+100", gravity="west") # 将gravity设为"west"此时geometry中"+0+0"表示左边中间位置而"+0+100"和"+0-100"的效果一样都表示向下移动100

#==========(www.xing528.com)

# 练习通过点击鼠标方便地进行截取

#==========

library(plothelper)

# image_crop_click(image) # 我们此时在画面上点击至少两次以便确定出矩形区域的四个边界然后按Esc键就可完成截取了读者可通过查阅该函数的帮助了解如何截取不规则区域

## 尺寸调整

image_resize(image, "400x390!") # 宽为400高为390

image_resize(image, "400x390") # 宽为400高为268

# 这两行代码的差异在于第1行代码加了"!"调整后图片的尺寸正好就是我们设定的尺寸只是图片的宽和高发生了扭曲第2行代码没有加"!"程序会尝试保持宽高比使图片不扭曲但尺寸不一定跟我们设定的相同

image_resize(image, "595x842!") # A4纸的比例

image_resize(image, "90%x120%!") # 两个数字后都加"%"会被理解为根据百分比进行调整

image_resize(image, "400x>450!") # ">450"的含义是如果图片的高大于450就将其调整为450如果不大于450就保持不变"<"的含义与此相仿

image_resize(image, "400") # 宽调为400高根据高宽比自动调整

image_resize(image, "400!") # 宽调为400高保持不变

image_resize(image, "x400") # 高调为400此处"x"前边什么都不写),宽自动调整

三、图片效果

plane=image_resize(image_read("plane yellow.jpg"), "25%x25%!") # 课件中的图片

## 转为黑白图片

image_convert(plane, colorspace="gray")

## 加入和减少噪声

image_noise(plane, noisetype="gaussian") # "gaussian"为高斯噪声图1-3-1a),还可选择"multiplicative""impulse""laplacian""poisson"

image_reducenoise(plane, radius=8) # 减少噪声以产生模糊化效果radius越大效果越明显图1-3-1b

## 模糊化

image_blur(plane, radius=5, sigma=10) # radius和sigma的默认值为1和0.5要增强效果必须同时增大它们的值图1-3-1c

image_median(plane, radius=10) # 中值模糊化图1-3-1d

## 油画效果

image_oilpaint(plane, radius=6) # radius越大效果越明显默认为1图1-3-1e

图1-3-1 左上=图a加入噪声,右上=图b减少噪声,左中=图c模糊化,右中=图d中值模糊化,左下=图e油画效果,右下=图f炭笔效果

## 炭笔效果

image_charcoal(plane, radius=1, sigma=0.5) # radius和sigma的默认值为1和0.5要增强效果必须同时增大它们的值图1-3-1f

## 反色

image_negate(plane) #图1-3-2a

image_negate(image_convolve(plane, kernel="Do G:0, 0, 2")) # High Pass效果图1-3-2b

## 酸化效果

image_emboss(plane, radius=2, sigma=2) # 主要通过调节radius参数改变效果

## 内爆扭曲

image_implode(plane, factor=0.5) # factor为0至1的数值

## 添加半透明矩形

image_colorize(plane, opacity=30, color="purple") # 必须给出opacity和coloropacity的值越大效果越明显图1-3-2c

## 均衡化

image_equalize(plane)

## HSV调整

image_modulate(plane, brightness=120, saturation=120, hue=190) # brightness和saturation参数表示明度和饱和度相对于当前值的变化百分比默认值都是100也就是不发生变化hue的默认值为100取值范围为0至200表示在色盘的当前位置向两边旋转的角度因此200就代表向后旋转180度)(图1-3-2d

图1-3-2 左上=图a反色,右上=图b High Pass效果,左中=图c添加半透明矩形,右中=图d HSV调整,左下=图e减少颜色并使用黑白颜色,右下=图f将透明背景变为有色背景

## 减少图片中颜色的数量

image_quantize(plane, max=2) # 用max指定允许出现的颜色的数量默认值为256

image_quantize(plane, max=20, colorspace="gray") # 转为黑白图片并限制灰度的数量图1-3-2e

## 添加背景色

transp=image_read("plane yellow transparent.png") # 课件中的图片

image_background(transp, color="purple") #图1-3-2f

## 图片合并

# 不同的合并效果是通过设置image_composite函数中的operator参数实现的,我们可以用compose_types()来查看operator的可选项以下列出了几种常用的操作

a=image_read("river.jpg") # 课件中的图片

a=image_resize(a, "600x400!")

b=image_read("plane transparent.png")

b=image_resize(b, "200x150!")

image_composite(a, b, operator="atop", offset="+200+125") # 将b置于a的上边并且将a中用offset指定的点作为b的左上角图1-3-3a

image_composite(a, b, operator="atop", gravity="center") # 将b置于a的中间请查看上文对gravity参数的解释

image_composite(a, b, operator="blend", compose_args="65", offset="+200+125") # operator="blend"代表图片融合compose_args用字符设定,数值越小b越不明显图1-3-3b

图1-3-3 左=图a atop合并,右=图b blend合并

# 先把a中与b尺寸相同的一个区域在本例中是a的中心区域截取出来再用b的形状去截取这个区域

part=image_crop(a, "200x150+199+124")

image_composite(b, part, operator="in") # 飞机轮廓外变为透明图1-3-4aimage_composite(b, part, operator="out") # 飞机轮廓内变为透明图1-3-4b# 现在将operator设为"dstout"从而保留a但是让a由b中的图形占据的地方变为透明注意透明度在jpg格式的图片中是无效的而本例中的a就是jpg格式的图片因此我们必须首先将a转为png格式同时用matte=TRUE打开透明度效果图1-3-4c

a_matte=image_convert(a, "png", matte=TRUE)

image_composite(a_matte, b, operator="dstout", offset="+200+125")

图1-3-4 左上=图a in合并,左下=图b out合并,右=图c dstout合并

免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。

我要反馈