ãæé¤ããããã«ã³ããè²·ã£ã¦å年以ä¸ãã¡ã¾ãããå¤åºæã«ã«ã³ããèµ·åãã¦ãå¸°å® ãããæé¤ãçµãã£ã¦ãããã¨ããæãã§ä½¿ã£ã¦ãã¾ãããã ã確ãã«é¨å±ã¯ãããã«ãªã£ã¦ããã®ã§ãããæ¬å½ã«é¨å±ã®é ã ã¾ã§æé¤ãã¦ããã¦ããã®ããåãããªããã¨ããããã§ãã«ã³ãã®ç§»åçµè·¯ãé£ç¶æ®å½±ãã¦ãã¡ããã¨é¨å±ã®é ã ã¾ã§æé¤ãã¦ããã確èªããããã°ã©ã ãRubyã¨Cocoa(Objective-C)ã§ä½ãã¾ããã
æ¦è¦
ä»åã¯ä»¥ä¸ã®äºã¤ã®ããã°ã©ã ãä½ãã¾ããã
å®é¨
çµè«
- ï¼åéã§çµæ§ãã¡ãã¡æé¤ãã¦ããã¦ãããã¨ãåãã
- ï¼æç®ã®åçã§ã¯å¥¥ã®ã»ãï¼å°æãããï¼ã«ã¯ããªããä¸åº¦ãä¾µå ¥ãã¦ããªããï¼å以ä¸æé¤ããã°ã¡ããã¨ä¾µå ¥ãã¦ãããã¯ãã ãã
- ï¼æç®ãã¿ãã¨ãå é»ãã¼ã¹ã«ã¯ã»ã¨ãã©è¿ã¥ãã¦ããªããã¨ãããããããã¯ã«ã³ãã®ä»æ§ã£ã½ãããªã®ã§ãå é»ãã¼ã¹å¨ãã¯çµæ§ãã³ãªããã¾ããã¡ãã¨ãã©ãå é»ãã¼ã¹ã®å ´æãå¤ãã¦ãããã¨ããã
- ä»åã®ããã°ã©ã ã§ããç¨åº¦ã«ã³ãã®è»è·¡ã調æ»ã§ãããã¨ã確èªã§ãããä»åº¦ã¯ãã«ã§æé¤ããã¦çµæãã¿ã¦ã¿ããã
- ã«ã³ãã¯ä¾¿å©ãªã®ã§ãã¿ããªãè²·ãã°ããã¨æãã
ãã¾ã
åæãã¼ã¸ã§ã³ã®åæã¹ã¯ãªããã«ããåæç»åããã¯ã»ã«å¤ã®å·®åããã®ã¾ã¾åºåãã¦ã¿ããã«ã³ããèªèãããããã©ãã¡ãã£ã¨ç»åã¨ãã¦è¦è¾ãã®ã§ãä»åã¯ãã¯ã»ã«å¤ã®å¹³åå¤ãåºåãã¦ãéæã£ã½ãè¦ããããã«ããã
å®é¨ä¸ã«å¶ç¶æ®å½±ãããç»åã人影ã®ãããªãã®ãåãè¾¼ãã§ãããããã°ã©ãã¼ã®åªç¸éãä½ããããããªãã
ããã°ã©ã 解説(camara.app)
ã½ã¼ã¹
ã¾ãã¯åçæ®å½±é¨ã®ã½ã¼ã¹ãããObjective-Cã§æ¸ããCocoaã¢ããªã§ãã
// // MainController.m // camera // // Created by æ¾å å¥å¤ªé on 09/07/25. // Copyright 2009 __MyCompanyName__. All rights reserved. // #import "MainController.h" @implementation MainController - (IBAction)startRecording:(id)sender { recording = TRUE; } - (IBAction)stopRecording:(id)sender { recording = FALSE; } - (void)exportImageToURL:(NSURL*)inURL { CGColorSpaceRef colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); CIContext *exportContext = [CIContext contextWithCGContext:[[NSGraphicsContext currentContext] graphicsPort] options:nil]; CGColorSpaceRelease(colorSpace); CGImageDestinationRef imageDestination = CGImageDestinationCreateWithURL((CFURLRef)inURL, (CFStringRef)@"public.jpeg", 1, nil); if (imageDestination == NULL) { NSLog(@"problems creating image destination\n"); CFRelease(imageDestination); return; } CGImageRef renderedImage = [exportContext createCGImage:image fromRect:[image extent]]; CGImageDestinationAddImage(imageDestination, renderedImage, NULL); if (!CGImageDestinationFinalize(imageDestination)) { NSLog(@"problems writing JPEG file\n"); } CFRelease(imageDestination); CGImageRelease(renderedImage); } - (void)captureOutput:(QTCaptureOutput *)captureOutput didOutputVideoFrame:(CVImageBufferRef)videoFrame withSampleBuffer:(QTSampleBuffer *)sampleBuffer fromConnection:(QTCaptureConnection *)connection { @synchronized (self) { if(recording && canSave){ CVBufferRetain(videoFrame); image = [CIImage imageWithCVImageBuffer:videoFrame]; CVBufferRelease(videoFrame); NSLog([image description]); imgCnt++; NSString *dir = @"/Users/ken/work/kenmaz-sandbox/projects/roomba/imgs/cam"; NSString *filepath = [NSString stringWithFormat:@"%@/%d.jpg", dir, imgCnt]; [self exportImageToURL:[NSURL fileURLWithPath:filepath]]; canSave = FALSE; } } } -(void)saveImage:(NSTimer*)timer { canSave = TRUE; } - (void)awakeFromNib { timer = [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:@selector(saveImage:) userInfo:nil repeats:YES]; mCaptureSession = [[QTCaptureSession alloc] init]; BOOL success = NO; NSError *error; QTCaptureDevice *device = [QTCaptureDevice defaultInputDeviceWithMediaType:QTMediaTypeVideo]; if (device) { success = [device open:&error]; if (!success) { // Handle error } mCaptureDeviceInput = [[QTCaptureDeviceInput alloc] initWithDevice:device]; success = [mCaptureSession addInput:mCaptureDeviceInput error:&error]; if (!success) { // Handle error } mCaptureDecompressVideoOutput = [[QTCaptureDecompressedVideoOutput alloc] init]; success = [mCaptureSession addOutput:mCaptureDecompressVideoOutput error:&error]; if(!success){ //Error } // Set the controller be the movie file output delegate. [mCaptureDecompressVideoOutput setDelegate:self]; // Associate the capture view in the UI with the session [mCaptureView setCaptureSession:mCaptureSession]; } // Start the capture session running [mCaptureSession startRunning]; } - (void)windowWillClose:(NSNotification *)notification { [mCaptureSession stopRunning]; [[mCaptureDeviceInput device] close]; } - (void)dealloc { [mCaptureSession release]; [mCaptureDeviceInput release]; [mCaptureDecompressVideoOutput release]; [super dealloc]; } @end
解説
- ä¸è¨ã®ã½ã¼ã¹ä»¥å¤ã«ãUIãã«ãã¼ã§ããã£ããã£ãã¥ã¼ã¨æ®å½±ãã¿ã³ããã£ãç°¡åãªã¦ã£ã³ãã¦ãä½ã£ã¦ããã¾ã
- ã¢ããªãèµ·åããã¨awakeFromNibã¡ã½ãããå®è¡ããã¾ãããã®ã¡ã½ããä¸ã§ã¯ãç»åãã£ããã£ã®ããã®ã»ãã·ã§ã³(QTCaptureSession)ãã¾ãä½æãã¦ã¾ãã次ã«ããã¤ã¹(QTCaptureDevice)ãæ¤åºãã¦ãã»ãã·ã§ã³ã¸ã®å ¥åå ã¨ãã¦è¨å®ãã¦ãã¾ããã¾ããåºåå ã¨ãã¦éå§ç¸®ç»åãåå¾ããããã®Outputãä½æããåããã»ãã·ã§ã³ã«åºåå ã¨ãã¦è¨å®ãã¦ãã¾ãããã¨ã¯ï¼ç§ãã¨ã«æ®å½±ãè¡ãããã®ã¿ã¤ãã¼çãè¨å®ãã¦ãã¾ãã
- ã«ã¡ã©ãç»åãã¨ããããã³ã«ãcaptureOutput:didOUtputVideoFrameã¡ã½ãããå®è¡ããã¾ããã¡ã½ããã§ã¯ãï¼ç§ããã«ã«ã¡ã©ãæ®å½±ããç»å(CIImage)ãèªã¿è¾¼ãã§ãexportImageToURLã¡ã½ãããå¼ã³ã¾ãã
- exportImageToURLã¡ã½ããå ã§ã¯åãåã£ãç»åããã¼ã«ã«ã«jpegå½¢å¼ã§ä¿åãã¾ãã
- Macã®ãã¤ãã£ãã¢ããªãä½ãã®ã¯ã¯ããã¦ã§ããããiPhoneã¢ããªéçºã§ããç¨åº¦Cocoaãã¬ã¼ã ã¯ã¼ã¯ã®éçºææ³ãç解ãã¦ããã®ã§ãå²ã¨ãããªãä½ãã¾ããã
- ï¼ç§ãã¨ã«NSTimerãå®è¡ãã¦ç»åãä¿åãã¦ãããã§ãããããã¡ãã£ã¨è¯ãããæ¹ã¯ç¡ãããªããJavaã§è¨ãã¨ããã®System.currentTimeInMillis()ã¿ãããªã®ã§æéãè¨ããã°ããã¡ããã·ã³ãã«ã«ãªã£ãã®ã ããã
- ã¤ã³ãã³ãããã¡ããã¡ãã«è¡¨ç¤ºããããªã¼ãï¼ã¯ã¦ãªè¨æ³
ããã°ã©ã 解説(mono.rb)
ã½ã¼ã¹
ä»åº¦ã¯camera.appã§æ®å½±ããç»åãèªã¿è¾¼ãã§ããã¾ããã¨åæããRubyã®ã¹ã¯ãªããã§ãããã¡ã¤ã«åãmono.rbã¨ãªã£ã¦ãã¾ããããã®ååã«ç¹ã«æå³ã¯ããã¾ããã
require 'rubygems' require 'rmagick' include Magick include Math def diff(base, file) puts "processing #{file} ..." img = ImageList.new(file) base.rows.times do |y| base.columns.times do |x| clr1 = base.pixel_color(x, y) clr2 = img.pixel_color(x, y) r1, g1, b1 = clr1.red, clr1.green, clr1.blue r2, g2, b2 = clr2.red, clr2.green, clr2.blue r = (r1 - r2).abs g = (g1 - g2).abs b = (b1 - b2).abs r = r < 5000 ? r1 : (r1+r1+r2)/3 g = g < 5000 ? g1 : (g1+r1+g2)/3 b = b < 5000 ? b1 : (b1+r1+b2)/3 base.pixel_color(x, y, Pixel.new(r,g,b)) end end base.write("jpeg:#{Time.now.to_i}.jpg") end def collect files = get_files bass = ImageList.new(files[0]) files.each do |file| diff(bass, file) end bass.write("jpeg:out.jpg") end def get_files fnames = [] Dir::foreach(ARGV[0]) do |f| if f =~ /.jpg/ fnames << f end end fnames.sort!{|a,b| a.to_i <=> b.to_i } files = [] fnames.each do |f| files << ARGV[0] + f end files end collect
解説,ææ³
- å®è¡ã«ã¯,ImageMagick+RMagickãã¤ã³ã¹ãã¼ã«ããã¦ããå¿ è¦ãããã¾ãã
- ãã£ã¦ãããã¨ã¯ãå¼æ°ã§ä¸ãããããã©ã«ã以ä¸ã®å ¨ã¦ã®ãã¡ã¤ã«å士ããã¯ã»ã«åä½ã§æ¯è¼ããç¸éãããã°åæãã¦åºåãã¦ãæçµçã«ä¸æã®ç»åãã¡ã¤ã«ãçæãã¦ããã ãã§ãã
- diffã¡ã½ããã§ã¯ãä¸æç®ã®ç»åãåºæº(base)ã¨ãã¦ãæ®ãã®ç»å(img)ã¨ãã¯ã»ã«åä½ã§æ¯è¼ããå·®ç°ããªããã°baseã®ãã¯ã»ã«å¤ãæ¡ç¨ãå·®ç°ãããã°base:img = 2:1ã®å²åã§ãã¯ã»ã«å¤ã®å¹³åãåã£ã¦æ¡ç¨ãã¦ãã¾ãããr = r < 5000 ? r1 : (r1+r1+r2)/3ãã¨ããã£ã¦ãé¨åãªãã§ãããç¸å½é©å½ã§ãã
- ã¦ãããããéãã§ãããã®ãã¡Cã§æ¸ããªããã¾ãã
ã½ã¼ã¹ä¸å¼
以ä¸ã«ç½®ãã¦ããã¾ãã
http://code.google.com/p/kenmaz-sandbox/source/browse/#svn/trunk/projects/roomba