Захват увеличенного предварительного просмотра в AVFoundation - PullRequest
9 голосов
/ 16 ноября 2011

Я работаю с функцией масштабирования в камере AVFoundation, я реализовал масштабирование путем масштабирования вида с AVCaptureVideoPreviewLayer. Теперь я хочу захватить увеличенное изображение.

вот мой код для добавления AVFoundationVideoPreviewLayer для просмотра:

 // create a uiview subclass for showing the camera feed
 UIView *previewView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 430)];
 [[self view] addSubview:previewView];

 CGRect layerRect = CGRectMake(0, 0, 320, 430);
 [[self avCaptureVideoPreviewLayer] setBounds:layerRect];

 [[self  previewLayer] setPosition:CGPointMake(CGRectGetMidX(layerRect), CGRectGetMidY(layerRect))];

 // add the video previewview layer to the preview view
 [[previewView layer] addSublayer:[self avCaptureVideoPreviewLayer]];

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

  // zoom the preview view using core graphics
 [previewView setTransform:CGAffineTransformMakeScale(2.0, 2.0 )];

Теперь я хочу захватить увеличенное изображение из предварительного просмотра.

Заранее спасибо.

Ответы [ 4 ]

7 голосов
/ 17 ноября 2011

Наконец-то мне удалось добавить снимок в моем приложении. Это немного некрасиво, но это работает. Я использовал UIImage + код изменения размера из сети, а затем масштабировал изображение, чтобы увеличить масштаб, и вычислил положение смещения для увеличенной области [которая видна на виде с камеры], а затем я обрезал его.

Теперь мое приложение иногда падает, когда масштаб увеличения максимальный, т.е. 6x. У меня проблема с памятью, так как увеличенное изображение слишком велико, я задам это как еще один вопрос.

Надеюсь, этот код может быть кому-то полезен.

 if (cameraZoom > 1.0) 
 {
        // save the images original size
        CGSize orgSize = [image size];  

        // resize the image to the zoom scale  
        image = [image resizedImage:CGSizeMake(image.size.width * cameraZoom, image.size.height *cameraZoom) interpolationQuality:kCGInterpolationNone];           

        // now calculate the offset x and offset y
        CGFloat offsetX = ( image.size.width / 2 ) - (orgSize.width /2) ;
        CGFloat offsetY =  ( image.size.height / 2 ) - (orgSize.height /2);

         // crop the image from the offset position to the original width and height
         image = [image croppedImage:CGRectMake(offsetX, offsetY, orgSize.width, orgSize.height)];
    }


    UIButton *imgBtn = (UIButton *)[self.view viewWithTag:500];
    [imgBtn setImage:image forState:UIControlStateNormal];
4 голосов
/ 25 февраля 2014

Я устанавливаю масштаб изображения и обрезаю напрямую с помощью:

AVCaptureConnection *stillImageConnection = [_stillImageOutput.connections objectAtIndex:0];
[stillImageConnection setVideoScaleAndCropFactor:imagePreviewScale];

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

2 голосов
/ 07 декабря 2012

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

То, что вы делаете сейчас, выглядит так: изображение 600X600 станет 3600X3600 при 6x, затем вы обрежете его, что даст600X600 снова.Но почему бы вам не попробовать 600X600 с кадрированием 6x, то получится 100X100, а затем снова изменить его размер до 600X600.

Возможно, что при низком исходном разрешении выходное изображение обоих процессов будет немного отличаться, но если исходное разрешениезначение 8MP / 5MP / 3MP (самое высокое в 5 / 4s / 4 / 3G), тогда выходной сигнал будет почти одинаковым.

Таким образом, чтобы получить лучший результат, используйте процесс, когда низкое разрешение, и для высокого разрешения используйте обратное.что я предложил выше.

0 голосов
/ 01 июня 2013

Мне удалось сначала выполнить кадрирование, а затем масштабирование с использованием базовых преобразований графического изображения.Обратите внимание, что мы сохраняем исходный размер и масштаб изображения в буфере изображения и полностью выполняем функцию масштабирования с операциями преобразования отдельных пикселей.Обратите внимание, что этот код не учитывает ориентацию устройства (в моем случае в настоящее время я использую только вертикальный портрет), но его можно легко выполнить с помощью дополнительного преобразования вращения:

UIGraphicsBeginImageContextWithOptions(imageSize,NO,1.0); // this will crop

CGContextRef context = UIGraphicsGetCurrentContext();


CGRect newRect = CGRectMake(0, 0, width, height);

// apply a scaling transform to zoom
// rotate about the center
// First we scale, then rotate, then translate
// actual matrix multiplication steps are applied in reverse when using
// right-handed coordinate system
// M' = M * translatation * rotation * scale
CGContextTranslateCTM(context, (width - scaledWidth)*0.5f,
                               (height-scaledHeight)*0.5f);
CGContextScaleCTM(context,scaleFactor,scaleFactor);

[sourceImage drawInRect:newRect];

newImage = UIGraphicsGetImageFromCurrentImageContext();
if (newImage == nil) {
    NSLog(@"could not scale image");
}

// pop the context to get back to the default
UIGraphicsEndImageContext();
...