やりたいこと
xcodeでswiftプロジェクトを作成し、swift内にopenCVを入れる事で画像処理を楽にする。
iPhoneカメラで撮影した画像を2値化したり、エッジ検出する
※いつものように個人macでの実装なので業務関係ない
open cvのダウンロード
以前ダウンロードまでは実施したので、この記事では実装をしていく。
インストールしてない人は、以下記事参考
Object-cからopen cvを呼び出す
Nextでファイル作成を実行するとポップアップが表示する。
Object-Cを実行するために必要なbridging header fileをXcodeが自動生成してくれる。
Object-C++ファイルにする為に、OpenCVSample.mファイルを.mmに変更する
#import "OpenCVSample.h"
#import <UIKit/UIKit.h>
@interface OpenCVSample : NSObject
+(UIImage *)GrayScale:(UIImage *)image;
@end
最初は撮影した画像をグレースケールに変換する
#import <opencv2/opencv.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
swiftからObjective-Cを実行
ViewControllerに撮影、撮影後の表示をUIImagePickerControllerで実装
storybordなどでカメラボタンを配置してください。今回は割愛してオブジェクトが配置された前提にします。
//フレームワークをインポートする
import UIKit
//ビュー用のクラス
class ViewController: UIViewController, UIImagePickerControllerDelegate,UINavigationControllerDelegate{
@IBOutlet weak var imageView: UIImageView!
let imagePicker = UIImagePickerController()
override func viewDidLoad() {
super.viewDidLoad()
//画像の初期設定みたいなもの
//tyoeで.cameraを.photoLibraryに変更にすれば写真フォルダから参照する
imagePicker.delegate = self
imagePicker.sourceType = .camera
imagePicker.allowsEditing = true
}
//カメラでuse select選択すると関数起動
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
//画像情報定義
if let userPickedImage = info[UIImagePickerController.InfoKey.editedImage] as? UIImage {
imageView.image = userPickedImage
guard let ciimage = CIImage(image:userPickedImage) else {
fatalError("エラーじゃ取得できぬ")
}
//画像を引数にdetect関数起動
detect(image: ciimage)
}
//ピッカー解除
imagePicker.dismiss(animated: true, completion: nil)
}
//画像処理関数
func detect(image:CIImage) {
let thresholdImage = imageView.image
let gray = OpenCVSample.grayScale(thresholdImage)
//最終表示画像
imageView.image = gray
}
//ピッカー解除
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
imagePicker.dismiss(animated: true,completion: nil)
}
@IBAction func cameraTapped(_ sender: UIBarButtonItem) {
present(imagePicker, animated: true, completion: nil)
}
}
実機へビルドして動作確認
iPhoneで撮影した画像がグレースケール化されている事が分かる
画像が回転してしまっているので、別途記述する必要はあり。
画像を2値化してみる
先程記述したobj-c++ファイルを修正する。
以下二値化部分切り取り
//引数(入力画像、出力画像、輝度閾値、輝度最大値、タイプ)
cv::threshold(gray, binary, 110, 255, cv::THRESH_BINARY);
#import <opencv2/opencv.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);
//2値化処理
cv::Mat binary;
cv::threshold(gray, binary, 110, 255, cv::THRESH_BINARY);
// 引数の画像をbinaryに変更する
UIImage * grayImg = MatToUIImage(binary);
return grayImg;
}
@end
まとめ
今回は単純2値化のみしか実装してないが、適応的閾値処理を活用して影を2値化時に検出しない様にする必要はあります。
画像の回転を元に戻すなどありますが、参考になれば幸いです
以下参考にさせていただいた記事