gpt4 book ai didi

ios - 如何在不转换为 UIImage 的情况下在 IOS 4 中直接旋转 CVImageBuffer 图像?

转载 作者:技术小花猫 更新时间:2023-10-29 10:43:26 27 4
gpt4 key购买 nike

我在 iPhone 上使用 OpenCV 2.2 检测人脸。我正在使用 IOS 4 的 AVCaptureSession 来访问相机流,如以下代码所示。

我的挑战是视频帧以 CVBufferRef(指向 CVImageBuffer 的指针)对象的形式出现,并且它们以风景的形式出现,宽 480 像素,高 300 像素。如果您将手机横向放置,这很好,但是当手机处于直立位置时,我想将这些框架顺时针旋转 90 度,以便 OpenCV 可以正确找到人脸。

可以将 CVBufferRef 转换为 CGImage,然后转换为 UIImage,然后旋转,就像这个人所做的那样:Rotate CGImage taken from video frame

然而,这会浪费大量的 CPU。我正在寻找一种更快的方法来旋转传入的图像,如果可能的话最好使用 GPU 来执行此处理。

有什么想法吗?

伊恩

代码示例:

 -(void) startCameraCapture {
// Start up the face detector

faceDetector = [[FaceDetector alloc] initWithCascade:@"haarcascade_frontalface_alt2" withFileExtension:@"xml"];

// Create the AVCapture Session
session = [[AVCaptureSession alloc] init];

// create a preview layer to show the output from the camera
AVCaptureVideoPreviewLayer *previewLayer = [AVCaptureVideoPreviewLayer layerWithSession:session];
previewLayer.frame = previewView.frame;
previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;

[previewView.layer addSublayer:previewLayer];

// Get the default camera device
AVCaptureDevice* camera = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];

// Create a AVCaptureInput with the camera device
NSError *error=nil;
AVCaptureInput* cameraInput = [[AVCaptureDeviceInput alloc] initWithDevice:camera error:&error];
if (cameraInput == nil) {
NSLog(@"Error to create camera capture:%@",error);
}

// Set the output
AVCaptureVideoDataOutput* videoOutput = [[AVCaptureVideoDataOutput alloc] init];
videoOutput.alwaysDiscardsLateVideoFrames = YES;

// create a queue besides the main thread queue to run the capture on
dispatch_queue_t captureQueue = dispatch_queue_create("catpureQueue", NULL);

// setup our delegate
[videoOutput setSampleBufferDelegate:self queue:captureQueue];

// release the queue. I still don't entirely understand why we're releasing it here,
// but the code examples I've found indicate this is the right thing. Hmm...
dispatch_release(captureQueue);

// configure the pixel format
videoOutput.videoSettings = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithUnsignedInt:kCVPixelFormatType_32BGRA],
(id)kCVPixelBufferPixelFormatTypeKey,
nil];

// and the size of the frames we want
// try AVCaptureSessionPresetLow if this is too slow...
[session setSessionPreset:AVCaptureSessionPresetMedium];

// If you wish to cap the frame rate to a known value, such as 10 fps, set
// minFrameDuration.
videoOutput.minFrameDuration = CMTimeMake(1, 10);

// Add the input and output
[session addInput:cameraInput];
[session addOutput:videoOutput];

// Start the session
[session startRunning];
}

- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection {
// only run if we're not already processing an image
if (!faceDetector.imageNeedsProcessing) {

// Get CVImage from sample buffer
CVImageBufferRef cvImage = CMSampleBufferGetImageBuffer(sampleBuffer);

// Send the CVImage to the FaceDetector for later processing
[faceDetector setImageFromCVPixelBufferRef:cvImage];

// Trigger the image processing on the main thread
[self performSelectorOnMainThread:@selector(processImage) withObject:nil waitUntilDone:NO];
}
}

最佳答案

vImage 是一种非常快速的方法。虽然需要 ios5。该调用显示 ARGB,但它适用于您从缓冲区获得的 BGRA。

这还有一个好处,就是你可以切出缓冲区的一部分并旋转它。 See my answer here

- (unsigned char*) rotateBuffer: (CMSampleBufferRef) sampleBuffer
{
CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
CVPixelBufferLockBaseAddress(imageBuffer,0);

size_t bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer);
size_t width = CVPixelBufferGetWidth(imageBuffer);
size_t height = CVPixelBufferGetHeight(imageBuffer);
size_t currSize = bytesPerRow*height*sizeof(unsigned char);
size_t bytesPerRowOut = 4*height*sizeof(unsigned char);

void *srcBuff = CVPixelBufferGetBaseAddress(imageBuffer);
unsigned char *outBuff = (unsigned char*)malloc(currSize);

vImage_Buffer ibuff = { srcBuff, height, width, bytesPerRow};
vImage_Buffer ubuff = { outBuff, width, height, bytesPerRowOut};

uint8_t rotConst = 1; // 0, 1, 2, 3 is equal to 0, 90, 180, 270 degrees rotation

vImage_Error err= vImageRotate90_ARGB8888 (&ibuff, &ubuff, NULL, rotConst, NULL,0);
if (err != kvImageNoError) NSLog(@"%ld", err);

return outBuff;
}

关于ios - 如何在不转换为 UIImage 的情况下在 IOS 4 中直接旋转 CVImageBuffer 图像?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4528879/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com