en

hi, it seems you are using microsoft internet explorer. it doesn't match web standard and causes problems browsing this site. please please please use mozilla firefox or google chrome instead. thank you!

zh

哦哦!您正在使用Internet Explorer 瀏覽器,它與我們的網頁標準並不相容,可能會導致畫面顯示不正常。
請改用 Mozilla Firefox 或者 Google Chrome 才能正常瀏覽本網站,謝謝!

12.05.2010

Camera / 攝影機畫面的擷取方式-前篇( iOS 4 以上適用)

如果您是 iOS 5.0 SDK 以上的使用者,這篇文章你將不再適用,請前往索引式搜索頁面中的 AVFoundation 分類項目,取得新的設定方式。

有別於以往使用 Image Picker 擷取桌面的方式來取得Camera的影像,在 iOS 4 中可以使用另一種方式(AV Foundation),直接抓取 Camera 中的影像,這種方式更快,也更直接,負擔也較小,特別注意本範例只能在 Device 上執行與編譯,在模擬器下則會出現錯誤。其程式碼如下。(View-based Template)

首先在 ViewCotroller.h 中加設定代理,之後才能正常使設定與取得 Camera 的相關參數。

@interface CameraSampleViewController : UIViewController<AVCaptureVideoDataOutputSampleBufferDelegate> {
//自行定義的函式,目的用來顯示Camera所擷取到的畫面
-(void)captureSession {

    //session為AVCaptureSession型態的指標,之後將透過這個指標對Camera影像做擷取並輸出
    session = [[AVCaptureSession alloc] init];

    //設定擷取時畫面的大小,這裡提供三種等級可以選擇
    session.sessionPreset = AVCaptureSessionPresetMedium;

    //選擇Device,也就是Camera
    AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];

    NSError *error = nil;

    //將Device設定成輸入端(可以想成輸入為Camera擷取的影像,輸出為我們設定的ImageView)
    AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:device error:&error];
    if (!input) {
        //這裡可撰寫啟動攝影機失敗的處理常式,目前是不做任何事情
    }

    //將輸入端導入給session
    [session addInput:input];

程式碼到這裡其實已經可以成功擷取 Camera 的影像,只是缺少輸出沒辦法呈現出來,而下面程式碼將要製作一個輸出端,並利用這個輸出端將 session 內的 Camera 影像傳至 ImageView 中。

    //製作一個輸出端並指派給session
    AVCaptureVideoDataOutput *output = [[[AVCaptureVideoDataOutput alloc] init] autorelease];
    [session addOutput:output];

    //對輸出端的queue做設定
    dispatch_queue_t queue = dispatch_queue_create("myQueue", NULL);
    [output setSampleBufferDelegate:self queue:queue];
    dispatch_release(queue);

    //輸出端的像素(Pixel)格式化,包含透明度的32位元
    output.videoSettings = [NSDictionary dictionaryWithObject:[NSNumber
        numberWithInt:kCVPixelFormatType_32BGRA] forKey:(id)kCVPixelBufferPixelFormatTypeKey ];

    //這裡將幀率數值化,這裡設定是每秒15張影像,也可不做設定使用之前的設定值
    output.minFrameDuration = CMTimeMake(1, 15);

    //宣告一個AVCaptureVideoPreviewLayer的指標,用來存放session要輸出的東西(Camera中的畫面)
    AVCaptureVideoPreviewLayer *previewLayer = [AVCaptureVideoPreviewLayer layerWithSession:session];

    //設定輸出畫面的邊界大小
    previewLayer.frame = self.view.bounds;

    //將輸出的東西透過preview秀出來,preview為UIImageView型態
    [self.preview.layer addSublayer:previewLayer];

    //完成session的輸入端與輸出端的相關設定之後,啟動的這個session,它將會自動將輸入端與輸出端做連結
    [session startRunning];
}

最後,別忘記將 AVFoundation、CoreMedia 和 CoreVideo 的 framework 加入到你的專案內,程式才能正常執行。加入的方法是在 Groups & Files 內的專案名稱上按下右鍵 > Add >  Existing Frameworks,之後選擇需要的 framework 並 Add 即可。







2 則留言:

  1. 你好
    請問一下上面的code都是放在同一個method 裡面嗎

    我實作了上面的code

    不過還是沒有辦法抓到手機的相機
    在console上有一個WARNING: -[ setMinFrameDuration:] is deprecated. Please use AVCaptureConnection's -setVideoMinFrameDuration:

    請問有辦法解決嗎 謝謝

    回覆刪除
  2. 我使用 iOS 5 編譯雖然可以過,程式也能正常執行,但是 console也跟你出現一樣的警告訊息,剛剛看了一下 library 就像 console 說的一樣,這個方法在 iOS 5 裡是不建議使用的,關於iOS5 的使用方式我可能還要再研究看看唷。

    http://developer.apple.com/library/mac/#releasenotes/AudioVideo/RN-AVFoundation/_index.html

    回到您的問題,這些CODE我是放在同一個method 沒錯,不過你抓不到像機的原因應該不是這個WARNING的問題,如果你想要SOURCE CODE 的話可以來信到furnacedigital@gmail.com 索取。

    補充說明一下,我是使用iPhone4 並非4s不知道是不是硬體的關係。

    回覆刪除