Обработка нескольких изображений с помощью Magick (в R) с преобразованиями - PullRequest
3 голосов
/ 05 июня 2019

Мне нужно автоматизировать некоторые преобразования изображений, чтобы сделать следующее: - читать более 16 000 изображений, которые короткие и широкие, размеры не одинаковы. - масштабировать каждое изображение до 90 пикселей в высоту - обрезать 90 пикселей по ширине изображения, так что несколько 90х90 обрезать по 1 изображению - затем сделать это снова для следующего изображения - каждое изображение 90x90 должно быть сохранено как file-name_1.png, file-name_2.png и т. д. в последовательном порядке

Я выполнил тест на 8 изображениях, и с помощью пакета magick мне удалось изменить масштаб и вручную создать несколько обрезок для каждого изображения. Проблема в том, что когда я пытаюсь сделать несколько изображений, я могу легко изменить размер изображений, но когда дело доходит до их сохранения, возникает проблема.

# capture images, file paths in a list
img_list <- list.files("./orig_images", pattern = "\\.png$", full.names = TRUE)

# get all images in a list
all_images <- lapply(img_list, image_read)

# scale each image height - THIS DOESN'T WORK, GET NULL VALUE
scale_images <- 
  for (i in 1:length(all_images)) {
  scale_images(all_images[[i]], "x90")
    }

# all images added into one
all_images_joined <- image_join(all_images)

# scale images - THIS WORKS to scale, but problems later
all_images_scaled <- 
  image_scale(all_images_joined, "x90")

# Test whether a single file will be written or multiple files; 
# only writes one file (even if I 
for (i in 1:length(all_images_scaled)) {
  image_write(all_images_scaled[[i]], path = "filepath/new_cropimages/filename")
}

В идеале я бы масштабировал изображения с помощью цикла for. Таким образом, я могу сохранить масштабированные изображения в каталог. Это не сработало - я не получаю сообщение об ошибке, но когда я проверяю содержимое переменной, оно равно нулю. Функция image_join объединяет их все и масштабирует до 90 (ширина также пропорционально масштабируется), но я не могу записать отдельные изображения в каталог. Кроме того, следующий фрагмент - обрезать каждое изображение по ширине и сохранить новые изображения file-name_1.png и т. Д. Для каждого изображения 90x90, переместить на 90 пикселей, обрезать 90x90 и т. Д. Я выбрал магию, потому что было легко индивидуально масштабировать и обрезать, но я открыт для других идей (или учусь, как заставить этот пакет работать). Спасибо за любую помощь.

Вот несколько изображений:

[Original Image, untransformed][1]
[Manual 90x90 crop][2]
[Another manual 90x90 crop, farther down the same image][3]


  [1]: https://i.stack.imgur.com/8ptXv.png
  [2]: https://i.stack.imgur.com/SF9pG.png
  [3]: https://i.stack.imgur.com/NyKxS.png

Ответы [ 2 ]

1 голос
/ 06 июня 2019

Обновлено - чтобы лучше использовать инструменты в EBImage

ImageMagick - отличный подход.Но если вы хотите выполнить некоторый контент-анализ изображений, вот решение с помощью R. R предоставляет довольно удобные инструменты.Кроме того, изображения - это «ничто», кроме матриц, с которыми R справляется очень хорошо.Сокращая изображения до матриц, пакет EBImage делает это очень хорошо и, к лучшему или к худшему, удаляет некоторые метаданные с каждым изображением.Вот решение R с EBImage.Опять же, решение Марка может быть лучше для действительно больших производственных циклов.

Решение построено вокруг большого цикла «для».Было бы целесообразно добавить проверку ошибок в несколько этапов.Код использует преимущества EBImage для управления как цветными изображениями, так и изображениями в градациях серого.

Здесь конечное изображение центрируется в расширенном изображении путем добавления пикселей требуемого цвета фона.Расширенное изображение затем обрезается на плитки.Логика, определяющая значение для pad, может быть скорректирована, чтобы просто обрезать изображение или выровнять по левому краю или по правому краю, если это необходимо.

Он начинается с предположения, что вы начинаете в рабочем каталоге с исходными файлами в ./source и местом назначения в ./dest.Он также создает новый каталог для каждого «мозаичного» изображения.Это можно изменить, чтобы один каталог получал все изображения, а также другие защитные коды.Здесь предполагается, что изображения представляют собой файлы PNG с соответствующим расширением.Требуемый размер плитки (90) для применения к высоте и ширине сохраняется в переменной size.

# EBImage needs to be available
  if (!require(EBImage)) {
    source("https://bioconductor.org/biocLite.R")
    biocLite("EBImage")
    library(EBImage)
  }

# From the working directory, select image files
  size <- 90
  bg.col <- "transparent" # or any other color specification for R
  ff <- list.files("source", full = TRUE,
    pattern = "png$", ignore.case = TRUE)

# Walk through all files with a 'for' loop, 
  for (f in ff) {
    # Extract base name, even names like "foo.bar.1.png" 
      txt <- unlist(strsplit(basename(f), ".", fixed = TRUE))
      len <- length(txt)
      base <- ifelse(len == 1, txt[1], paste(txt[-len], collapse = "."))

    # Read one image and resize
      img <- readImage(f)
      img <- resize(img, h = size) # options allow for antialiasing

    # Determine number tiles and padding needed
      nx <- ceiling(dim(img)[1]/size)
      newdm <- c(nx * size, size) # extend final image
      pad <- newdm[1] - dim(img)[1] # pixels needed to extend 

    # Translate the image with given background fille
      img <- translate(img, c(pad%/%2, 0), output.dim = newdm, bg.col = bg.col)

    # Split image into appropriate sized tiles with 'untile'
      img <- untile(img, c(nx, 1), lwd = 0) # see the help file

    # Create a new directory for each image
      dpath <- file.path("dest", trimws(base)) # Windows doesn't like " "
      if (!dir.create(dpath))
        stop("unable to create directory: ", dpath)

    # Create new image file names for each frame
      fn <- sprintf("%s_%03d.png", base, seq_len(nx))
      fpaths <- file.path(dpath, fn)

    # Save individual tiles (as PNG) and names of saved files
      saved <- mapply(writeImage, x = getFrames(img, type = "render"), 
        files = fpaths)

    # Check on the results from 'mapply'
      print(saved)
  }

1 голос
/ 06 июня 2019

Я не говорю на R, но я надеюсь, что смогу помочь с аспектами ImageMagick и обработать 16 000 изображений.

Находясь на Mac, вы можете очень легко установить 2 очень полезных пакета с помощью homebrew , используя:

brew install imagemagick
brew install parallel

Итак, ваше исходное изображение предложения имеет размер 1850x105 пикселей, вы можете видеть это в терминале так:

magick identify sentence.png
sentence.png PNG 1850x105 1850x105+0+0 8-bit Gray 256c 51626B 0.000u 0:00.000

Если вы измените высоту до 90px, оставив пропорциональную ширину, она станет 1586x90px:

magick sentence.png -resize x90 info:
sentence.png PNG 1586x90 1586x90+0+0 8-bit Gray 51626B 0.060u 0:00.006

Итак, если вы измените размер, а затем обрежете его на фрагменты шириной 90px:

magick sentence.png -resize x90 -crop 90x chunk-%03d.png

вы получите 18 кусков, каждый шириной 90 пикселей, кроме последнего, следующим образом:

-rw-r--r--  1 mark  staff  5648  6 Jun 08:07 chunk-000.png
-rw-r--r--  1 mark  staff  5319  6 Jun 08:07 chunk-001.png
-rw-r--r--  1 mark  staff  5870  6 Jun 08:07 chunk-002.png
-rw-r--r--  1 mark  staff  6164  6 Jun 08:07 chunk-003.png
-rw-r--r--  1 mark  staff  5001  6 Jun 08:07 chunk-004.png
-rw-r--r--  1 mark  staff  6420  6 Jun 08:07 chunk-005.png
-rw-r--r--  1 mark  staff  4726  6 Jun 08:07 chunk-006.png
-rw-r--r--  1 mark  staff  5559  6 Jun 08:07 chunk-007.png
-rw-r--r--  1 mark  staff  5053  6 Jun 08:07 chunk-008.png
-rw-r--r--  1 mark  staff  4413  6 Jun 08:07 chunk-009.png
-rw-r--r--  1 mark  staff  5960  6 Jun 08:07 chunk-010.png
-rw-r--r--  1 mark  staff  5392  6 Jun 08:07 chunk-011.png
-rw-r--r--  1 mark  staff  4280  6 Jun 08:07 chunk-012.png
-rw-r--r--  1 mark  staff  5681  6 Jun 08:07 chunk-013.png
-rw-r--r--  1 mark  staff  5395  6 Jun 08:07 chunk-014.png
-rw-r--r--  1 mark  staff  5065  6 Jun 08:07 chunk-015.png
-rw-r--r--  1 mark  staff  6322  6 Jun 08:07 chunk-016.png
-rw-r--r--  1 mark  staff  4848  6 Jun 08:07 chunk-017.png

Теперь, если у вас есть 16 000 предложений для обработки, вы можете использовать GNU Parallel , чтобы выполнить их все параллельно, а также получить разумные имена для всех файлов. Давайте сначала сделаем пробный прогон, чтобы он на самом деле ничего не делал, а просто показал вам, что он будет делать:

parallel --dry-run magick {} -resize x90 -crop 90x {.}-%03d.png ::: sentence*

Пример вывода

magick sentence1.png -resize x90 -crop 90x sentence1-%03d.png 
magick sentence2.png -resize x90 -crop 90x sentence2-%03d.png
magick sentence3.png -resize x90 -crop 90x sentence3-%03d.png

Это выглядит хорошо, поэтому удалите --dry-run и сделайте это снова, и вы получите следующий вывод для трех (идентичных копий) вашего предложения, которое я сделал:

-rw-r--r--  1 mark  staff  5648  6 Jun 08:13 sentence1-000.png
-rw-r--r--  1 mark  staff  5319  6 Jun 08:13 sentence1-001.png
-rw-r--r--  1 mark  staff  5870  6 Jun 08:13 sentence1-002.png
-rw-r--r--  1 mark  staff  6164  6 Jun 08:13 sentence1-003.png
-rw-r--r--  1 mark  staff  5001  6 Jun 08:13 sentence1-004.png
-rw-r--r--  1 mark  staff  6420  6 Jun 08:13 sentence1-005.png
-rw-r--r--  1 mark  staff  4726  6 Jun 08:13 sentence1-006.png
-rw-r--r--  1 mark  staff  5559  6 Jun 08:13 sentence1-007.png
-rw-r--r--  1 mark  staff  5053  6 Jun 08:13 sentence1-008.png
-rw-r--r--  1 mark  staff  4413  6 Jun 08:13 sentence1-009.png
-rw-r--r--  1 mark  staff  5960  6 Jun 08:13 sentence1-010.png
-rw-r--r--  1 mark  staff  5392  6 Jun 08:13 sentence1-011.png
-rw-r--r--  1 mark  staff  4280  6 Jun 08:13 sentence1-012.png
-rw-r--r--  1 mark  staff  5681  6 Jun 08:13 sentence1-013.png
-rw-r--r--  1 mark  staff  5395  6 Jun 08:13 sentence1-014.png
-rw-r--r--  1 mark  staff  5065  6 Jun 08:13 sentence1-015.png
-rw-r--r--  1 mark  staff  6322  6 Jun 08:13 sentence1-016.png
-rw-r--r--  1 mark  staff  4848  6 Jun 08:13 sentence1-017.png
-rw-r--r--  1 mark  staff  5648  6 Jun 08:13 sentence2-000.png
-rw-r--r--  1 mark  staff  5319  6 Jun 08:13 sentence2-001.png
-rw-r--r--  1 mark  staff  5870  6 Jun 08:13 sentence2-002.png
-rw-r--r--  1 mark  staff  6164  6 Jun 08:13 sentence2-003.png
-rw-r--r--  1 mark  staff  5001  6 Jun 08:13 sentence2-004.png
-rw-r--r--  1 mark  staff  6420  6 Jun 08:13 sentence2-005.png
-rw-r--r--  1 mark  staff  4726  6 Jun 08:13 sentence2-006.png
-rw-r--r--  1 mark  staff  5559  6 Jun 08:13 sentence2-007.png
-rw-r--r--  1 mark  staff  5053  6 Jun 08:13 sentence2-008.png
-rw-r--r--  1 mark  staff  4413  6 Jun 08:13 sentence2-009.png
-rw-r--r--  1 mark  staff  5960  6 Jun 08:13 sentence2-010.png
-rw-r--r--  1 mark  staff  5392  6 Jun 08:13 sentence2-011.png
-rw-r--r--  1 mark  staff  4280  6 Jun 08:13 sentence2-012.png
-rw-r--r--  1 mark  staff  5681  6 Jun 08:13 sentence2-013.png
-rw-r--r--  1 mark  staff  5395  6 Jun 08:13 sentence2-014.png
-rw-r--r--  1 mark  staff  5065  6 Jun 08:13 sentence2-015.png
-rw-r--r--  1 mark  staff  6322  6 Jun 08:13 sentence2-016.png
-rw-r--r--  1 mark  staff  4848  6 Jun 08:13 sentence2-017.png
-rw-r--r--  1 mark  staff  5648  6 Jun 08:13 sentence3-000.png
-rw-r--r--  1 mark  staff  5319  6 Jun 08:13 sentence3-001.png
-rw-r--r--  1 mark  staff  5870  6 Jun 08:13 sentence3-002.png
-rw-r--r--  1 mark  staff  6164  6 Jun 08:13 sentence3-003.png
-rw-r--r--  1 mark  staff  5001  6 Jun 08:13 sentence3-004.png
-rw-r--r--  1 mark  staff  6420  6 Jun 08:13 sentence3-005.png
-rw-r--r--  1 mark  staff  4726  6 Jun 08:13 sentence3-006.png
-rw-r--r--  1 mark  staff  5559  6 Jun 08:13 sentence3-007.png
-rw-r--r--  1 mark  staff  5053  6 Jun 08:13 sentence3-008.png
-rw-r--r--  1 mark  staff  4413  6 Jun 08:13 sentence3-009.png
-rw-r--r--  1 mark  staff  5960  6 Jun 08:13 sentence3-010.png
-rw-r--r--  1 mark  staff  5392  6 Jun 08:13 sentence3-011.png
-rw-r--r--  1 mark  staff  4280  6 Jun 08:13 sentence3-012.png
-rw-r--r--  1 mark  staff  5681  6 Jun 08:13 sentence3-013.png
-rw-r--r--  1 mark  staff  5395  6 Jun 08:13 sentence3-014.png
-rw-r--r--  1 mark  staff  5065  6 Jun 08:13 sentence3-015.png
-rw-r--r--  1 mark  staff  6322  6 Jun 08:13 sentence3-016.png
-rw-r--r--  1 mark  staff  4848  6 Jun 08:13 sentence3-017.png

Несколько слов о параметрах parallel:

  • {} относится к «текущему файлу»
  • {.} означает «текущий файл без его расширения»
  • ::: отделяет параметры, предназначенные для parallel, от параметров, предназначенных для вашей magick команды

Одно замечание: PNG-изображения могут «помнить» , откуда они пришли, что может быть полезным или очень раздражающим. Если вы посмотрите на последний фрагмент сверху, вы увидите, что он 56x90, но после этого он «запоминает» он был получен с холста 1586x90 со смещением 1530,0:

identify sentence3-017.png 
sentence3-017.png PNG 56x90 1586x90+1530+0 8-bit Gray 256c 4848B 0.000u 0:00.000

Это может иногда расстраивать последующую обработку, что раздражает, или иногда очень полезно при повторной сборке изображений, которые были нарезаны! Если вы хотите удалить его, вам необходимо выполнить повторную команду, поэтому приведенная выше команда выглядит так:

magick input.png -resize x90 -crop 90x +repage output.png 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...