2017年11月1日水曜日

アルバムから写真を取得して表示する (OpenCVでリサイズ)

ピッカーで選択した画像をリサイズして表示する

1. OpenCVの準備をする
2. Bridge header.hの修正 (以下を追加)
      #import "OpenCVWrapper.h"       // 追加
3. OpenCvWrapper.h の修正
     (作成する関数を記載する)
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>

@interface OpenCvWrapper : NSObject
// funciton to get opencv version
+(NSString * ) openCVVersionString;
+(UIImage * ) openCvResize:(UIImage * )image targetWidth:(int)width targetHeight:(int)height;

@end

4. C++コードを OpenCvWrapper.mm に記載する
#import <opencv2/opencv.hpp>        // 追加
// #import <opencv2/highgui.hpp>
#import <opencv2/imgcodecs/ios.h>   // UIImageToMatなどに必要(3.1.1以降はコレの模様)
#import "OpenCvWrapper.h"

@implementation OpenCvWrapper       // swiftからはこのクラス名でアクセス

// 追加関数 ()
+(NSString *) openCVVersionString
{
    return [NSString stringWithFormat: @"openCV Version %s", CV_VERSION];
}

// 引数x3を受けてUIImageを返す関数(param2,3はラベルをつけるらしい)
// 呼び出し側(Swift)はこんな感じに
// OpenCvWrapper.openCvResize(image, targetWidth: 320, targetHeight: 240)
+(UIImage*) openCvResize:(UIImage * )image targetWidth:(int)width targetHeight:(int)height
{
    // UIImage uiImag2
   
    NSLog(@"width:%d height:%d", width, height);
    if(width > height) {
        // 横画像
        NSLog(@"横画像");
    } else {
        // 縦画像
        NSLog(@"縦画像");
    }
   
    cv::Mat imageMat;
    UIImageToMat(image, imageMat);

    cv::Mat resizedMat(cv::Size(width, height), imageMat.type());
    cv::resize(imageMat, resizedMat, resizedMat.size(), cv::INTER_LINEAR);
   
    // cv::Mat resizedMat(cv::Size(10, 10), CV_8UC3, cv::Scalar(0,0,255));
   
    return MatToUIImage(resizedMat);
}

@end

5. ViewController.swiftに上記の関数を呼び出すコードを記載する

// 本アプリは以下の動作をします
// 1. ImageViewをタップするとpicker controllerが表示
// 2. picker controllerで写真を選択するとImgeViwに写真を表示

import UIKit

class ViewController: UIViewController , UIImagePickerControllerDelegate, UINavigationControllerDelegate {

    var imagePicker: UIImagePickerController!
    @IBOutlet weak var photoView: UIImageView!
    let tagPhotoView = 1
   
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
       
        // viewにタグを設定(本筋ではないがImageViewをタッチした際にpicker controllerを表示させるため)
        photoView.tag = tagPhotoView
       
        // インスタンス生成
        imagePicker = UIImagePickerController()
       
       
        // デリゲート設定
        imagePicker.delegate = self
       
        // 画像の取得先はフォトライブラリとする(カメラにするとカメラを起動した撮影した画像を取得できるみたい)
        // この段階ではImagePickerは起動させません(エラーになるから...)
        imagePicker.sourceType = UIImagePickerControllerSourceType.PhotoLibrary
        // self.presentViewController(imagePicker, animated: true, completion: nil)
    }

    override func viewDidAppear(animated: Bool) {
       
    }
   
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
   
    // ImagePickerControllerで画像を選択した際に呼び出されるdelegate (self指定の為)
    func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject])
    {
        // Add your functionality here
        //選択された画像を取得.
        let selectedImage: AnyObject?  = info[UIImagePickerControllerOriginalImage]
       
        //選択された画像を表示するViewContorllerにセットする.
        let image = (selectedImage as! UIImage)
        // photoView.image = (selectedImage as! UIImage)
       
        print("\(image.size.width)  x  \(image.size.height) : \(photoView.layer.bounds.width) x \(photoView.layer.bounds.height)")
       
        // リサイズ
        let resizedImage = OpenCvWrapper.openCvResize(image, targetWidth: 160, targetHeight: 160)
        // let resizedImage = OpenCvWrapper.openCvResize(image, targetWidth: Int32(photoView.layer.bounds.width), targetHeight: Int32(photoView.layer.bounds.height))
       
        // viewControllerに設定
        photoView.image = resizedImage
       
        // モーダルビューを閉じる
        self.dismissViewControllerAnimated(true, completion: nil)
    }
   
   
     // 画像選択がキャンセルされた時に呼ばれる.
    func imagePickerControllerDidCancel(picker: UIImagePickerController) {
        // モーダルビューを閉じる
        self.dismissViewControllerAnimated(true, completion: nil)
       
    }
   
    // user interaction enable / multiple touchをチェックしておく
    override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
        super.touchesEnded(touches, withEvent: event)
        for touch: UITouch in touches {
            let tag = touch.view!.tag
            switch tag {
            case tagPhotoView:
                self.presentViewController(imagePicker, animated: true, completion: nil)
            default:
                break
            }
        }
    }
}

※ ImagePickerのサンプル で、取得した画像をリサイスするように修正したコードです
http://tantan2014.blogspot.jp/2017/10/uiimagepickercontroller.html