Created
February 23, 2014 16:10
-
-
Save edom18/9173315 to your computer and use it in GitHub Desktop.
[Objective-C] AVCaptureとvImageを使ってリアルタイムフィルタを作ってみる ref: http://qiita.com/edo_m18/items/727bee5affe6e36d77c2
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#import <Accelerate/Accelerate.h> | |
#import <AVFoundation/AVFoundation.h> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
self.captureSession = [[AVCaptureSession alloc] init]; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
gaussianblur(&inputvImage, &outputvImage); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ビットマップコンテキストの生成 | |
CGBitmapInfo bitmapInfo = kCGBitmapByteOrder32Little | kCGImageAlphaPremultipledFirst; | |
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); | |
CGContextRef cgContext = CGBitmapContextCreate(outputvImage.data, width, height, 8, bytesPerRow, colorSpace, bitmapInfo); | |
// 画像の作成 | |
CGImageRef dstImage = CGBitmapContextCreateImage(cgContext); | |
__typeof(self) __weak wself = self; | |
dispatch_sync(dispatch_get_main_queue(), ^{ | |
wself.previewLayer.contents = (__bredge id)dstImage; | |
}); | |
// 解放処理 | |
free(outBuffer); | |
CGImageRelease(dstImage); | |
CGContextReleaes(cgContext); | |
CGColorSpaceRelease(colorSpace); | |
// バッファのアンロック | |
CVPicelBufferUnlockBaseAddress(imageBufer, 0); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
void gaussianblur(const vImage_Buffer *src, const vImage_Buffer *dst) { | |
const int16_t kernel[] = { | |
1, 4, 6, 4, 1, | |
4, 16, 24, 16, 4, | |
6, 24, 36, 24, 6, | |
4, 16, 24, 16, 4, | |
1, 4, 6, 4, 1 | |
}; | |
int length = sizeof(kernel) / sizeof(int16_t); | |
int32_t divisor = 0; | |
for (int i = 0; i < length; i++) { | |
divisor += kernel[i]; | |
} | |
unsigned int size = sqrt(length); | |
uint32_t kernel_height = size; | |
uint32_t kernel_width = size; | |
vImageConvolve_ARGB8888(src, dst, NULL, 0, 0, kernel, kernel_height, kernel_width, divisor, NULL, kvImageCopyInPlace); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
typedef short int16_t; | |
typedef int int32_t; | |
/* 8 bit planar pixel value */ | |
typedef uint8_t Pixel_8; | |
typedef unsigned char uint8_t; | |
/* ARGB interleaved (8 bit/channel) pixel value. uint8_t[4] = { alpha, red, green, blue } */ | |
typedef uint8_t Pixel_8888[4]; | |
/* Pedantic: A number of pixels. For LP64 (ppc64/x86_64) this is a 64-bit quantity. */ | |
typedef unsigned long vImagePixelCount; | |
typedef struct vImage_Buffer | |
{ | |
void *data; /* Pointer to the top left pixel of the buffer. */ | |
vImagePixelCount height; /* The height (in pixels) of the buffer */ | |
vImagePixelCount width; /* The width (in pixels) of the buffer */ | |
size_t rowBytes; /* The number of bytes in a pixel row, including any unused space between one row and the next. */ | |
} vImage_Buffer; | |
/* Pedantic: A number of pixels. For LP64 (ppc64/x86_64) this is a 64-bit quantity. */ | |
typedef unsigned long vImagePixelCount; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
vImageConvolve_ARGB8888( | |
&src, // const vImage_Buffer *src | |
&dst, // const vImage_Buffer *dest | |
NULL, // void *tempBuffer | |
0, // vImagePixelCount srcOffsetToROI_X | |
0, // vImagePixelCount srcOffsetToROI_Y | |
kernelArray, // const int16_t *kernel | |
3, // uint32_t kernel_height | |
3, // uint32_t kernel_width | |
divisor, // int32_t divisor | |
NULL, // Pixel_8888 backgroundColor | |
kvImageCopyInPlace // vImage_Flags flags | |
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<Error>: CGBitmapContextCreate: invalid data bytes/row: should be at least 1920 for 8 integer bits/component, 3 components, kCGImageAlphaPremultipliedFirst. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 実際に使ってるやつ | |
const size_t bufferSize = CVPixelBufferGetDataSize(imageBuffer); | |
// 以下のように自前で計算してもOK | |
const size_t bufferSize = sizeof(uint8_t) * width * height * 4; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<Error>: CGBitmapContextCreate: invalid data bytes/row: should be at least 1920 for 8 integer bits/component, 3 components, kCGImageAlphaPremultipliedFirst. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 実際に使ってるやつ | |
const size_t bufferSize = CVPixelBufferGetDataSize(imageBuffer); | |
// 以下のように自前で計算してもOK | |
const size_t bufferSize = sizeof(uint8_t) * width * height * 4; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
NSArray *devices = [AVCaptureDevice devices]; | |
AVCaptureDeviceInput *frontInput; | |
AVCaptureDeviceInput *backInput; | |
for (AVCaptureDevice *device in devices) { | |
if ([device hasMediaType:AVMediaTypeVideo]) { | |
NSError *error = nil; | |
if (device.position == AVCaptureDevicePositionFront) { | |
frontInput = [AVCaptureDeviceInput deviceInputWithDevice:device error:&error]; | |
} | |
else { | |
backInput = [AVCaptureDeviceInput deviceInputWithDevice:device error:&error]; | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[self.captureSession addInput:backInput]; | |
NSDictionary *settings; | |
settings = @{(NSString *)kCVPixelBufferPixelFormatTypeKey:@(kCVPixelFormatType_32BGRA)}; | |
self.videoOutput = [[AVCaptureVideoDataOutput alloc] init]; | |
[self.videoOutput setVideoSettings:settings]; | |
[self.videoOutput setAlwaysDiscardsLateVideoFrame:YES]; | |
[self.captureSession addOutput:self.videoOutput]; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// カメラの向きを設定 | |
AVCaptureConnection *videoConnection = nil; | |
[self.captureSession beginConfiguration]; | |
for (AVCaptureConnection *connection in [self.videoOutput connections]) { | |
for (AVCaptureInputPort *port in [connection inputPorts]) { | |
if ([[port mediaType] isEqual:AVMediaTypeVideo]) { | |
videoConnection = connection; | |
} | |
} | |
} | |
if ([videoConnection isVideoOrientationSupported]) { | |
[videoConnection setVideoOrientation:AVCaptureVideoOrientationPortrait]; | |
} | |
[self.captureSession commitConfiguration]; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
dispatch_queue_t queue = dispatch_queue_create("VideoQueue", DISPATCH_QUEUE_SERIAL); | |
[self.videoOutput setSampleBufferDelegate:self queue:queue]; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
self.previewLayer = [AVCaptureVideoPreviewLayer layer]; | |
self.previewLayer.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height); | |
self.previewLayer.position = CGPointMake(self.view.frame.size.width / 2, self.view.frame.size.height / 2); | |
[self.view.layer addSublayer:self.previewLayer]; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer); | |
CVPixelBufferLockBaseAddress(imageBuffer, 0); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
size_t width = CVPixelBufferGetWidth(imageBuffer); | |
size_t height = CVPixelBufferGetHeight(imageBuffer); | |
size_t bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer); | |
const size_t bufferSize = CVPixelBufferGetDataSize(imageBuffer); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 入力用 | |
uint_8 *buffer = (uint8_t *)CVPixelBufferGetBaseAddress(imageBuffer); | |
const vImage_Buffer inputvImage = {buffer, height, width, bytesPerRow}; | |
// 出力用 | |
void *outBuffer = malloc(bufferSize); // 出力用に空のメモリを確保 | |
const vImage_Buffer outputvImage = {outBuffer, height, width, bytesPerRow}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment