Как объединить несколько CGImage в больший CGImage? - PullRequest
0 голосов
/ 23 марта 2020

Я создал приложение, которое применяет нейронную сеть (con vnet) к входному изображению с последующей постобработкой. Этот con vnet является в основном фильтром, который вводит изображение (плюс один параметр) и выводит изображение аналогичного размера. Поскольку con vnet не может обработать большое изображение за один проход из-за проблемы с памятью, изображение должно быть разбито на плитки, которые затем склеиваются (или объединяются) вместе после применения модели. Моя проблема связана с манипулированием изображениями. После того, как я представлю вам, что будет сделано в деталях, будет более ясно:

  • Входное изображение - это UIImage
  • Разделить входное изображение на список UIImage, называемый listInput
  • Создать пустой listOutput
  • Для каждой плитки в listInput:
    • Преобразовать UIImage в CGImage
    • Преобразовать CGImage в CVPixelBuffer
    • Применение модели CoreML к CVPixelBuffer, который возвращает CVPixelBuffer того же размера
    • Преобразование CVPixelBuffer в CIImage
    • Преобразование CIImage в CGImage
    • Преобразуйте CGImage в UIImage
    • Добавьте UIImage в listOutput
  • Объедините все плитки в listOutput в выходной UIImage
  • Fuse ввод и вывод UIImage (постобработка):
    • Преобразование ввода UIImage в CGImage, затем в CIImage
    • Преобразование вывода UIImage в CGImage, затем в CIImage
    • Слияние 2 CIImage с помощью CIFilter
    • Конвертировать полученный CI Изображение в CGImage
    • Преобразование CGImage в UIImage

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

Общая проблема, с которой я сталкиваюсь, - это все преобразования между UIImage в CGImage в CIImage и в диалог. Я пытаюсь полностью избавиться от UIImage (за исключением загрузки изображения). Я действительно хочу манипулировать CGImage от начала до конца. Это уже упростит код.

Я изменил свой код, чтобы манипулировать списком CGImage вместо списка UIImage. Часть обрезки на самом деле проще с CGImage, чем с UIImage. Но я не могу разобраться с другой стороной: объединить CGImage вместе в большее изображение. Это моя конкретная проблема c. Сильфон - это функция, которую я создал для унификации UIImage.

func unifyTiles(listTiles: [UIImage], listRect: [CGRect]) -> UIImage? {

    guard let input = input else {
        return nil
    }


    let outputSize = CGSize(width : Int(input.size.width), height: Int(input.size.height))

    UIGraphicsBeginImageContextWithOptions(outputSize, true, 1.0)

    for i in 0..<listTiles.count {
        listTiles[i].draw(at: listRect[i].origin)
    }

    guard let output = UIGraphicsGetImageFromCurrentImageContext() else {
        return nil
    }
    UIGraphicsEndImageContext()

    return output
}

Итак, мой вопрос:

  • Можно ли сделать то же самое, просто манипулируя CGImage?
  • Это даже хорошая идея?

Некоторые примечания:

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

  • В посте -процесс обработки, мне было предложено конвертировать непосредственно UIImage <-> CIImage без прохождения CGImage. По некоторым причинам, которые я не знаю, насколько я помню, это не работает.

  • Я знаю, что используя Vision, я мог бы вместо этого напрямую подавать CGImage в сеть CVPixelBuffer, но я не знаю, может ли Vision также выводить CGImage. Надеемся, что скоро это будет расследовано.

Спасибо за любую информацию, которую вы могли бы дать мне.

1 Ответ

1 голос
/ 23 марта 2020

UIImage к CIImage

Этот шаг:

UIImage в CGImage, затем к CIImage

преувеличивается, так как CIImage имеет инициализатор init(image:) это идет непосредственно от UIImage к CIImage.

Обрезка

Вы, кажется, думаете, что обрезать CGImage проще, чем обрезать UIImage, но это не так. Чтобы обрезать UIImage, просто нарисуйте его в меньшем графическом контексте со смещением, чтобы поместить нужную точку в верхнем левом углу обрезки.

Графические контексты

Вы можете рисовать только в графический контекст, и это будет контекст изображения, нравится вам это или нет. Нет такой вещи, как рисование в «контексте CGImage», если вы об этом думаете. Вы можете нарисовать CGImage непосредственно в контексте изображения, но результаты обычно являются катастрофическими (как я объясню в следующем параграфе).

Заключительные мысли

В общем, я хотел бы установить ваши ум в состоянии покоя об UIImage. UIImage - это хорошая вещь. Это (обычно) очень легкая обертка вокруг CGImage. CGImage - это растровые данные; Оболочка добавляет информацию, такую ​​как масштаб и ориентация. Потеря этой информации может привести к очень плохому выходу рисунка; попытка нарисовать CGImage может привести к тому, что рисунок будет перевернут и неправильно масштабирован. Не делай этого! Используй UIImage и будь счастлив.

...