iPhoneでカラートラッキングの実験をしました。
下記のページなどを参考にしました。
(当記事は過去に別のブログに投稿したものの再掲です。)
・iOSのカメラ機能を使う方法まとめ【13日目】
#import "ViewController.h" #import "CoreVideo/CoreVideo.h" #import "CoreImage/CoreImage.h" #import "CoreGraphics/CoreGraphics.h" @interface ViewController () @property (strong, nonatomic) AVCaptureDeviceInput *videoInput; @property (strong, nonatomic) AVCaptureVideoDataOutput *videoDataOutput; @property (strong, nonatomic) AVCaptureSession *session; @property (nonatomic, strong) AVCaptureVideoPreviewLayer *previewLayer; @property (nonatomic, strong) CALayer* indicatorLayer; @property (nonatomic, retain) CIDetector* faceDetector; @property (weak, nonatomic) IBOutlet UIImageView *previewImageView; @end @implementation ViewControlle - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. // 撮影開始 [self setupAVCapture]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } - (void)setupAVCapture { NSError *error = nil; // 入力と出力からキャプチャーセッションを作成 self.session = [[AVCaptureSession alloc] init]; self.session.sessionPreset = AVCaptureSessionPreset640x480; // カメラからの入力を作成 AVCaptureDevice *camera = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; // カメラからの入力を作成し、セッションに追加 self.videoInput = [AVCaptureDeviceInput deviceInputWithDevice:camera error:&error]; [self.session addInput:self.videoInput]; // 画像への出力を作成し、セッションに追加 self.videoDataOutput = [[AVCaptureVideoDataOutput alloc] init]; [self.session addOutput:self.videoDataOutput]; // ビデオ出力のキャプチャの画像情報のキューを設定 dispatch_queue_t queue = dispatch_queue_create("myQueue", NULL); [self.videoDataOutput setAlwaysDiscardsLateVideoFrames:TRUE]; [self.videoDataOutput setSampleBufferDelegate:self queue:queue]; // ビデオへの出力の画像は、BGRAで出力 self.videoDataOutput.videoSettings = @{ (id)kCVPixelBufferPixelFormatTypeKey :[NSNumber numberWithInt:kCVPixelFormatType_32BGRA] }; // ビデオ入力のAVCaptureConnectionを取得 //AVCaptureConnection *videoConnection = [self.videoDataOutput connectionWithMediaType:AVMediaTypeVideo]; // 1秒あたり12回画像をキャプチャ if ( YES == [camera lockForConfiguration:NULL] ) { [camera setActiveVideoMinFrameDuration:CMTimeMake(50,600)]; [camera setActiveVideoMaxFrameDuration:CMTimeMake(50,600)]; } //背景 _previewLayer = [AVCaptureVideoPreviewLayer layerWithSession:self.session]; _previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill; _previewLayer.frame = self.previewImageView.bounds; [self.view.layer addSublayer:_previewLayer]; //マーカー self.indicatorLayer = [CALayer layer]; self.indicatorLayer.frame = CGRectMake(0,0, self.view.bounds.size.width,self.view.bounds.size.height); self.indicatorLayer.hidden = NO; [self.view.layer addSublayer:self.indicatorLayer]; [self.session startRunning]; } // AVCaptureVideoDataOutputSampleBufferDelegateプロトコルのメソッド。 // 新しいキャプチャの情報が追加されたときに呼び出される。 - (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection { // *** COLOR DETECTION *** NSArray* ledPoints = [self colorDetect:sampleBuffer]; // *** DRAW *** UIGraphicsBeginImageContext(CGSizeMake(self.view.bounds.size.width, self.view.bounds.size.height));// オフスクリーンに描画 CGContextRef context = UIGraphicsGetCurrentContext(); //green CGContextSetFillColorWithColor(context, [UIColor greenColor].CGColor);//塗り色 CGContextAddEllipseInRect(context, CGRectMake([[ledPoints objectAtIndex:0] CGPointValue].x-10, [[ledPoints objectAtIndex:0] CGPointValue].y-10, 20, 20));//円の大きさ CGContextDrawPath(context, kCGPathFillStroke);//描く //red CGContextSetFillColorWithColor(context, [UIColor redColor].CGColor);//塗り色 CGContextAddEllipseInRect(context, CGRectMake([[ledPoints objectAtIndex:1] CGPointValue].x-10, [[ledPoints objectAtIndex:1] CGPointValue].y-10, 20, 20));//円の大きさ CGContextDrawPath(context, kCGPathFillStroke);//描く UIImage *img = UIGraphicsGetImageFromCurrentImageContext();// オフスクリーン内容をUIImageに変換 UIGraphicsEndImageContext();// オフスクリーン描画を終了 // 画像を画面に表示 dispatch_async(dispatch_get_main_queue(), ^{ self.indicatorLayer.contents = (id)img.CGImage;//layerにイメージをセットする }); img = nil; } // COLOR DETECTION - (NSArray*)colorDetect:(CMSampleBufferRef)sampleBuffer { CGPoint tagR = CGPointMake(0, 0); CGPoint tagG = CGPointMake(0, 0); BOOL detection_g = NO; BOOL detection_r = NO; int sumX_g = 0; int sumY_g = 0; int pixelNum_g = 0; int sumX_r = 0; int sumY_r = 0; int pixelNum_r = 0; // キャプチャしたフレームからCGImageを作成 UIImage *image = [self imageFromSampleBuffer:sampleBuffer]; // CGImageを取得する CGImageRef imageRef = image.CGImage; // データプロバイダを取得する CGDataProviderRef dataProvider = CGImageGetDataProvider(imageRef); // ビットマップデータを取得する CFDataRef dataRef = CGDataProviderCopyData(dataProvider); UInt8* buffer = (UInt8*)CFDataGetBytePtr(dataRef); CFRelease(dataRef); size_t bytesPerRow = CGImageGetBytesPerRow(imageRef); size_t width = CGImageGetWidth(imageRef); size_t height = CGImageGetHeight(imageRef); imageRef = nil; NSUInteger x,y; UInt8 r,g,b; UInt8* pixelPtr; for (y=0; y<height; y+=4) { for (x=0; x<width; x+=4) { // ピクセルのポインタを取得する pixelPtr = buffer + y * bytesPerRow + x * 4; // 色情報を取得する b = *(pixelPtr + 0); // 青 g = *(pixelPtr + 1); // 緑 r = *(pixelPtr + 2); // 赤 if (g > 240 && r <120 && b < 120) { detection_g = YES; sumX_g += x; //X座標値を加算する sumY_g += y; //Y座標値を加算する pixelNum_g++; //近似色ピクセルの個数を加算する } if (r > 240 && g <120 && b < 120) { detection_r = YES; sumX_r += x; //X座標値を加算する sumY_r += y; //Y座標値を加算する pixelNum_r++; //近似色ピクセルの個数を加算する } pixelPtr = nil; } } if(detection_g){ tagG.y = sumX_g / pixelNum_g * 568 / 640; tagG.x = 320-sumY_g / pixelNum_g * 320 / 480; } if(detection_r){ tagR.y = sumX_r / pixelNum_r * 568 / 640; tagR.x = 320-sumY_r / pixelNum_r * 320 / 480; } return [[NSArray alloc]initWithObjects:[NSValue valueWithCGPoint:tagG],[NSValue valueWithCGPoint:tagR],nil]; } // サンプルバッファのデータからCGImageRefを生成する - (UIImage *)imageFromSampleBuffer:(CMSampleBufferRef)sampleBuffer { CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer); // ピクセルバッファのベースアドレスをロックする CVPixelBufferLockBaseAddress(imageBuffer, 0); // Get information of the image uint8_t *baseAddress = (uint8_t *) CVPixelBufferGetBaseAddressOfPlane(imageBuffer, 0); size_t bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer); size_t width = CVPixelBufferGetWidth(imageBuffer); size_t height = CVPixelBufferGetHeight(imageBuffer); // RGBの色空間 CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); CGContextRef newContext = CGBitmapContextCreate(baseAddress, width, height, 8, bytesPerRow, colorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst); CGImageRef cgImage = CGBitmapContextCreateImage(newContext); CGContextRelease(newContext); CGColorSpaceRelease(colorSpace); CVPixelBufferUnlockBaseAddress(imageBuffer, 0); UIImage *image = [UIImage imageWithCGImage:cgImage scale:1.0 orientation:UIImageOrientationRight]; CGImageRelease(cgImage); return image; } @end