2013-03-06 2 views
0

J'utilise AVFoundation pour capturer des images vidéo, traiter avec opencv et afficher le résultat dans un UIImageView sur le nouvel iPad. Le processus de OpenCV fait les Suiveurs (« inImg » est la trame vidéo):cv :: Mat ne correspond pas à UIImageView width?

cv::Mat testROI = inImg.rowRange(0,100); 
testROI = testROI.colRange(0,10); 
testROI.setTo(255); // this is a BGRA frame. 

Cependant, au lieu d'obtenir une barre blanche verticale (100 rangée x 10 col) dans le coin supérieur gauche du cadre, je me suis 100 lignes horizontales en escalier, du coin supérieur droit au coin inférieur gauche, chacune avec une longueur de 10 pixels. Après quelques recherches, j'ai réalisé que la largeur de l'image affichée était de 8 pixels plus large que le cv :: Mat. (c'est-à-dire que le 9ème pixel de la 2ème rangée est juste en dessous du 1er pixel de la 1ère rangée.).

L'image vidéo elle-même est affichée correctement (pas de déplacement entre les lignes). Le problème apparaît lorsque AVCaptureSession.sessionPreset est AVCaptureSessionPresetMedium (frame rows = 480, cols = 360) mais n'apparaît pas lorsqu'il s'agit de AVCaptureSessionPresetHigh (frame rows = 640, cols = 480).

Il y a 360 colonnes affichées en plein écran. (J'ai essayé de traverser et de modifier le pixel par pixel cv :: Mat. Les pixels 1-360 ont été affichés correctement, 361-368 ont disparu et 369 a été affiché juste sous le pixel 1).

J'ai essayé des combinaisons de imageview.contentMode (UIViewContentModeScaleAspectFill et UIViewContentModeScaleAspectFit) et imageview.clipsToBound (YES/NO) mais pas de chance.

Quel pourrait être le problème? Merci beaucoup.

J'utilise le code suivant pour créer le AVCaptureSession:

NSArray* devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo]; 

if ([devices count] == 0) { 
    NSLog(@"No video capture devices found"); 
    return NO; 
} 


for (AVCaptureDevice *device in devices) { 
    if ([device position] == AVCaptureDevicePositionFront) { 
      _captureDevice = device; 
    } 
} 


NSError* error_exp = nil; 
if ([_captureDevice lockForConfiguration:&error_exp]) { 
    [_captureDevice setWhiteBalanceMode:AVCaptureWhiteBalanceModeContinuousAutoWhiteBalance]; 
    [_captureDevice unlockForConfiguration]; 
} 
// Create the capture session 
_captureSession = [[AVCaptureSession alloc] init]; 
_captureSession.sessionPreset = AVCaptureSessionPresetMedium; 


// Create device input 
NSError *error = nil; 
AVCaptureDeviceInput *input = [[AVCaptureDeviceInput alloc] initWithDevice:_captureDevice error:&error]; 

// Create and configure device output 
_videoOutput = [[AVCaptureVideoDataOutput alloc] init]; 

dispatch_queue_t queue = dispatch_queue_create("cameraQueue", NULL); 
[_videoOutput setSampleBufferDelegate:self queue:queue]; 
dispatch_release(queue); 

_videoOutput.alwaysDiscardsLateVideoFrames = YES; 

OSType format = kCVPixelFormatType_32BGRA; 

_videoOutput.videoSettings = [NSDictionary dictionaryWithObject:[NSNumber numberWithUnsignedInt:format]forKey:(id)kCVPixelBufferPixelFormatTypeKey]; 


// Connect up inputs and outputs 
if ([_captureSession canAddInput:input]) { 
    [_captureSession addInput:input]; 
} 

if ([_captureSession canAddOutput:_videoOutput]) { 
    [_captureSession addOutput:_videoOutput]; 
} 

AVCaptureConnection * captureConnection = [_videoOutput connectionWithMediaType:AVMediaTypeVideo]; 

if (captureConnection.isVideoMinFrameDurationSupported) 
    captureConnection.videoMinFrameDuration = CMTimeMake(1, 60); 
if (captureConnection.isVideoMaxFrameDurationSupported) 
    captureConnection.videoMaxFrameDuration = CMTimeMake(1, 60); 

if (captureConnection.supportsVideoMirroring) 
    [captureConnection setVideoMirrored:NO]; 

[captureConnection setVideoOrientation:AVCaptureVideoOrientationPortraitUpsideDown]; 

Lorsqu'une trame est reçue, ce qui suit est appelé:

- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection 
{ 
@autoreleasepool { 

    CVPixelBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer); 
    OSType format = CVPixelBufferGetPixelFormatType(pixelBuffer); 
    CGRect videoRect = CGRectMake(0.0f, 0.0f, CVPixelBufferGetWidth(pixelBuffer), CVPixelBufferGetHeight(pixelBuffer)); 

    AVCaptureConnection *currentConnection = [[_videoOutput connections] objectAtIndex:0]; 

    AVCaptureVideoOrientation videoOrientation = [currentConnection videoOrientation]; 
    CGImageRef quartzImage; 

    // For color mode a 4-channel cv::Mat is created from the BGRA data 
    CVPixelBufferLockBaseAddress(pixelBuffer, 0); 
    void *baseaddress = CVPixelBufferGetBaseAddress(pixelBuffer); 

    cv::Mat mat(videoRect.size.height, videoRect.size.width, CV_8UC4, baseaddress, 0); 

    if ([self doFrame]) { // a flag to switch processing ON/OFF 
      [self processFrame:mat videoRect:videoRect videoOrientation:videoOrientation]; // "processFrame" is the opencv function shown above 
    } 

    CIImage *ciImage = [CIImage imageWithCVPixelBuffer:pixelBuffer]; 
    quartzImage = [self.context createCGImage:ciImage fromRect:ciImage.extent]; 
    CVPixelBufferUnlockBaseAddress(pixelBuffer, 0); 

    UIImage *image = [UIImage imageWithCGImage:quartzImage scale:1.0 orientation:UIImageOrientationUp]; 

    CGImageRelease(quartzImage); 

    [self.imageView performSelectorOnMainThread:@selector(setImage:) withObject:image waitUntilDone:YES]; 

Répondre

1

Je suppose que vous utilisez le constructeur Mat(int _rows, int _cols, int _type, void* _data, size_t _step=AUTO_STEP) et que AUTO_STEP est 0 et suppose que la foulée de ligne est width*bytesPerPixel.

Ceci est généralement faux — c'est très commun d'aligner des lignes à une limite plus grande. Dans ce cas, 360 n'est pas un multiple de 16 mais 368 est; ce qui suggère fortement qu'il s'aligne sur des limites de 16 pixels (peut-être pour aider les algorithmes qui traitent 16 blocs 16?).

Essayez

cv::Mat mat(videoRect.size.height, videoRect.size.width, CV_8UC4, baseaddress, CVPixelBufferGetBytesPerRow(pixelBuffer)); 
+0

Merci beaucoup. Cela a résolu le problème. –

+0

Incroyable! Merci Monsieur! –

Questions connexes