Swift로 OpenCV 3.1 사용하여 iOS 앱 만들기

Swift로 OpenCV 3.1 사용하여 iOS 앱 만들기

iOS 9.0 이상에서 Swift로 OpenCV 3.1 버전을 사용하여 앱을 만들 수 있는 간단한 예제이다. http://opencv.org/ 에서 iOS로 빌드된 OpenCV 3.1 Framework을 다운로드 받아 사용하면 애물레이터에서는 문제가 없지만, 단말 환경에 맞춰 빌드를 하면 png 모듈에서 링크 오류가 발생한다. 따라서 이 문제를 해결한 OpenCV 3.1 패치버전의 iOS Framework을 빌드하거나 다운로드 받아 사용해야 한다. OpenCV 빌드 및 설치 관련 내용은 macOS Xcode에서 OpenCV 사용하기 포스팅을 참고하면 된다.

이 포스팅은  https://www.youtube.com/watch?v=ywUBHqxwM5Q을 참고하여 작성했다.

1. 개발 환경

이 포스팅에서 소개할 Xcode 프로젝트 개발환경은 다음과 같다. 

2. OpenCV 프로젝트 생성

2.1 HelloOpenCV 프로젝트 생성

Xcode을 실행 후에 아래 화면과 같이 'Create a new Xcode project'을 선택한다.

iOS을 선택하고, Single View Application을 선택 후에 'Next' 버튼을 선택한다.
프로젝트 이름을 'HelloOpenCV' 로 입력하고, Language는 'Swift'을 선택 후 Devices 항목은 가지고 있는 단말에 맞춰 선택하면 된다. 예제에서는 iPhone을 선택했다.
그 이후에 프로젝트가 생성될 위치를 선택하면 간단하게 Xcode 프로젝트는 생성된다.

2.2 iOS용 OpevCV Framework 연결

프로젝트가 생성되면 아래 화면과 같이 'Framework' 그룹을 만든다. 이 그룹은 OpenCV를 비롯하여 다른 iOS Framework 등을 사용할 때 한 곳에 관리하면 좋다.



그룹이 생성되면 아래 화면과 같이 빌드 또는 다운로드 한 iOS OpenCV Framework을 Finder에서 찾아 마우스로 끌어다 놓기를 하면 된다. 이 때 OpenCV Framework을 복사할 것인지? 아니면 참조만 할 것인지 여부를 물어보는데, 이 예제에서는 OpenCV Framework은 이 프로젝트의 디렉터리로 복사가 될 수 있도록 옵션을 선택했다.
 


정상적으로 OpenCV Framework이 추가가 되면 다음 화면과 같이 헤더파일들을 확인할 수 있다.

2.3 OpenCV Wrapper 클래스와 Bridging Header 만들기

이 프로젝트는 Swift 언어로 iOS 앱을 만든다. Swift에서는 C++ 라이브러리에 직접 접근을 할 수 없기 때문에 아래 그림과 같이 Bridging Header와 Wrapper Class을 Objective C로 만든 인터페이스를 만들어야 한다. 여기서 주의해야 할 점은 Bridging Header와 Wrapper Class의 Header 파일은 Swift 언어에서 참조하기 때문에 절대 C++의 Header 파일을 참조하면 절대 안된다.


OpenCVWrapper 클래스와 Bridging 헤더파일을 생성해보다.
우선 프로젝트에서 'OpenCVWrapper' 그룹을 만들고, 'OpenCVWrapper'에서 오른쪽 마우스버튼을 누른 후 'New Files...' 메뉴를 선택한다.

그리고 파일 템플릿을 'Cocoa Touch Class'을 선택 후 'Next' 버튼을 누른다.
Class 이름은 'OpenCVWrapper'로 설정하고, NSObject로부터 상속받도록 설정 후 Language는 Objective-C로 설정한다.
이 때 Objective-C Bridging header 생성 여부를 물어 보는데, 'Create Bridging Header' 버튼을 눌러 생성한다. 
모든 단계가 끝나면  OpenCVWrapper.h, OpenCVWrapper.m, HelloOpenCV-Bridging-Header.h 파일이 생성된다. OpenCV 3.1 Framework은 C++로 구현되어 있기 때문에 OpenCVWrapper.m 파일의 확장자를 OpenCVWrapper.mm으로 수정하고, 아래와 같이 Bridging Header에 내용을 추가하면 OpenCV을 사용하는 기본 환경 설정은 끝난다.

[HelloOpenCV-Bridging-Header.h]
//
//  Use this file to import your target's public headers that you would like to expose to Swift.
//
#include "OpenCVWrapper.h" 



3. iOS에서 OpenCV 사용하기

이번 예제에서는 화면에 두 개의 ImageView 컨트롤을 만든 후 한 개에 사진 등 이미지를 설정하면, 다른 ImageView에 그레이 색상으로 변환하여 표시한다. OpenCVWrapper에 makeGrayImage 함수를 추가하고, 이 구현 코드에서는 OpenCV의 Mat을 이용하여 색상을 흑백으로 그레이 색상으로 변환시킨다.

[OpenCVWrapper.h]
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>

@interface OpenCVWrapper : NSObject

+(UIImage *) makeGrayImage:(UIImage *) image;

@end

[OpenCVWrapper.mm]

#import "OpenCVWrapper.h"
#import <opencv2/opencv.hpp>
#import <opencv2/imgcodecs/ios.h>

@implementation OpenCVWrapper

+(UIImage *) makeGrayImage:(UIImage *) image {
    // Transform UIImage to cv::Mat
    cv::Mat imageMat;
   
    UIImageToMat(image, imageMat);
   
    // If the image was alread grayscale, return it
    if (imageMat.channels() == 1)
        return image;
   
    // Transform the cv::mat color image to gray
    cv::Mat grayMat;
    cv::cvtColor(imageMat, grayMat, CV_BGR2GRAY);
   
    // Transform grayMat to UIImage and return
    return MatToUIImage(grayMat);
}

@end


이 예제는 간단하게 이미지를 보여주기 위하여 프로젝트에 이미지를 추가했다. 아래 그림과 같이 'Assets.xcassets' 항목을 선택 후 사진을 끌어다 놓으면 된다. 추가된 그림의 이름은 'sample'로 설정되는데, 추가하는 파일이름으로 설정되므로 그림의 파일 이름을 기억해 둔다.


이제 UI를 간단하게 만들것이다. iOS에서 UI는 Main.storyboard을 선택해서 컨트롤들을 추가하면 되는데, 이 예제는 아래 화면과 같이 위와 아래에 두 개의 ImageView 컨트롤을 사용한다.

위쪽의 ImageView 컨트롤은 이전에 추가한 sample 이미지를 선택한다. 'Content Mode'는 이미지의 가로와 세로 비율을 맞출 수 있도록 Aspect Fit로 설정하고, 배경색을 선택한다.

아래쪽 ImageView 컨트롤은 OpenCV을 이용하여 위쪽 ImageView 컨트롤에 있는 이미지를 읽어 들어 그레이 이미지로 변환하여 표시한다.


그리고 아래 화면에서 오른쪽 상단에 'Show the Assistance editor' 버튼을 누르면 하단에 ViewController.swift 소스 코드가 보여지고, 두 개의 ImageView 컨트롤이 각각 sourceView와 targetView 변수로 매핑할 수 있다.


매핑 방법은 'Control' 키를 누른 상태에서 마우스로 위쪽 ImageView 컨트롤을 선택 후 끌어다가 소스에 놓으면 조그마한 팝업창이 뜨는데, 여기에 'sourceView' 라고 입력하면 위쪽 ImageView 컨트롤이  sourceView 변수로 매핑이 되어 ImageView을 제어할 수 있다. 아래쪽 ImageView 컨트롤은 targetView로 매핑하면 된다.



그리고 ViewController.swift 코드에서 viewDidLoad() 함수에 사진을 그레이 코드로 변환하는 코드 한줄만 추가하면 프로그램이 실행될 때 자동으로 변환되어 아래의 ImageView 컨트롤에 표시 된다.

[ViewController.swift]

import UIKit
 
class ViewController: UIViewController {
    @IBOutlet weak var sourceView: UIImageView!
    @IBOutlet weak var targetView: UIImageView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Do any additional setup after loading the view, typically from a nib.
        targetView.image = OpenCVWrapper.makeGrayImage(sourceView.image);
    }
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}


다음은 실행 화면이다.


지금까지 OpenCV을 iOS에서 사용할 수 있도록 프로젝트 생성 과정과 Swift 언어에서 OpenCV을 사용할 수 있는 Wrapper 클래스 생성 및 연동 방법을 설명했다. 이 예제의 소스코드는 아래 링크에서 다운로드 받을 수 있다.



4. Reference

  1. OpenCV 3 with Swift, YouTube: https://www.youtube.com/watch?v=ywUBHqxwM5Q

댓글

  1. 좋은 강좌 매우 감사합니다.
    근데 OpenCV 3.1 프레임워크와 예제파일을 다운로드 할 수 없어요 ㅠㅠ
    혹시 링크 수정을 부탁드려도 될려는지요..

    답글삭제

댓글 쓰기

이 블로그의 인기 게시물

Google Protocol Buffers 소개

Google Cloud Platform 사용하기 - Comput Engine(VM) 인스턴스 만들기