可変ブログ

色々メモとか。とりあえず自分が分かるように。その後、なるべく人が見て分かるように。可変。

voronoi図を作ってみた。

ここのアルゴリズムを参考にして作りました。




voronoifield.hpp

#ifndef VORONOIFIELD_HPP
#define VORONOIFIELD_HPP

#include "opencv2/opencv.hpp"
#include <vector>
#include <omp.h>


class Voronoi{
	double CalcDistance(cv::Point a, cv::Point b){
		return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
	}
	void CellProcessing(cv::Point center, cv::Point side){
		if ((side.x < 0) || (image_size.x <= side.x) || (side.y < 0) || (image_size.y <= side.y)){ return; }

		if (cells[side.x][side.y].flag == MOTHER){
			if (cells[center.x][center.y].flag == NONE){
				cells[center.x][center.y].flag = DETECTED;
				cells[center.x][center.y].distance = CalcDistance(center, side);
				cells[center.x][center.y].point_mother = side;
			}
			else if (cells[center.x][center.y].flag == DETECTED){
				if (cells[center.x][center.y].distance > CalcDistance(center, side)){
					cells[center.x][center.y].distance = CalcDistance(center, side);
					cells[center.x][center.y].point_mother = side;
				}
			}
		}
		else if (cells[side.x][side.y].flag == DETECTED){
			if (cells[center.x][center.y].flag == NONE){
				cells[center.x][center.y].flag = DETECTED;
				cells[center.x][center.y].distance = CalcDistance(center, cells[side.x][side.y].point_mother);
				cells[center.x][center.y].point_mother = cells[side.x][side.y].point_mother;
			}
			else if (cells[center.x][center.y].flag == DETECTED){
				if (cells[center.x][center.y].distance > CalcDistance(center, cells[side.x][side.y].point_mother)){
					cells[center.x][center.y].distance = CalcDistance(center, cells[side.x][side.y].point_mother);
					cells[center.x][center.y].point_mother = cells[side.x][side.y].point_mother;
				}
			}
		}
	}
public:
	class cell_info{
	public:
		int flag;
		cv::Point point_mother;
		double distance;
		cell_info(){
			flag = 0;
			point_mother = cv::Point(-1, -1);
			distance = 0;
		}

	};
	cv::Point image_size;
	double max_distance;
	std::vector<std::vector<cell_info> > cells;

	int NONE;
	int MOTHER;
	int DETECTED;

	Voronoi(){
		NONE = 0;
		MOTHER = 1;
		DETECTED = -1;
	}
	Voronoi(cv::Point size){
		NONE = 0;
		MOTHER = 1;
		DETECTED = -1;

		SetMap(size);
	}
	void SetMap(cv::Point size){
		image_size = size;
		cells = std::vector<std::vector<cell_info> >(image_size.x, std::vector<cell_info>(image_size.y));
		max_distance = CalcDistance(cv::Point(0, 0), size);
	}
	void SetPoints(std::vector<cv::Point> points){
		for (std::vector<cv::Point>::iterator itr = points.begin(); itr < points.end(); ++itr){
			if ((itr->x < 0) || (image_size.x <= itr->x) || (itr->y < 0) || (image_size.y <= itr->y)){ return; }
			cells[itr->x][itr->y].flag = MOTHER;
		}
	}
	void CreateVoronoi(){
		for (int k = image_size.x; k >= 1; k /= 2){
			double naname = sqrt(k*k + k* k);
#pragma omp parallel for
			for (int i = 0; i < image_size.x; ++i){
				for (int j = 0; j < image_size.y; ++j){
					CellProcessing(cv::Point(i, j), cv::Point(i - k, j - k));
					CellProcessing(cv::Point(i, j), cv::Point(i + k, j - k));
					CellProcessing(cv::Point(i, j), cv::Point(i - k, j + k));
					CellProcessing(cv::Point(i, j), cv::Point(i + k, j + k));
					CellProcessing(cv::Point(i, j), cv::Point(i, j - k));
					CellProcessing(cv::Point(i, j), cv::Point(i, j + k));
					CellProcessing(cv::Point(i, j), cv::Point(i - k, j));
					CellProcessing(cv::Point(i, j), cv::Point(i + k, j));
				}
			}
		}
	}
	void GetImage(cv::Mat &image){
#pragma omp parallel for
		for (int i = 0; i < image_size.x; ++i){
			for (int j = 0; j < image_size.y; ++j){
				image.at<unsigned char>(cv::Point(i, j)) = cells[i][j].distance * (512 / max_distance);
			}
		}
	}
	void GetData(cv::Mat &image, double max_d){
#pragma omp parallel for
		for (int i = 0; i < image_size.x; ++i){
			for (int j = 0; j < image_size.y; ++j){
				image.at<double>(cv::Point(i, j)) = cells[i][j].distance / max_d;
			}
		}
	}
};

#endif




main.cpp

#include "voronoifield.hpp"

/*標準入出力ライブラリ*/
#include <iostream>
/*可変長リストライブラリ*/
#include <vector>
/*OpenCVライブラリ*/
#include "opencv2/opencv.hpp"
#include "opencv2/highgui/highgui_c.h"
/*処理時間測定用ライブラリ*/
#include <time.h>

#include <omp.h>

using namespace std;
using namespace cv;


int main() {
	int i = 2;
	Voronoi voronoi(Point(128 * i, 128 * i));

	//vector<Point> points(7);

	//points[0] = Point(32 * i, 32 * i);
	//points[1] = Point(20 * i, 10 * i);
	//points[2] = Point(4 * i, 50 * i);
	//points[3] = Point(50 * i, 33 * 8);
	//points[4] = Point(100 * i, 100 * i);
	//points[5] = Point(100 * i, 10 * i);
	//points[6] = Point(10 * i, 100 * i);


	vector<Point> points;
	for (int x = 100; x < 140; ++x){
		for (int y = 100; y < 130; ++y){
			points.push_back(Point(x, y));
		}
	}

	for (int x = 10; x < 14; ++x){
		for (int y = 10; y < 13; ++y){
			points.push_back(Point(x, y));
		}
	}

	voronoi.SetPoints(points);
	voronoi.CreateVoronoi();

	Mat image = Mat(voronoi.image_size, CV_8UC1, Scalar::all(0));
	voronoi.GetImage(image);
	imshow("voronoi", image);
	waitKey(0);

	return 0;

}