茶漬けの技術メモ

Golang, Rubyで趣味開発します。テックニュース書いたり。ガジェット触ったり。

【Swift】OpenCVを使ってみる 5 〜特徴点を検出してみる〜

この記事は、

【Swift】OpenCVを使ってみる 1 〜導入編〜 - 茶漬けの技術メモ

【Swift】OpenCVを使ってみる 2 〜バージョンを表示〜 - 茶漬けの技術メモ

【Swift】OpenCVを使ってみる 3 〜カラー画像をグレースケールに変換〜 - 茶漬けの技術メモ

【Swift】OpenCVを使ってみる 4 〜テンプレートマッチングしてみる〜 - 茶漬けの技術メモ

これらの記事の続きとなってます。

それでは今回は、OpenCVを使って特徴点を検出していこうと思います。


OpenCVを使って特徴点を検出する

画像から特徴点を検出するためのアルゴリズムはいくつか種類があるようですが、今回はOpencv2.0 から実装されている、FAST というアルゴリズムを決めうちで使っています。
ただアルゴリズムの種類によってはこのソースでは動かない場合がありました。。。そこらへんの理由とか調べないとなー。

以下に実際のソースを貼っていきます。
import <opencv2/highgui/ios.h>を忘れずに。

OpenCVWrapper.mm

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

@implementation OpenCVWrapper

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

+(UIImage * ) makeGrayFromImage:(UIImage *)image
{
    // transform UIImagge to cv::Mat
    cv::Mat imageMat;
    UIImageToMat(image, imageMat);
    
    // if the image already 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);
    
    return MatToUIImage(grayMat);
}

+ (UIImage *)match :(UIImage *)srcImage templateImage:(UIImage *)templateImage {
    
    cv::Mat srcMat = [OpenCVHelper cvMatFromUIImage:srcImage];
    cv::Mat tmpMat = [OpenCVHelper cvMatFromUIImage:templateImage];
    
    // 入力画像をコピー
    cv::Mat dst = srcMat.clone();
    
    // マッチング
    cv::matchTemplate(srcMat, tmpMat, dst, cv::TM_CCOEFF);
    
    double min_val, max_val;
    cv::Point min_loc, max_loc;
    cv::minMaxLoc(dst, &min_val, &max_val, &min_loc, &max_loc);
    
    // 結果の描画
    cv::rectangle(srcMat, max_loc, cv::Point(max_loc.x + tmpMat.cols, max_loc.y + tmpMat.rows), CV_RGB(0, 255, 0), 2);
    
    return [OpenCVHelper UIImageFromCVMat:srcMat];
}


+ (UIImage *)detectKeypoints:(UIImage *)srcImage
{
    cv::Mat srcMat = [OpenCVHelper cvMatFromUIImage:srcImage];
    
//    Ptr<FeatureDetector> FeatureDetector::create("SURF");
    
    // detector 生成
    cv::Ptr<cv::FeatureDetector> detector = cv::FeatureDetector::create("FAST");
    // 特徴点抽出
    std::vector<cv::KeyPoint> keypoints;
    detector->detect(srcMat, keypoints);
    
    printf("%lu keypoints are detected.\n", keypoints.size());
    
    // 特徴点を描画
    cv::Mat dstMat;
    
    dstMat = srcMat.clone();
    for(int i = 0; i < keypoints.size(); i++) {
        
        cv::KeyPoint *point = &(keypoints[i]);
        cv::Point center;
        int radius;
        center.x = cvRound(point->pt.x);
        center.y = cvRound(point->pt.y);
        radius = cvRound(point->size*0.25);
        
        cv::circle(dstMat, center, radius, cvScalar(255,255,0));
    }
    return [OpenCVHelper UIImageFromCVMat:dstMat];
}

@end


OpenCVWrapper.h

#import <UIKit/UIKit.h>

@interface OpenCVWrapper : NSObject

// funciton to get opencv version
+(NSString * ) openCVVersionString;

// function to convert image to grayscale
+(UIImage * ) makeGrayFromImage:(UIImage * ) image;

// function to match
+ (UIImage *)match :(UIImage *)srcImage templateImage:(UIImage *)templateImage;

// function do detect feature points
+ (UIImage *)detectKeypoints:(UIImage *)srcImage;

@end


ViewController.swift

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var openCVVersionLabel: UILabel!
    @IBOutlet weak var birdImageView: UIImageView!
    let original_image = UIImage(named: "bird.jpg")
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        
        openCVVersionLabel.text = OpenCVWrapper.openCVVersionString()
    }

    @IBAction func detect(_ sender: UIButton) {
        birdImageView.image = OpenCVWrapper.detectKeypoints(original_image)
    }
}


これでアプリを実行すると。

これが、

f:id:biwako_no_otyazuke:20161127164007p:plain:w400
こうなります。

f:id:biwako_no_otyazuke:20161127164043p:plain:w400

画像の特徴点が黄色く描画されていることがわかると思います。
今回は、特徴点を検出しただけですが、OpenCV ではマッチングのためのクラスもあるようなので、これらを使って面白そうなものを色々作れそうな香りがプンプンします。
近いうちにOpenCV を使ったアプリ開発とかしたいな〜。


Thanks

特徴点を用いた物体認識 - ComputerVisionまとめの部屋

[OpenCV] いまさら局所特徴量で物体検出!? - Qiita

iOS / OpenCV 3.0 で画像の特徴点を検出する(AKAZE, SIFT, SURF, ORB) - Qiita