7
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

SVG + opencvでベクター形式の図形を出力

Last updated at Posted at 2017-12-09

#SVG形式
個人的にベクター形式の画像が必要になり,かといってepsをプログラムで出力するのは大変そうだ。と思っていたところ,以下のようなSVGと呼ばれるHTMLのように簡単に書けるベクターフォーマットがあることがわかりました。

なんか簡単そうですね。
C++の簡易ラッパーは以下で見つけることができました。

これにはPolyline関数はなかったのですが、簡単に作れそうだったので、上記を参考にopencvのPoint形式でSVG出力できるクラスを作ってみました。透過色も指定できるようです。とりあえず、僕はPolylineが使えれば十分だったので、それしかないのですが、ほかの描画関数も簡単に追加できると思います。

svg.hのコード

svg.h
#include <fstream>
#include <iostream>

#include <opencv2/opencv.hpp>

using namespace std;
using namespace cv;

class svg_drawer {

	std::ofstream fout;
	int width, height;

public:

	svg_drawer(char *filename, int w, int h) {

		fout.open(filename);
		width  = w;
		height = h;
		
		fout << "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" width= \"" << width << "\" height=\"" << height << "\">" << std::endl;

	}
	~svg_drawer(void) {
		fout << "</svg>" << std::endl;
		return;
	}

	void drawPolyLine(const vector<Point2d> & pts, Scalar col, int stroke_width, Scalar fcol, int dash = 0, double opacity = 1.0) {

		char stroke_color[255];
		char fill_color[255];
		sprintf(stroke_color, "rgb(%d,%d,%d)", (int) col[2], (int) col[1], (int) col[0]);
		sprintf(fill_color,   "rgb(%d,%d,%d)", (int)fcol[2], (int)fcol[1], (int)fcol[0]);

		fout << "<polyline points=\"";

		int N = pts.size();
		for (int i = 0; i <= N; i++) {

			double vx = pts[i%N].x;
			double vy = pts[i%N].y;

			fout << vx << "," << vy << " ";
		}
		fout << "\"";
		if (dash > 0) fout << " stroke-dasharray=\"" << dash << "\"";
		fout << " stroke-width=\"" << stroke_width << "\" stroke=\"" << stroke_color << "\" fill=\"" << fill_color << "\" fill-opacity=\"" << opacity << "\"/>" << std::endl;

		return;
	}
	void drawLine(const double x0, const double y0, const double x1, const double y1, int stroke_width, Scalar col, int dash = 0, double opacity = 1.0) {

		char stroke_color[255];
		sprintf(stroke_color, "rgb(%d,%d,%d)", (int)col[2], (int)col[1], (int)col[0]);
		
		fout << "<line x1=\"" << x0 << "\" y1=\"" << y0 << "\" x2=\"" << x1 << "\" y2=\"" << y1 << "\"";
		if (dash > 0) fout << " stroke-dasharray=\"" << dash << "\"";
		fout << " stroke-width=\"" << stroke_width << "\" stroke=\"" << stroke_color << "\" stroke-opacity=\"" << opacity << "\"/>" << std::endl;

		return;
	}
};

##サンプル
上のクラスを使って適当な図形を描画します。svg.hを読み込むだけで使えます。

main.cpp
#include <stdio.h>
#include "svg.h"

int main(){
	
	svg_drawer sd("test.svg", 500,500);


	int div = 360;

	for (int n = 0; n < 50; n++) {
		vector<Point2d> pts;
		int   dx = rand() % 500;
		int   dy = rand() % 500;
		float dr = (rand() % 100) / 100.0;
		float dt = rand() % 30 + 3;
		for (int i = 0; i < div; i++) {
			float t = 2 * 3.14159 * i / float(div);
			float x, y, r;
			r = dr * (50 + sin(dt * t) * 20);
			x = dx + r * cos(t);
			y = dy + r * sin(t);
			pts.push_back(Point2d(x, y));
		}

		sd.drawPolyLine(pts, CV_RGB(rand() % 255, 0, 0), 1, CV_RGB(rand() % 255, rand() % 192, rand() % 32), 0, 0.5);
	}

	return 0;
}

実行するとtest.svgというファイルができます。ファイルをダブルクリックしてブラウザなどで開けます。ブラウザ上でCtrを押しながらマウスホイールすると拡大できます。ベクター形式なので拡大してもきれいです。イラストレータなどのペイントツールで開いて、epsに変換すればパワーポイントやlatexに図を張り付けることができます。

適当に作った謎の図形。

test.svgをブラウザで開く

7
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?