적당한 고통은 희열이다

- 댄 브라운 '다빈치 코드' 중에서

초보 iOS 개발자의 일상/개발 업무

[Swift iOS] OpenCV 흑백변환

hongssup_ 2022. 1. 11. 18:24
반응형

OpenCV 설치

터미널에서

$ pod init
$ open -a Xcode Podfile

target 'OpenCVtest' do
  use_frameworks!
  pod 'OpenCV', '~> 4.3'
end

$ arch -x86_64 pod install

 

pod 설치 대신 opencv framework를 프로젝트에 그대로 넣어서 사용하는 방법도 있지만,

그렇게 하니까 framework 내부의 opencv 코드들을 뜯어보기가 힘들어서 cocoapod 으로 설치하는걸 추천..!

 

Objective-C 파일 생성

Swift에서 Bridge-Header를 이용해 objective-c를 호출하고, objective-c에서 opencv를 호출하여 리턴해주는 구조. 

따라서 아마도 Objective-C로만 함수를 만들 수 있다는 슬픈 소식...

 

New File... > Cocoa Touch Class 

Cocoa Touch Class로 새 파일을 생성해준다. Class 명은 마음대로 정하고, Language를 Objective-C로 설정을 해준다.

그런 다음, Swift 프로젝트에서 Objective-C 파일을 생성해주었기 때문에 Create Bridging Header를 눌러 Bridging Header를 함께 만들어준다. 

 

Objective-C 파일 작성

다음과 같이 Objective-C 파일과 Header 파일이 생성되었다면, 먼저 .m 파일의 확장자를 .mm 으로 바꿔준다. 

opencvWrapper.h 파일과 opencvWrapper.mm 파일을 다음과 같이 작성해준 후,

// opencvWrapper.h

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN

@interface opencvWrapper : NSObject

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

@end

NS_ASSUME_NONNULL_END
// opencvWrapper.mm

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

@implementation opencvWrapper

+ (UIImage *)toGray:(UIImage *)image {
    //Transform UIImage to cv::Mat
    cv::Mat imageMat;
    UIImageToMat(image, imageMat);
    
    //If the image was alreay 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::COLOR_BGR2GRAY);
    
    //Transform grayMat to UIImage and return
    return MatToUIImage(grayMat);
}
@end

위와 같이 Objective-C로 만든 toGray 함수를 Swift 파일에서 사용하기 위해 Bridging-Header에 opencvWrapper.h를 추가해준다. 

// opencv_test-Bridging-Header

#import "opencvWrapper.h"

 

Swift에 적용하기

이미지 뷰 두개를 만들어 ViewController에 다음과 같이 코드를 작성해준다. 

위의 사진을 흑백으로 변환해 아래 이미지뷰에 넣어주는 방식이다. 

실행하면 다음과 같이 사진이 흑백으로 잘 변환된 것을 볼 수 있다. 

 

+  실행시 다음과 같이 에러가 나는 경우가 있다.

Parse Issue 

Expected identifier

expanded from macro ’NO’

해당 오류를 일으키는 곳에 그냥 다음과 같이 주석처리해주었더니 실행이 잘 되더라.

//#include "opencv2/stitching.hpp"

 

OpenCV Issues에 보니 이런 문제를 많은 사람들이 겪고 있던데 예전에 vlc 라이브러리 사용할때도 그랬고 생각보다 고작 라이브러리 선언 순서? 때문에 에러가 나는 경우도 꽤 있는것 같다.

참고 : github opencv issues - expended from macro 'NO'

 

 

이처럼 opencv에서 사용할 함수들을 opencvWrapper.mm 파일에 구현하고 Swift에서 가져다 사용할 수 있다.

Objective-C로 함수를 작성해줘야하다니... 갈길이 멀다.. 화이팅..! 

 

OpenCV 샘플 프로젝트는 👉🏻여기를 참고해주세요. 

 


참고 : hello-bryan.tistory

728x90
반응형