# 4.2.1 熊大图像处理

    # 清空工作空间
    rm(list = ls())

    # 引入所需要的package
    # install.packages(knitr)
    require(knitr)
    # install.packages(jpeg)
    library(jpeg)
    # install.packages(png)
    library(png)
    # 安装EBImage包，只安装一次即可
    # source("http://bioconductor.org/biocLite.R")
    # biocLite("EBImage")
    library(EBImage)
    # install.packages(RgoogleMaps)
    library(RgoogleMaps)
    # install.packages(magick)
    library(magick)

## 1. 读取、储存图像

想要处理图像，第一件事儿就是把图像读进来，处理完成后也许要把图像再次储存。这里我们以最常见的两种图像格式JPG和PNG为例来展示R读取和储存图像的方法。

    data1 = readJPEG("bear_1.jpg")  # 读入jpg格式的图像
    writeJPEG(data1, target = "bear_jpg_saved.jpg", quality = 1)  # 存储图像

    data2 = readPNG("bear_1_png.png")  # 读入png格式的图像
    writePNG(data2, target = "bear_png_saved.png")  # 存储图像

有时候我们需要处理大量的图像，难道要用“人工”智能来手动输入所有图像名吗？小编的内心是拒绝的。其实只要使用一个简单的for循环就可以批量处理一个文件夹中的所有图像，关键问题是明确循环中要遍历的变量是什么。直观上，识别同一文件夹中的不同图像时最简单的依凭是图像的名字。

    fileName = dir("bear_family/")  # 读取图像名
    for (i in 1:length(fileName)){
      # 读入其中一张图像
      # 在这行代码之后可以输入具体的图像处理函数从而实现批量处理
      file_image_data = readJPEG(paste("bear_family/", fileName[i], sep = ''))
    }

## 2. 提取图像的三基色通道

对于人类视觉系统来说，自然界中的大多数色彩都可由红、绿、蓝三色按不同的比例混合而成，R读入的图像也储存了这三色通道的信息。这里需要引入名为“EBImage”的包，利用基础的矩阵运算即可提取三基色通道的信息。

    X1 = readImage("bear_1.jpg")  # 读入图像
    n.size = 300
    X1 = resize(X1, n.size, n.size)  # 修整图像尺寸，为下面的处理做准备

    X11 = X1; X11[, , 1] = 0 * X11[, , 1]; X11[, , 2] = 0 * X11[, , 2]; display(X11)  # 提取蓝色通道的图像

    X12 = X1; X12[, , 1] = 0 * X12[, , 1]; X12[, , 3] = 0 * X12[, , 3]; display(X12)  # 提取绿色通道的图像

    X13 = X1; X13[, , 2] = 0 * X13[, , 2]; X13[, , 3] = 0 * X13[, , 3]; display(X13)  # 提取红色通道的图像

想要看看不同通道混合而成的图像吗？只需要在display()函数中用简单的加号即可实现。

    display(X11 + X12)  # 蓝色熊大+绿色熊大

    display(X11 + X13)  # 蓝色熊大+红色熊大

    display(X12 + X13)  # 绿色熊大+红色熊大

## 3. 灰度图

如前文所述，读入的图像以一个三维数组的形式储存，运算较为复杂，这在后续的图像处理极为不便，机智的前辈们对此进行了降维从而提出了灰度图的概念。这里提供两种转化灰度图的方法。第一种是用之前使用的EBImage包，第二种是用RgoogleMaps包。

    gray_image = channel(data1, "gray")  # 用EBImage包转灰度图
    gray_image = RGB2GRAY(data1)  # 用RgoogleMaps包转灰度图

## 4. 分辨率

    Y1 = readJPEG("bear_1_green.jpg")  # 读入图像
    gray_image = RGB2GRAY(Y1)  # 转灰度图

    # 画图展示图像分割
    plot_jpeg = function(M, add = FALSE)  # 画图函数
    {
      res = dim(M)[1:2]  # get the resolution
      if (!add)  # initialize an empty plot area if add == FALSE
        plot(1, 1, xlim = c(1, res[1]), ylim = c(1, res[2]), type = "n", asp = 1,
             xlab = '', ylab = '', bty = 'n', xaxs = 'i', yaxs = 'i', xaxt = 'n', yaxt = 'n')
      rasterImage(M, 1, 1, res[1], res[2])
      axis(1, at = (1:9) * 30, tick = T);
      axis(2, at = (1:9) * 30, tick = T);
      abline(h = (1:9) * 30, v = (1:9) * 30, col = "yellow", lty = 2)
    }
    plot_jpeg(gray_image)

    # 将每个分割的小块像素归一
    index_group = cut(1:300, seq(0, 300, 30))
    lev = levels(index_group)
    M1 = matrix(0, nrow = length(lev), ncol = length(lev))
    for (i in 1:length(lev))
    {
      for (j in 1:length(lev))
      {
        M1[i, j] = mean(gray_image[index_group == lev[i], index_group == lev[j]])  # M1即为10*10的图像
      }
    }

## 5. 图像运算

图像与数字或图像与图像进行简单的运算会碰撞出怎样的火花呢？再次搬出神奇的display()函数。

    display(X1 + 0.5)  # 熊大+0.5

    display(X1 - 0.5)  # 熊大-0.5

    display(X1 * 2)  # 熊大*2

    display(X1 / 2)  # 熊大/2

    display(1 - X1)  # 1-熊大

    display(X1 ^ 10)  # 熊大^10

    X2 = readImage("bear_2.jpg");
    X2 = resize(X2, n.size, n.size)  # 读入熊二的图像
    display(X2)

    display(X1 + X2)  # 熊大+熊二

    display(X1 - X2)  # 熊大-熊二

## 6. magick包

用magick包可以对图像进行更为多样的处理。

    data1 = image_read("bear_1.jpg")  # 读入图像
    image_crop(data1, "100 x 150 + 50")  # 剪切图像

    image_border(data1, "black", "10 x 10")  # 加边框

    image_rotate(data1, 45)  # 旋转45度

    image_flip(data1)  # 上下翻转

    image_flop(data1)  # 左右翻转

    image_negate(data1)  # 反色

    # 加标签
    image_annotate(data1, "CONFIDENTIAL", size = 30, color = "red", boxcolor = "pink", degrees = 60, location = "+ 50 + 100")

    image_noise(data1)  # 噪点

    image_charcoal(data1)  # 素描风格

对图像的基本分析的就介绍到这里，接下来我们将会以一个与PM2.5有关的实例来进一步说明R在图像分析中的妙用。