Удаляем фон у фото используя CoreML / Хабр
Всем привет! Однажды передо мной встала задача сделать фон картинки прозрачным, без мам, пап и бекндов… Задача есть, надо её решать! В этой статье вы узнаете, с чем мне пришлось столкнуться и как я реализовал вырезание заднего фона у фотографий в приложении на iOS.
Зачем вообще вот это вот всё ?
В приложении, над которым я работаю, есть редактор создания коллажа. Коллаж создаётся из фотографий одежды, аксессуаров, обуви и прочего. Все фотографии нашего каталога, имеют белый фон, но для реализации качественного результата этот фон нужно вырезать, а иначе получится мозаика из фотографий. Исторически, обрезание фона происходило на бекенде на устройстве силами библиотеки GPUImage, но результат оставлял желать лучшего…
Как можно заметить, присутствует очень много «снега» и артефактов.
Решено, внедряем машинное обучение !
Ищем способ удаления заднего фона
На просторах интернета есть хорошие туториалы, описывающие удаление фона с использованием модели машинного обучения DeeplabV3, представленной на официальном сайте Аpple. Только есть одно но. Данная моделька распознаёт ограниченный набор натренированных объектов и если скормить ей картинку с кроссовками или сумкой, она просто не распознает объекта на ней.
Продолжительный гуглинг открыл для меня прекрасную модель под названием u2Net. Данная модель очень качественно сегментирует фотографию на объекты, расположенные на ней. Но на страничке гитхаба модельки лежат в неведомом формате .pth, а ведь наш родной CoreML принимает только формат .mlModel, что делать ?
Есть два пути:
Используем официальную python тулзу для конвертации моделей в .mlModel формат
Заходим на страничку гитхаба, где сконвертировали всё за вас
Выбор очевиден 😅
Внедряем U2Net в своё приложение
И так, для того, что бы магия свершилась, нам нужно, чтобы моделька оказалась внутри нашего приложения. Самый простой путь — перетащить её в директорию. На выбор вам предоставляется две модели, u2Net и u2Netp, пока выбирайте любую, в чём их отличие помимо размера мы поговорим далее.
Модель машинного обучения среди файловПосле того как модель окажется внутри вашего файлового дерева, будет сгенерирован класс для импортированной модели, название его вы увидите на страничке модельки.
Расположение названия классаНаконец-то настало время попрограммировать. Разминаем пальчики !
Давайте, для удобства сделаем функцию, которая будет присутствовать у каждого экземпляра UIImage класса, что бы, если нам вздумается, мы могли вырезать фон где угодно !! И забегая немного вперёд, уточню, что модель машинного обучения принимают изображения строго определённого размера, который описан на страничке модели во вкладке
import UIKit extension UIImage { func removeBackgroudIfPosible() -> UIImage? { let resizedImage: UIImage = resize(size: .init(width: 320, height: 320)) ... } }Используемая функция resize
extension UIImage { func resize(size: CGSize? = nil, insets: UIEdgeInsets = . zero, fill: UIColor = .white) -> UIImage { var size: CGSize = size ?? self.size let widthRatio = size.width / self.size.width let heightRatio = size.height / self.size.height if widthRatio > heightRatio { size = CGSize(width: floor(self.size.width * heightRatio), height: floor(self.size.height * heightRatio)) } else if heightRatio > widthRatio { size = CGSize(width: floor(self.size.width * widthRatio), height: floor(self.size.height * widthRatio)) } let rect = CGRect(x: 0, y: 0, width: size.width + insets.left + insets.right, height: size.height + insets.top + insets.bottom) UIGraphicsBeginImageContextWithOptions(rect.size, false, scale) fill.setFill() UIGraphicsGetCurrentContext()?.fill(rect) draw(in: CGRect(x: insets.left, y: insets.top, width: size.width, height: size. height)) let newImage = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() return newImage! } }
Так, картинку мы отресайзили под нужные нам размеры, что дальше, спросите вы ?
Дальше — магия машинного обучения и предсказание !!
import UIKit extension UIImage { func removeBackgroudIfPosible() -> UIImage? { let resizedImage: UIImage = resize(size: .init(width: 320, height: 320)) guard let resizedCGImage = resizedImage.cgImage, let originalCGImage = cgImage, let mlModel = try? u2netp(), let resultMask = try? mlModel.prediction(input: u2netpInput(in_0With: resizedCGImage)).out_p1 else { return nil } ... } }
Давайте я опишу, получившийся, жирный guard и что там происходит.
resizedCGImage — У u2netpInput, есть несколько инициализаторов, мы будем работать с тем, что принимает cgImage;
originalCGImage — cgImage оригинального изображения, будем использовать далее для наложения маски;
mlModel — инстанс модели машинного обучения, инициализированный на основе сгенерированного класса;
resultMask — та самая магия! Функция prediction, возвращает нам u2netpOutput, где out_p1 можно использовать в качестве маски нашего изображения!
Если преобразовать получившуюся маску в картинку, то мы сможем увидеть то, как моделька обработала входящие картинки. Так как возвращаемая картинка имеет размер 320×320, не забудьте заресайзить её под исходные размеры.
let originalImage = CIImage(cgImage: originalCGImage) var maskImage = CIImage(cvPixelBuffer: resultMask) let scaleX = originalImage.extent.width / maskImage.extent.width let scaleY = originalImage.extent.height / maskImage.extent.height maskImage = maskImage.transformed(by: .init(scaleX: scaleX, y: scaleY)) return UIImage(ciImage: maskImage)Маски исходных изображений
Вау! Выглядит очень аккуратно, нет снега и каки-то сильных вкраплений, давайте накладывать маску на оригинальную картинку !
Применяем получившуюся маску
У Apple есть хорошая статья, демонстрирующая подход по применения сегментирующей маски к исходному изображению. Её то мы и возьмём за основу с небольшими доработками.
let context = CIContext(options: nil) guard let inputCGImage = context.createCGImage(originalImage, from: originalImage.extent) else { return nil } let blendFilter = CIFilter. blendWithRedMask() blendFilter.inputImage = CIImage(cgImage: inputCGImage) blendFilter.maskImage = maskImage guard let outputCIImage = blendFilter.outputImage?.oriented(.up), let outputCGImage = context.createCGImage(outputCIImage, from: outputCIImage.extent) else { return nil } return UIImage(cgImage: outputCGImage)
Итак, поскольку мы оперируем CIImage и применяем к ней фильтр, я бы хотел сохранить исходное качество, с использованием CIContext удалось этого добиться.
Используя эти не хитрые манипуляции, мы можем взглянуть на результат!
Хочется сказать только одно — ВАУ! О такой качественном обрезании мы могли только мечтать, а количество кода, которое пришлось написать, просто мизирное!
Финальная функция для обрезания фото у картинкиimport UIKit import CoreML import CoreImage.CIFilterBuiltins extension UIImage { func removeBackgroudIfPosible() -> UIImage? { let resizedImage: UIImage = resize(size: . init(width: 320, height: 320)) guard let resizedCGImage = resizedImage.cgImage, let originalCGImage = cgImage, let mlModel = try? u2netp(), let resultMask = try? mlModel.prediction(input: u2netpInput(in_0With: resizedCGImage)).out_p1 else { return nil } let originalImage = CIImage(cgImage: originalCGImage) var maskImage = CIImage(cvPixelBuffer: resultMask) let scaleX = originalImage.extent.width / maskImage.extent.width let scaleY = originalImage.extent.height / maskImage.extent.height maskImage = maskImage.transformed(by: .init(scaleX: scaleX, y: scaleY)) let context = CIContext(options: nil) guard let inputCGImage = context.createCGImage(originalImage, from: originalImage.extent) else { return nil } let blendFilter = CIFilter.blendWithRedMask() blendFilter.inputImage = CIImage(cgImage: inputCGImage) blendFilter.maskImage = maskImage guard let outputCIImage = blendFilter.outputImage?.oriented(.up), let outputCGImage = context.createCGImage(outputCIImage, from: outputCIImage.extent) else { return nil } return UIImage(cgImage: outputCGImage) } }
Всё круто, но как ты собираешься хранить такую тяжёлую модель ?
Модель машинного обучения u2Net, распространяется в двух версиях, u2Netp — light версия 4.6 мб и u2Net — full версия 175.9 мб . Разница между ними очень ощутима, если обратить внимание на их вес. Полную версию u2Net даже не получится хранить в гите, так что не советую вам комитить код с полной моделькой, если планируете его пушить на github. На результат работы light модели можно взглянуть ниже.
Обрезание фона с использованием Light версии моделиМы же приняли решение хранить в приложении light версию модели, а большую, полную версию модели загружать в фоне, что позволило сохранить функциональность редактора, пока модель не загружена. Если вы захотите сделать тоже самое, Apple и тут о нас подумали и написали туториал !
Итог
Теперь мы умеем пользоваться моделями машинного обучения в iOS приложении и применять их на практике. Машинное обучение открывает море возможностей для распознания, сегментации, классификации, оценки глубины, обнаружения объектов и позы человека и это всё только про фото, а ведь можно ещё и работать с текстом !
Помимо сторонних моделей машинного обучения, iOS имеет встроенный фраемворк Vision, который, оперируя алгоритмами машинного зрения, поможет вам обнаружить лицо, кисть, штрихкод или человека!
Спасибо за прочтение! Надеюсь, что эта статья помогла вам решить аналогичную задачу или просто помогла узнать, как работать с ML моделями в iOS.
Используемые материалы
Список ML моделей от Apple
Тулза по конвертации моделей в mlModel
Конвертированные популярные ML модели
Статья Apple по применению сегментированной маски
Статья Apple по загрузки ML модели из сети
Статья по удалению фона с использованием DeeplabV3
python — Как убрать белый фон с картинки?
Что получается = https://i. stack.imgur.com/Vp4ZM.png
Картинка = https://www.flaticon.com/free-icon/volleyball_3231041 Что нужно исправить в этом коде, чтобы убрать белый фон с картинки?.Set_colorkey не убирает белый фон, он остаётся на картинке.
import pygame MAX_X = 1280 MAX_Y = 720 GREEN = (0,250,0) BLACK = (0,0,0) RED = (250,0,0) WHITE = (255,255,255) img = pygame.image.load(r"C:\Картинки\volleyball.png") speed = 3 class Player(pygame.sprite.Sprite): def __init__(self): pygame.sprite.Sprite.__init__(self) self.image = img self.image.set_colorkey(WHITE)!!! self.rect = self.image.get_rect() self.rect.center = (MAX_X / 2, MAX_Y / 2) def update(self): self.rect.x += speed if self.rect.left > MAX_X: self.rect.right = 0 fps = 60 pygame.init() pygame.mixer.init() screen = pygame.display.set_mode((MAX_X,MAX_Y)) pygame.display.set_caption('PyGame!') clock = pygame.time.Clock() all_sprites = pygame.sprite.Group() player = Player() all_sprites.add(player) while True: screen.fill(BLACK) for event in pygame.event.get(): if event.type == pygame.KEYDOWN: if event.key == pygame.K_ESCAPE: pygame.quit() quit() clock.tick(fps) all_sprites.update() all_sprites.draw(screen) pygame.display.flip()
- python
- pygame
- png
3
вы как-то не правильно сохранили картинку.
import pygame MAX_X = 1280 MAX_Y = 720 GREEN = (0,250,0) BLACK = (0,0,0) RED = (250,0,0) WHITE = (255,255,255) img = pygame.image.load("volleyball.png") # !!! speed = 3 class Player(pygame.sprite.Sprite): def __init__(self): pygame.sprite.Sprite.__init__(self) self.image = img self.image.set_colorkey(WHITE) self.rect = self.image.get_rect() self.rect.center = (MAX_X / 2, MAX_Y / 2) def update(self): self. rect.x += speed if self.rect.left > MAX_X: self.rect.right = 0 fps = 60 pygame.init() pygame.mixer.init() screen = pygame.display.set_mode((MAX_X,MAX_Y)) pygame.display.set_caption('PyGame!') clock = pygame.time.Clock() all_sprites = pygame.sprite.Group() player = Player() all_sprites.add(player) while True: screen.fill(BLACK) for event in pygame.event.get(): if event.type == pygame.KEYDOWN: if event.key == pygame.K_ESCAPE: pygame.quit() quit() clock.tick(fps) all_sprites.update() all_sprites.draw(screen) pygame.display.flip()
4
Зарегистрируйтесь или войдите
Регистрация через Google
Регистрация через Facebook
Регистрация через почту
Отправить без регистрации
Почта
Необходима, но никому не показывается
Отправить без регистрации
Почта
Необходима, но никому не показывается
Нажимая на кнопку «Отправить ответ», вы соглашаетесь с нашими пользовательским соглашением, политикой конфиденциальности и политикой о куки
Как удалить фон с изображения в iOS 16
- Вы можете удалить фон практически с любого изображения на вашем iPhone, если у вас iOS 16 или новее.
- Нажмите и удерживайте объект изображения, а затем скопируйте или поделитесь им.
- Если вы хотите сохранить тему, вставьте ее в сообщение, а затем сохраните.
В течение многих лет, если вы хотели удалить фон фотографии, чтобы изолировать объект, вам нужно было тщательно редактировать фотографию в программе редактирования, такой как Photoshop, применяя навыки редактирования фотографий с помощью набора инструментов выбора. В знак того, насколько умными и мощными стали смартфоны, теперь вы можете делать это автоматически, просто нажав на свой iPhone. Если у вас iOS 16 или более поздняя версия, вы можете просто удалить фон с изображения и вставить его в другое приложение.
Как удалить фон с изображения в приложении «Фото»
Чтобы удалить фон с изображения на iPhone, начните с поиска изображения, которое хотите отредактировать. Это может быть практически где угодно — в приложении «Фото», изображение, отправленное вам в сообщении, или даже веб-изображение в Safari. Однако процесс удаления фона в Safari немного отличается, поэтому подробности об этом см. в следующем разделе.
Чтобы быть хорошим кандидатом для этой задачи по редактированию фотографий, должно быть достаточно четкое разграничение между объектом и фоном, а фон не должен быть слишком визуально занят или похож на объект. Однако ваш iPhone сделает все возможное, и с некоторой практикой вы поймете, какие фотографии работают лучше всего.
Подсказка: Как правило, с фотографии можно удалить только самый крупный и заметный объект.
Нажмите и удерживайте объект. Вы увидите белое мерцание вокруг объекта, а затем всплывающее окно с предложением Копировать или Поделиться . Если этого не произошло, измените положение пальца и повторите попытку. Иногда вам нужно будет попробовать несколько раз, прежде чем вы успешно удалите фон.
Нажмите и удерживайте объект фотографии, и ваш iPhone автоматически отделит его от фона. Дэйв Джонсон/ИнсайдерНажмите Скопируйте или Поделитесь . Если вы нажмете «Копировать», вы можете перейти в другое приложение и вставить его. Если вы решите поделиться им, вы увидите все обычные параметры «Поделиться».
Когда вы вставляете полученное изображение, вы получаете объект сам по себе на пустом фоне. Дэйв Джонсон/ИнсайдерКак удалить фон с изображения в Safari
Если вы хотите попробовать этот эффект на изображении на веб-странице, нажмите и удерживайте изображение в Safari. Вместо мерцания, за которым следует всплывающее меню «Копировать и поделиться», вы увидите всплывающее меню с дополнительными параметрами. Выберите Скопировать тему , а затем вы можете вставить ее в другое приложение.
Выберите «Копировать тему», чтобы удалить фон с веб-изображения. Дэйв Джонсон/ИнсайдерКак сохранить изображение, которое вы удалили из фона
Ваш iPhone напрямую не дает вам возможность сохранить объект, который вы вырезали из фона, но вы можете сделать это довольно легко. Скопировав тему в буфер обмена iPhone, запустите приложение «Сообщения», вставьте тему в беседу и отправьте ее. Затем нажмите и удерживайте отправленное изображение. Во всплывающем меню выберите Сохранить . Изображение будет сохранено в вашей фотопленке.
После вставки и отправки изображения в сообщениях вы можете сохранить его в фотопленку. Дэйв Джонсон/ИнсайдерДэйв Джонсон
Внештатный писатель
Дэйв Джонсон — технический журналист, который пишет о потребительских технологиях и о том, как индустрия трансформирует спекулятивный мир научной фантастики в современную реальную жизнь. Дэйв вырос в Нью-Джерси, прежде чем поступить в ВВС, чтобы управлять спутниками, преподавать космические операции и планировать космические запуски. Затем он провел восемь лет в качестве руководителя отдела контента в группе Windows в Microsoft. Как фотограф Дэйв фотографировал волков в их естественной среде обитания; он также инструктор по подводному плаванию и соведущий нескольких подкастов. Дэйв является автором более двух десятков книг и участвовал во многих сайтах и публикациях, включая CNET, Forbes, PC World, How To Geek и Insider.
ПодробнееПодробнее
Бесплатный редактор изображений для профиля — создайте потрясающий PFP онлайн
Что означает «ПФП»?
PFP — это аббревиатура от изображения профиля. У него есть и другие значения, однако в последние годы аватарка стала более распространенной. Аббревиатура быстро прижилась во всех социальных сетях и мессенджерах, во всех группах пользователей. Таким образом, сегодня это в основном связано с аватаркой или, другими словами, с аватаркой.
ЧИТАТЬ ДАЛЕЕ →
Зачем использовать PFPMaker?
Удаление фона AI
Автоматически удаляйте любой фон с вашей фотографии или пользовательского изображения.
Мгновенно сгенерированные
изображений профиля
Получите десятки потрясающих дизайнов аватарок за считанные секунды. Редактировать цвета, тени и другие настройки
Получите больше просмотров, лайков
и сообщения
Загрузите новое изображение профиля и подходящую фоновую обложку, готовые для использования в социальных сетях, мессенджерах или электронной почте.
Профили с фотографией профиля получают в 14 раз больше просмотров, чем без фото профиля.
Более того, с профессиональной фотографией в профиле у вас в 36 раз больше шансов получить сообщение.Как это работает
1
Загрузить фото
Загрузите свою фотографию, свою собаку или любое другое изображение, которое вы можете найти в Интернете. Поддерживаются JPG/PNG размером до 5 МБ.
Для лучшего результата используйте полный хедшот, т.е. не обрезанный границами снимка.
2
Фон удаляется автоматически
Мы используем искусственный интеллект для определения и автоматического удаления фона любой сложности
3
Просмотрите и настройте десятки профессионально созданных фотографий профиля.
Мгновенно получайте десятки идеальных профессионально выглядящих фотографий профиля. Используйте инструменты редактирования, чтобы настроить результат: измените размер фотографии, измените положение и цвета, а также отрегулируйте тени. PFPMaker также создаст соответствующую фоновую обложку.
Еще аватарки?
FAQ
Можно фон убрать поточнее?
Мы работаем над улучшением нашего средства удаления фона. Тем не менее, лучших результатов обработки можно добиться, загрузив более качественную, контрастную фотографию себя с хорошим освещением и убедившись, что ваш снимок не обрезан границами изображения, например. полностью видно
Где можно использовать созданные фотографии профиля?
В основном люди используют их в качестве аватарок в соцсетях, изображений для чата в мессенджерах, фотографий для подписи в электронной почте или резюме/резюме, приложений для знакомств и многими другими способами 🙂
Как можно использовать сгенерированные аватарки?
Вы можете использовать их любым способом, если это не нарушает наше соглашение об использовании. А именно, вы не можете использовать наши фотографии для ведения какой-либо незаконной деятельности
Что происходит с моей фотографией после загрузки?
Мы обрабатываем его на нашем сервере, чтобы удалить только фон.