読者です 読者をやめる 読者になる 読者になる

aa develop

開発と成長

OpenCVでドロネー分割・ボロノイ分割により画像のモザイクをつくる

OpenCV 画像処理

OpenCVのドロネー分割・ボロノイ分割の機能を使って,画像をランダムに設定した母点で分割し,モザイクのようにした.

入力画像

f:id:aa_debdeb:20160714112033j:plain

出力画像(ボロノイ分割/母点:100)

f:id:aa_debdeb:20160714112048j:plain

出力画像(ボロノイ分割/母点:500)

f:id:aa_debdeb:20160714112103j:plain

出力画像(ボロノイ分割/母点:3000)

f:id:aa_debdeb:20160714112117j:plain

出力画像(ボロノイ分割/母点:10000)

f:id:aa_debdeb:20160714112132j:plain

出力画像(ドロネー分割/母点:100)

f:id:aa_debdeb:20160714112146j:plain

出力画像(ドロネー分割/母点:500)

f:id:aa_debdeb:20160714112200j:plain

出力画像(ドロネー分割/母点:3000)

f:id:aa_debdeb:20160714112214j:plain

出力画像(ドロネー分割/母点:10000)

f:id:aa_debdeb:20160714112227j:plain

main.h

#include 
#include "opencv2/opencv.hpp"

int main(int argc, const char * argv[]) {
    cv::Mat img = cv::imread("lena.jpg", 1);
    if(img.empty()) return -1;
    
    cv::Subdiv2D subdiv;
    subdiv.initDelaunay(cv::Rect(0, 0, img.rows, img.cols));
    
    std::vector points;
    for(int i = 0; i < 10000; i++){
        cv::Point2f point = cv::Point2f(rand() % img.rows, rand() % img.cols);
        points.push_back(point);
    }
    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 = 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, 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 = 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, vertices, 3, cv::Scalar(polyColor[0], polyColor[1], polyColor[2]), CV_AA);
    }
    
    cv::imshow("voronoi", voronoi);
    cv::imshow("dalaunay", dalaunay);
    //cv::imwrite("voronoi.jpg", voronoi);
    //cv::imwrite("dalaunay.jpg", dalaunay);
    cv::waitKey(0);

}

OpenCV/dalaunay at master · aa-debdeb/OpenCV

参考