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];
Merci beaucoup. Cela a résolu le problème. –
Incroyable! Merci Monsieur! –