hirax.net::inside out::2018年04月22日

最新記事(inside out)へ  |   年と月を指定して記事を読む(クリック!)

2018年3月 を読む << 2018年4月 を読む >> 2018年5月 を読む

2018-04-22[n年前へ]

Python(Pythonista)でiOSカメラを自由自在に使ってみる 

 iPhone/iPadなどの機器のカメラは、焦点位置や露光時間や感度など、わりと細かく制御することができます。そうした撮影処理を使って、露光時間を変えた撮影を何枚もして画像(ハイダイナミックレンジ:HDR)合成をしたり、焦点位置を変えた撮影から焦点合成(フォーカススタッキング)を行ったりすると、意外に楽しいものです。とはいえ、そんなコード遊びをするのに、毎回Objective-C(やC++)でコーディングするのは少し面倒です。

 というわけで、今日はiOSで動くPython ( Pythonista ) で、iOSのカメラをマニュアル撮影的に使うコードを書いてみました。それが下に貼り付けたPythonコード例です。この例では、焦点制御を無効化した上で、最近接位置から無限遠までのレンズ位置を0.0〜1.0の任意位置に制御しつ、撮影を行うことができます。

 「開発用マシンでコードを書いてビルドした上で、スマホに転送して動かす」というような手間を掛けずとも、スマホ上で比較的短いコードを書いて、それをスマホ上で瞬時に動かして「自分だけの特殊撮影マシン」を仕立てて遊ぶことができるのは面白いものです。…今回貼り付けた撮影処理部分は全くPythonっぽくないコードですが、ひとたび「ライブラリ化」してしまえば、こんなコードを見る必要もなく、やりたいことだけをPythonから気楽に実行することができるようになります。…となれば、色々遊んでみたくなる人も多いのではないでしょうか。

# coding: utf-8

from objc_util import *
import time

AVCaptureSession = ObjCClass('AVCaptureSession')
AVCaptureDevice = ObjCClass('AVCaptureDevice')
AVCaptureDeviceInput = ObjCClass('AVCaptureDeviceInput')
AVCapturePhotoOutput = ObjCClass('AVCapturePhotoOutput')

def manualCapture(device, output, focusDistance, fileName):

    def captureOutput_didFinishProcessingPhotoSampleBuffer_
previewPhotoSampleBuffer_resolvedSettings_bracketSettings_error_(
             _self, _cmd, _output, _photoBuffer, _previewBuffer,
                    _resolveSettings, bracketSettings, _error ):
        photoBuffer = ObjCInstance(_photoBuffer)
        jpegPhotoData = ObjCClass('AVCapturePhotoOutput'
        ).JPEGPhotoDataRepresentationForJPEGSampleBuffer_
previewPhotoSampleBuffer_(
                             photoBuffer, _previewBuffer)
        jpegPhotoData.writeToFile_atomically_(fileName, True )

    # delegate
    CameraManualPhotoCaptureDelegate = create_objc_class(
                            'CameraManualPhotoCaptureDelegate',
        methods=[
        captureOutput_didFinishProcessingPhotoSampleBuffer_
previewPhotoSampleBuffer_resolvedSettings_bracketSettings_error_ ],
        protocols=[ 'AVCapturePhotoCaptureDelegate' ])

    device.lockForConfiguration_(None)
    device.setFocusModeLockedWithLensPosition_completionHandler_(
                                            focusDistance, None)
    device.unlockForConfiguration()
    
    time.sleep(1)
    delegate = CameraManualPhotoCaptureDelegate.new()
    settings = ObjCClass('AVCapturePhotoSettings'
         ).photoSettings()
    settings.AVCaptureFocusMode = 0
    output.capturePhotoWithSettings_delegate_(
                                    settings, delegate )
    time.sleep(1)
    delegate.release()

@on_main_thread
def main():
        session = AVCaptureSession.alloc().init()
        device =
AVCaptureDevice.defaultDeviceWithMediaType_('vide')
        _input =
AVCaptureDeviceInput.deviceInputWithDevice_error_(
    device, None)
        if _input:
            session.addInput_(_input)
        else:
            return

        session.startRunning()
        output = AVCapturePhotoOutput.alloc().init()
        session.addOutput_(output)        
        time.sleep(1)
        manualCapture(device, output, 0.0, 'sample.jpg')
        time.sleep(1)
        session.stopRunning()
        session.release()
        output.release()

if __name__ == '__main__':
    main()

Python(Pythonista)でiOSカメラを自由自在に使ってみる