aa develop

開発と成長

OpenCVで特徴点をもとに画像をボロノイ分割・ドロネー分割する

この前に,ランダムに選んだ母点をもとに画像をボロノイ分割,ドロネー分割して,モザイク画像を生成した.

今回は,母点の粗密がいい感じになることを期待して,画像の特徴点をもとに分割する. それぞれの特徴検出器のパラメータ設定は適当.

固有値に基づく特徴点検出

特徴点

f:id:aa_debdeb:20160714112351j:plain

ボロノイ図

f:id:aa_debdeb:20160714112409j:plain

ドロネー分割

f:id:aa_debdeb:20160714112429j:plain

Harris検出器に基づく特徴点検出

特徴点

f:id:aa_debdeb:20160714112443j:plain

ボロノイ図

f:id:aa_debdeb:20160714112459j:plain

ドロネー分割

f:id:aa_debdeb:20160714112513j:plain

FAST検出器に基づく特徴点検出

特徴点

f:id:aa_debdeb:20160714112530j:plain

ボロノイ図

f:id:aa_debdeb:20160714112546j:plain

ドロネー分割

f:id:aa_debdeb:20160714112600j:plain

Star検出器に基づく特徴点検出

特徴点

f:id:aa_debdeb:20160714112618j:plain

ボロノイ図

f:id:aa_debdeb:20160714112632j:plain

ドロネー分割

f:id:aa_debdeb:20160714112649j:plain

SIFT検出器に基づく特徴点検出

特徴点

f:id:aa_debdeb:20160714112705j:plain

ボロノイ図

f:id:aa_debdeb:20160714112720j:plain

ドロネー分割

f:id:aa_debdeb:20160714112738j:plain

SURF検出器に基づく特徴点検出

特徴点

f:id:aa_debdeb:20160714112755j:plain

ボロノイ図

f:id:aa_debdeb:20160714112813j:plain

ドロネー分割

f:id:aa_debdeb:20160714112836j:plain

MSER検出器に基づく特徴点検出

特徴点

f:id:aa_debdeb:20160714112856j:plain

ボロノイ図

f:id:aa_debdeb:20160714112913j:plain

ドロネー分割

f:id:aa_debdeb:20160714112928j:plain

ORB検出器に基づく特徴点検出

特徴点

f:id:aa_debdeb:20160714112942j:plain

ボロノイ図

f:id:aa_debdeb:20160714112954j:plain

ドロネー分割

f:id:aa_debdeb:20160714113009j:plain

FAST検出器+Gridアダプタ に基づく特徴点検出

特徴点

f:id:aa_debdeb:20160714113026j:plain

ボロノイ図

f:id:aa_debdeb:20160714113043j:plain

ドロネー分割

f:id:aa_debdeb:20160714113056j:plain

FAST検出器+Pyramidアダプタ に基づく特徴点検出

特徴点

f:id:aa_debdeb:20160714113114j:plain

ボロノイ図

f:id:aa_debdeb:20160714113131j:plain

ドロネー分割

f:id:aa_debdeb:20160714113148j:plain

main.cpp


#include 
#include "opencv2/opencv.hpp"
#include "opencv2/nonfree/nonfree.hpp"

int main(int argc, const char * argv[]) {
    cv::Mat img = cv::imread("lena.jpg", 1);
    if(img.empty()) return -1;
    
    cv::Mat gray_img;
    cv::cvtColor(img, gray_img, CV_BGR2GRAY);
    cv::normalize(gray_img, gray_img, 0, 255, cv::NORM_MINMAX);
    
    std::vector keypoints;
    std::vector::iterator itk;
    cv::GoodFeaturesToTrackDetector detector(1600, 0.01, 5, 3); // 固有値に基づく特徴点検出
//    cv::GoodFeaturesToTrackDetector detector(1600, 0.01, 5, 3, true); // Harris検出器に基づく特徴点検出
//    cv::FastFeatureDetector detector(25, false); // FAST検出器に基づく特徴点検出
//    cv::StarFeatureDetector detector(16, 5); // Star検出器に基づく特徴点検出
//    cv::SiftFeatureDetector detector(0.001, 3.0); // SIFT検出器に基づく特徴点検出
//    cv::SurfFeatureDetector detector(100); // SURF検出器に基づく特徴点検出
//    cv::MserFeatureDetector detector; // MSER検出器に基づく特徴点検出
//    cv::OrbFeatureDetector detector(1500); // ORB検出器に基づく特徴点検出
//    cv::GridAdaptedFeatureDetector detector(new cv::FastFeatureDetector(10), 5000, 5, 5); // FAST検出器+Gridアダプタ に基づく特徴点検出
//    cv::PyramidAdaptedFeatureDetector detector(new cv::FastFeatureDetector(10), 3); // FAST検出器+Pyramidアダプタ に基づく特徴点検出

    detector.detect(img, keypoints);
    cv::Mat feature_img = img.clone();
    
    cv::Subdiv2D subdiv;
    subdiv.initDelaunay(cv::Rect(0, 0, img.rows, img.cols));
    std::vector points;
    
    for(itk = keypoints.begin(); itk!=keypoints.end(); ++itk) {
        cv::circle(feature_img, itk->pt, 5, cv::Scalar(184, 210, 0), 1, CV_AA);
        points.push_back(itk->pt);
    }

    points.push_back(cv::Point2f(0, 0));
    points.push_back(cv::Point2f(img.rows - 1, 0));
    points.push_back(cv::Point2f(0, img.cols - 1));
    points.push_back(cv::Point2f(img.rows - 1, img.cols - 1));
    subdiv.insert(points);
    
    // ボロノイモザイクの作成
    std::vector idx;
    std::vector> facetLists;
    std::vector facetCenters;
    subdiv.getVoronoiFacetList(idx, facetLists, facetCenters);
    
    cv::Mat voronoi_img = cv::Mat::zeros(img.rows, img.cols, CV_8UC3);
    for(auto facetList = facetLists.begin(); facetList != facetLists.end(); facetList++){
        cv::Point *vertices = new cv::Point[facetList->size()];
        cv::Vec3f polyColor = cv::Vec3f(0, 0, 0);
        int polyColorNum = 0;
        for(int i = 0; i < facetList->size(); i++){
            cv::Point vertex = facetList->at(i);
            vertices[i] = vertex;
            if(0 <= vertex.x && vertex.x < img.rows && 0 <= vertex.y && vertex.y < img.cols){
                polyColor += img.at(vertex.y, vertex.x);
                polyColorNum++;
            }
        }
        polyColor /= float(polyColorNum);
        cv::fillConvexPoly(voronoi_img, vertices, int(facetList->size()), cv::Scalar(polyColor[0], polyColor[1], polyColor[2]), CV_AA);
        delete[] vertices;
    }
    
    // ドロネーモザイクの作成
    std::vector triangles;
    subdiv.getTriangleList(triangles);
    
    cv::Mat dalaunay_img = cv::Mat::zeros(img.rows, img.cols, CV_8UC3);
    for(auto it = triangles.begin(); it != triangles.end(); it++)
    {
        cv::Vec6f &vec = *it;
        cv::Point vertices[3];
        vertices[0] = cv::Point(vec[0], vec[1]);
        vertices[1] = cv::Point(vec[2], vec[3]);
        vertices[2] = cv::Point(vec[4], vec[5]);
        cv::Vec3f polyColor = cv::Vec3f(0, 0, 0);
        polyColor += img.at(vertices[0].y, vertices[0].x);
        polyColor += img.at(vertices[1].y, vertices[1].x);
        polyColor += img.at(vertices[2].y, vertices[2].x);
        polyColor /= float(3);
        cv::fillConvexPoly(dalaunay_img, vertices, 3, cv::Scalar(polyColor[0], polyColor[1], polyColor[2]), CV_AA);
    }
    
    
    cv::imshow("feature", feature_img);
    cv::imshow("voronoi", voronoi_img);
    cv::imshow("dalaunay", dalaunay_img);

    cv::waitKey(0);
    
    
}

OpenCV/dalaunay_feature at master · aa-debdeb/OpenCV

参考