Nano Hash - криптовалюты, майнинг, программирование

Как сфокусировать ближние объекты в iOS 8?

Я разрабатываю считыватель QR-кода. Мои коды имеют длину и ширину 1 см. Я использую метаданные AVFoundation для захвата машиночитаемых кодов, и все работает нормально. Но при этом мне нужно сфотографировать QR-код с логотипом (который находится посередине QR-кода). Поэтому я использую AVCaptureVideoDataOutput и didOutputSampleBuffer для получения неподвижных изображений. Проблема заключается в четкости изображения. он всегда выглядит размытым по краям кодов и логотипа. Поэтому я провел исследование ручного управления и внес некоторые изменения в код для ручной фокусировки, но до сих пор безуспешно.


  1. Как сфокусировать (находящийся в 10см от камеры и крошечный) близлежащие объекты?
  2. Есть ли у нас другой способ получить изображение после успешного сканирования из метаданных?
  3. В чем разница между setFocusModeLockedWithLensPosition и focusPointOfInterest ?

Вот мой код (часть его)

   // Create and configure a capture session and start it running
- (void)setupCaptureSession
{
    NSError *error = nil;

    // Create the session
    _session = [[AVCaptureSession alloc] init];

    // Configure the session to produce lower resolution video frames, if your
    // processing algorithm can cope. We'll specify medium quality for the
    // chosen device.
    _session.sessionPreset = AVCaptureSessionPresetHigh;

    // Find a suitable AVCaptureDevice
    _device = [AVCaptureDevice
                               defaultDeviceWithMediaType:AVMediaTypeVideo];
    if ([_device lockForConfiguration:&error]) {
        [_device setAutoFocusRangeRestriction:AVCaptureAutoFocusRangeRestrictionNone];
        [_device setFocusModeLockedWithLensPosition:0.5 completionHandler:nil];
        //[device setFocusMode:AVCaptureFocusModeAutoFocus];
       // _device.focusPointOfInterest = CGPointMake(0.5,0.5);
       // device.videoZoomFactor = 1.0 + 10;
        [_device unlockForConfiguration];
    }

//    if ([_device isSmoothAutoFocusEnabled])
//    {
//        _device.smoothAutoFocusEnabled = NO;
//    }
    // Create a device input with the device and add it to the session.
    AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:_device
                                                                        error:&error];
    if (!input) {
        // Handling the error appropriately.
    }
    [_session addInput:input];

    // For scanning QR code
    AVCaptureMetadataOutput *metaDataOutput = [[AVCaptureMetadataOutput alloc] init];
    // Have to add the output before setting metadata types
    [_session addOutput:metaDataOutput];
    [metaDataOutput setMetadataObjectTypes:@[AVMetadataObjectTypeQRCode]];
    [metaDataOutput setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];

    //For saving the image to camera roll
    _stillImageOutput = [[AVCaptureStillImageOutput alloc] init];
    NSDictionary *outputSettings = [[NSDictionary alloc] initWithObjectsAndKeys: AVVideoCodecJPEG, AVVideoCodecKey, nil];
    [_stillImageOutput setOutputSettings:outputSettings];
    [_session addOutput:_stillImageOutput];

    // Create a VideoDataOutput and add it to the session
    AVCaptureVideoDataOutput *output = [[AVCaptureVideoDataOutput alloc] init];
    [_session addOutput:output];

    // Configure your output.
    dispatch_queue_t queue = dispatch_queue_create("myQueue", NULL);
    [output setSampleBufferDelegate:self queue:queue];

    // Specify the pixel format
    output.videoSettings =
    [NSDictionary dictionaryWithObject:
     [NSNumber numberWithInt:kCVPixelFormatType_32BGRA]
                                forKey:(id)kCVPixelBufferPixelFormatTypeKey];


    // Start the session running to start the flow of data
    [self startCapturingWithSession:_session];

    // Assign session to an ivar.
    [self setSession:_session];
}

- (void)startCapturingWithSession: (AVCaptureSession *) captureSession
{
    NSLog(@"Adding video preview layer");
    [self setPreviewLayer:[[AVCaptureVideoPreviewLayer alloc] initWithSession:captureSession]];

    [self.previewLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill];


    //----- DISPLAY THE PREVIEW LAYER -----
    //Display it full screen under out view controller existing controls
    NSLog(@"Display the preview layer");
    CGRect layerRect = [[[self view] layer] bounds];
    [self.previewLayer setBounds:layerRect];
    [self.previewLayer setPosition:CGPointMake(CGRectGetMidX(layerRect),
                                               CGRectGetMidY(layerRect))];
    [self.previewLayer setAffineTransform:CGAffineTransformMakeScale(3.5, 3.5)];

    //[[[self view] layer] addSublayer:[[self CaptureManager] self.previewLayer]];
    //We use this instead so it goes on a layer behind our UI controls (avoids us having to manually bring each control to the front):
    UIView *CameraView = [[UIView alloc] init];
    [[self view] addSubview:CameraView];
    [self.view sendSubviewToBack:CameraView];

    [[CameraView layer] addSublayer:self.previewLayer];


    //----- START THE CAPTURE SESSION RUNNING -----
    [captureSession startRunning];
    [self switchONFlashLight];
}

// Delegate routine that is called when a sample buffer was written
- (void)captureOutput:(AVCaptureOutput *)captureOutput
didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer
       fromConnection:(AVCaptureConnection *)connection
{
    // Create a UIImage from the sample buffer data
    [connection setVideoOrientation:AVCaptureVideoOrientationLandscapeLeft];
    UIImage *image = [self imageFromSampleBuffer:sampleBuffer];
}
/ Create a UIImage from sample buffer data
- (UIImage *) imageFromSampleBuffer:(CMSampleBufferRef) sampleBuffer
{
    // Get a CMSampleBuffer's Core Video image buffer for the media data
    CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
    // Lock the base address of the pixel buffer
    CVPixelBufferLockBaseAddress(imageBuffer, 0);

    // Get the number of bytes per row for the pixel buffer
    void *baseAddress = CVPixelBufferGetBaseAddress(imageBuffer);

    // Get the number of bytes per row for the pixel buffer
    size_t bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer);
    // Get the pixel buffer width and height
    size_t width = CVPixelBufferGetWidth(imageBuffer);
    size_t height = CVPixelBufferGetHeight(imageBuffer);

    // Create a device-dependent RGB color space
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();

    // Create a bitmap graphics context with the sample buffer data
    CGContextRef context = CGBitmapContextCreate(baseAddress, width, height, 8,
                                                 bytesPerRow, colorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst);
    // Create a Quartz image from the pixel data in the bitmap graphics context
    CGImageRef quartzImage = CGBitmapContextCreateImage(context);
    // Unlock the pixel buffer
    CVPixelBufferUnlockBaseAddress(imageBuffer,0);

    // Free up the context and color space
    CGContextRelease(context);
    CGColorSpaceRelease(colorSpace);

    // Create an image object from the Quartz image
    UIImage *image = [UIImage imageWithCGImage:quartzImage];

    // Release the Quartz image
    CGImageRelease(quartzImage);

    return (image);
}

-(void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection{
    if (metadataObjects != nil && [metadataObjects count] > 0) {
        AVMetadataMachineReadableCodeObject *metadataObj = [metadataObjects objectAtIndex:0];
//        if ([_device lockForConfiguration:nil]){
//            [_device setAutoFocusRangeRestriction:AVCaptureAutoFocusRangeRestrictionNear];
//            _device.focusPointOfInterest = CGPointMake(metadataObj.bounds.origin.x, metadataObj.bounds.origin.y);
//            [_device unlockForConfiguration];
//        }

        if ([[metadataObj type] isEqualToString:AVMetadataObjectTypeQRCode]) {
            [_lblStatus performSelectorOnMainThread:@selector(setText:) withObject:[metadataObj stringValue] waitUntilDone:NO];
        }
    }    
}

Только для iOS 8 и последних iPhone.


Ответы:


1

After провел регрессивное исследование и получил информацию от фотографов. Делюсь своими ответами с будущими читателями.

  1. Начиная с iOS 8 Apple предоставляет только три режима фокусировки. Которые
typedef NS_ENUM(NSInteger, AVCaptureFocusMode) {
  AVCaptureFocusModeLocked              = 0,
  AVCaptureFocusModeAutoFocus           = 1,
  AVCaptureFocusModeContinuousAutoFocus = 2,
} NS_AVAILABLE(10_7, 4_0);

Чтобы сфокусировать объект, который находится очень близко к линзе, мы можем использовать AVCaptureAutoFocusRangeRestrictionNear

но для меня из-за ограничений по минимальному фокусному расстоянию с камерами iPhone невозможно получить четкое изображение моих кодов.

  1. Насколько я знаю, нет способа получить данные изображения из метаданных. Мой вопрос сам по себе неправильный. но как вы можете получить буферы изображений из видеокадров. проверьте Захват видеокадров как объектов UIImage для получения дополнительной информации.
  2. setFocusModeLockedWithLensPosition заблокирует режим фокусировки и позволит нам установить конкретное положение объектива, которое начинается с 0,0 до 1,0.

focusPointOfInterest не меняйте режим фокусировки, а просто устанавливает точки для фокусировки. Лучшим примером будет нажатие, чтобы сфокусироваться.

30.04.2015
Новые материалы

Кластеризация: более глубокий взгляд
Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

Как написать эффективное резюме
Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

Частный метод Python: улучшение инкапсуляции и безопасности
Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

Как я автоматизирую тестирование с помощью Jest
Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

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

Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..