Получить передний план от AdobeLabsUXMagicSelectionView (Adobe Creative SDK)

Я пытаюсь использовать AdobeLabsUXMagicSelectionView и сталкиваюсь с двумя проблемами. Я хочу "вырезать" выделенную область (передний план), используя эти 2 метода:

Способ 1) getForeground:andMatte: Это не дает мне правильный передний план. Когда я выбираю область и звоню getForeground:andMatte Я даю мне передний план и задний план (смешанный).

Выбор лица собаки введите описание изображения здесь

Стричь собачье лицо введите описание изображения здесь

Документация гласит:

В качестве альтернативы, если вам не нужно напрямую обрабатывать базовое растровое изображение и намереваться использовать результаты в качестве входных данных для CoreGraphics или CoreImage, вы можете вызвать:

Способ 2) После этого я пытаюсь "вырезать", как это делает документация

extension AdobeLabsUXMagicSelectionView {

    func foregroundCGImage() -> CGImage {
        let w = size_t(self.image.size.width)
        let h = size_t(self.image.size.height)
        let data = UnsafeMutablePointer<UInt8>(malloc(4 * w * h * sizeof(UInt8)))
        self.readForegroundAndMatteIntoBuffer(data)

        for var i = 0; i < 4 * w * h; i += 4 {
            let alpha: UInt8 = UInt8(data[i + 3]) / 255
            data[i] *= alpha
            data[i + 1] *= alpha
            data[i + 2] *= alpha
        }

        let bitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.NoneSkipLast.rawValue)
        let ctx = CGBitmapContextCreate(data, w, h, 8, 4 * w, CGColorSpaceCreateDeviceRGB(), bitmapInfo.rawValue)
        let imageRef = CGBitmapContextCreateImage(ctx)!

        return imageRef
    }

}

Но он только закрашивает (черный) невыбранную часть (фон) изображения.

Кто-нибудь может помочь? Я хочу получить окончательное изображение выбранной области.

ОБНОВИТЬ:

Как сказал @DonWoodward, я создал эту категорию:

@implementation AdobeLabsUXMagicSelectionView (Foreground)

- (UIImage *)getForeground {
    // show the results
    // first create a UIImage of just the foreground bits per the documentation in AdobeLabsUXMagicSelectionView.h
    size_t w = self.image.size.width;
    size_t h = self.image.size.height;

    uint8_t *data = (uint8_t *)malloc(4*w*h*sizeof(uint8_t));
    [self readForegroundAndMatteIntoBuffer:data];

    // Paint the non-selected portion of the image black
    for (int i = 0; i < 4*w*h; i += 4) {
        float alpha = (float)data[i + 3] / 255;
        data[i    ] *= alpha;
        data[i + 1] *= alpha;
        data[i + 2] *= alpha;
    }
    CGContextRef ctx = CGBitmapContextCreate(data, w, h, 8, 4*w, CGColorSpaceCreateDeviceRGB(), (CGBitmapInfo)kCGImageAlphaNoneSkipLast);
    CGImageRef imageRef = CGBitmapContextCreateImage(ctx);
    UIImage * foregroundBits = [UIImage imageWithCGImage:imageRef];
    CGImageRelease(imageRef);

    return foregroundBits;
}

@end

Но результат имеет много черного пикселя вокруг "переднего плана".

введите описание изображения здесь введите описание изображения здесь

Что мне нужно? Получить "чистый" передний план (выделенная область без черных пикселей), чтобы поместить поверх UIImageView

2 ответа

Решение

В этом случае вы предварительно умножаете каналы RGB на ваш альфа-канал, что подразумевает, что вы захотите использовать kCGImageAlphaPremultipliedLast при создании вашего контекста, как в:

// Paint the non-selected portion of the image black
for (int i = 0; i < 4*w*h; i += 4)
{
    float alpha = (float)data[i + 3] / 255;
    data[i    ] *= alpha;
    data[i + 1] *= alpha;
    data[i + 2] *= alpha;
}
CGContextRef ctx = CGBitmapContextCreate(data, w, h, 8, 4*w, CGColorSpaceCreateDeviceRGB(), (CGBitmapInfo)kCGImageAlphaPremultipliedLast);
CGImageRef imageRef = CGBitmapContextCreateImage(ctx);
UIImage * foregroundBits = [UIImage imageWithCGImage:imageRef];
CGImageRelease(imageRef);

Более подробную информацию можно найти в документации CGImage

Кроме того, вы также можете попробовать использовать CGImageCreateWithMask с выходом

- (void)getForeground:(UIImage **)foregroundImage andMatte:(UIImage **)matteImage

как описано в Руководстве по программированию Quartz 2D

UIImage *fg;
UIImage *matte;

[_magicSelectionView getForeground:&fg andMatte:&matte];

CGImageRef mattedForeground = CGImageCreateWithMask(fg.CGImage, matte.CGImage);
UIImage *foregroundBits = [UIImage imageWithCGImage:mattedForeground];

// show the results
_resultsView = [[UIImageView alloc] initWithFrame: CGRectMake(0, VIEW_Y_OFFSET, self.view.bounds.size.width, self.view.bounds.size.height-VIEW_Y_OFFSET)];
_resultsView.contentMode = UIViewContentModeScaleAspectFit;
[_resultsView setImage: foregroundBits];
[self.view addSubview: _resultsView];

Если ни один из этих способов не работает, возможно, возникли некоторые проблемы с настройкой UIImageViews используется для визуализации результатов, но без этого кода трудно сказать.

Я думаю, что проблема в том, что ваш масштабный фактор имеет тип uint8_t и поэтому вы обрезаете масштабный коэффициент до нуля. Сделайте это поплавком, и это должно работать. Вот код из MagicPuppy (в цели c), который делает это:

    // show the results
    // first create a UIImage of just the foreground bits per the documentation in AdobeLabsUXMagicSelectionView.h
    size_t w = _magicSelectionView.image.size.width;
    size_t h = _magicSelectionView.image.size.height;

    uint8_t *data = (uint8_t *)malloc(4*w*h*sizeof(uint8_t));
    [_magicSelectionView readForegroundAndMatteIntoBuffer:data];

    // Paint the non-selected portion of the image black
    for (int i = 0; i < 4*w*h; i += 4)
    {
        float alpha = (float)data[i + 3] / 255;
        data[i    ] *= alpha;
        data[i + 1] *= alpha;
        data[i + 2] *= alpha;
    }
    CGContextRef ctx = CGBitmapContextCreate(data, w, h, 8, 4*w, CGColorSpaceCreateDeviceRGB(), (CGBitmapInfo)kCGImageAlphaNoneSkipLast);
    CGImageRef imageRef = CGBitmapContextCreateImage(ctx);
    UIImage * foregroundBits = [UIImage imageWithCGImage:imageRef];
    CGImageRelease(imageRef);

    // show the results
    _resultsView = [[UIImageView alloc] initWithFrame: CGRectMake(0, VIEW_Y_OFFSET, self.view.bounds.size.width, self.view.bounds.size.height-VIEW_Y_OFFSET)];
    _resultsView.contentMode = UIViewContentModeScaleAspectFit;
    [_resultsView setImage: foregroundBits];
    [self.view addSubview: _resultsView];
Другие вопросы по тегам