見出し画像

SwiftでOpenCVを使ってみた

はじめに

Pythonでは使ったことがありましたが、Swiftでも使えるということで、実際にアプリを作ってみました。

完成イメージ

画像1

使用環境

● OS:macOS Big Sur 11.3.1
● Xcode:12.5
● Swift:5.4
● Objective-C++
● OpenCV:4.3.0

環境構築

cocopodsにOpenCVを導入

cocopodsにライブラリを導入する方法 → こちら

podfile

# Uncomment the next line to define a global platform for your project
# platform :ios, '9.0'

target 'OpenCV_Swift' do
 # Comment the next line if you don't want to use dynamic frameworks
 use_frameworks!

 # Pods for OpenCV_Swift
 pod "OpenCV"

 target 'OpenCV_SwiftTests' do
   inherit! :search_paths
   # Pods for testing
 end

 target 'OpenCV_SwiftUITests' do
   # Pods for testing
 end

end

Swiftでビルド出来る様に、Objective-C++でOpenCVのメソッドを書き込む

Swiftで直接ビルドできないため、下記の手順に処理をする
Objective-C → 
Objective-C++ → Swift

手順はこちらを参照 → 【swift4.2】swiftでOpenCVを使ってみる

Bridging-Header.hにObjective-Cクラスのヘッダを追加

 #import  "OpenCVSample.h"

OpenCVSample.hにラッパーメソッドを定義

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

NS_ASSUME_NONNULL_BEGIN

@interface OpenCVSample : NSObject
+(UIImage *)GrayScale:(UIImage *)image;
@end

NS_ASSUME_NONNULL_END

OpenCVSample.mmに処理を実装

//
//  OpenCVSample.mm
//  OpenCV_Swift
//
 #import  "opencv2/opencv.hpp" #import  "opencv2/imgproc.hpp" #import  "opencv2/imgcodecs.hpp" #import  "opencv2/imgcodecs/ios.h"
 #import  "OpenCVSample.h"

@implementation OpenCVSample
+(UIImage *)GrayScale:(UIImage *)image{
   // convert image to mat
   cv::Mat mat;
   UIImageToMat(image, mat);

   // convert mat to gray scale
   cv::Mat gray;
   cv::cvtColor(mat, gray, cv::COLOR_BGR2GRAY);

   // convert to image
   UIImage * grayImg = MatToUIImage(gray);

   return grayImg;
}
@end

実装

UI

Xcode上ではこんな感じです。

スクリーンショット 2021-09-25 22.17.25

PreviewでiPhone11、iPhone8 Plus、iPhone SE(1st generation)に見るとこんな感じです。

スクリーンショット 2021-09-25 22.19.03

レイアウトを付けているので、UIが崩れない様になっています。

1、UIButtonをwidthとheightを200に設定

スクリーンショット 2021-09-25 22.27.53

2、UIImageViewをwidthとheightを200、topを61に設定

スクリーンショット 2021-09-25 22.29.08

3、UIButtonとUIImageViewに horizontally in container を付ける

スクリーンショット 2021-09-25 22.28.28

スクリーンショット 2021-09-25 22.28.34

コード

//
//  ViewController.swift
//  OpenCV_Swift

import UIKit

class ViewController: UIViewController {
   
   @IBOutlet var profileImageButton: UIButton!
   
   @IBOutlet weak var grayScaleImage: UIImageView!
   
   
   override func viewDidLoad() {
       super.viewDidLoad()
       
       profileImageButton.layer.cornerRadius = 100
       profileImageButton.layer.borderWidth = 1
       let border = UIColor.black.cgColor
       profileImageButton.layer.borderColor = border
       profileImageButton.addTarget(self, action: #selector  (tappedProfileImageButton), for: .touchUpInside)
       grayScaleImage.layer.cornerRadius = 100
       grayScaleImage.layer.borderWidth = 1
       grayScaleImage.layer.borderColor = border
   }
   
   @objc private func tappedProfileImageButton() {
       print("tappedProfileImageButton")
       let imagePickerController = UIImagePickerController()
       imagePickerController.delegate = self
       imagePickerController.allowsEditing = true
       
       self.present(imagePickerController, animated: true, completion: nil)
   }
   
}

extension ViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate {
   func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
       if let editingImage = info[.editedImage] as? UIImage {
           profileImageButton.setImage(editingImage.withRenderingMode(.alwaysOriginal), for: .normal) } else if let originalImage = info[.originalImage] as? UIImage {
               profileImageButton.setImage(originalImage.withRenderingMode(.alwaysOriginal), for: .normal)
           }
       
       profileImageButton.setTitle("", for: .normal)
       profileImageButton.imageView?.contentMode = .scaleAspectFill
       profileImageButton.contentHorizontalAlignment = .fill
       profileImageButton.contentVerticalAlignment = .fill
       profileImageButton.clipsToBounds = true
       
       let image = profileImageButton.imageView?.image
       grayScaleImage.image = OpenCVSample.grayScale(image!)
       grayScaleImage.contentMode = .scaleAspectFill
       grayScaleImage.clipsToBounds = true
       
       dismiss(animated: true, completion: nil)
   }
}

おわりに

今回は、SwiftでOpenCVを使ったアプリを作り、学習して行きました。
またOpenCVを使ったアプリを作る際は、多機能を導入しているものを作りたいと思います。
最後まで読んで下さり、ありがとうございました。
この記事が参考になれば幸いです。

参考文献


この記事が気に入ったらサポートをしてみませんか?