OpenNH

日常のひとこま(自分用のメモとかあれこれ)

Bezier曲線をC++, Python, Juliaで書いてみた

目次

はじめに

ベジエ曲線を題材にして、C++Python、Juliaでそれぞれのコードの書き方の違いをメモしておくための記事です。自分用のメモなのでコードの書き方などおかしなところがあるかもしないので、その時は指摘していただけると幸いです。

ベジエ曲線とは

ベジェ曲線(ベジェきょくせん、Bézier Curve)またはベジエ曲線とは、N 個の制御点から得られる N − 1 次曲線である。フランスの自動車メーカー、シトロエン社のド・カステリョ(英語版) とルノー社のピエール・ベジェにより独立に考案された。ド・カステリョの方が先んじていたが、その論文が公知とならなかったためベジェの名が冠されている[1]。コンピューター上で滑らかな曲線を描くのに2次ベジェ曲線 (Quadratic Bézier curve) や3次ベジェ曲線 (Cubic Bézier curve) などが広く利用されている。
出典:「ベジェ曲線 - Wikipedia

C++

// "Bezier_curves.cpp"
// @Fumihachi

#include <iostream>
#include <random>

#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/line_descriptor.hpp>

// OpecCVのライブラリの読み込み
#ifdef _DEBUG
#pragma comment(lib,"opencv_core330d.lib")
#pragma comment(lib,"opencv_highgui330d.lib")
#pragma comment(lib,"opencv_line_descriptor330d.lib")
#pragma comment(lib,"opencv_imgproc330d.lib")
#else
#pragma comment(lib,"opencv_core330.lib")
#pragma comment(lib,"opencv_highgui330.lib")
#pragma comment(lib,"opencv_line_descriptor330.lib")
#pragma comment(lib,"opencv_imgproc330.lib")
#endif

#define N_CTRL 4  // 制御点の個数
#define RANDAM 0  // 1->制御点をランダムに生成

// 二項係数nCrの計算
int comb(int n, int r)
{
    int num = n - r + 1, x = 1;

    if (n == r) 
        return 1;
    else if (n < r) 
        std::cout << "Error : please set n >= r" << std::endl;

    for (int i = 1; i <= r; i++)
        x = x*num++ / i;

    return x;
}

// Bernstein係数
float bernstein(int n, int i, float t)
{
    int k = 0;
    float a = 1.0f, b = 1.0f;

    for (k = 0; k < i; k++)
        a *= t;

    for (k = 0; k < n-i; k++) 
        b *= 1 - t;

    return float(comb(n, i)) * a * b;
}

// Bezier curve の算出
cv::Point2f bezier_curve(int n, float t, float *px, float *py)
{
    float x = 0.0f, y = 0.0f, B = 0.0f;

    for (int i = 0; i <= n; i++) {
        B  = bernstein(n, i, t);
        x += B * px[i];
        y += B * py[i];
    }

    return cv::Point2f(x,y);
}

int main(void)
{
    // 制御点の指定
    float px[N_CTRL] = { 0.605222, 0.697092, 2.45667, 5.75014 };
    float py[N_CTRL] = { 0.983481, 4.994620, 2.51148, 8.39767 };

    // ランダムに制御点を生成
#if RANDAM
    std::cout << "Use randam control points." << std::endl;
    std::random_device rnd;
    for (int i = 0; i < N_CTRL; ++i) {
        px[i] = 10.0f * float(rnd()) / std::random_device::max();
        py[i] = 10.0f * float(rnd()) / std::random_device::max();
        std::cout << "[x, y] = " << px[i] << ", " << py[i] << std::endl;
    }
#else
    std::cout << "Use default control points." << std::endl;
    for (int i = 0; i < N_CTRL; ++i)
        std::cout << "[x, y] = " << px[i] << ", " << py[i] << std::endl;
#endif // RANDAM


    // Bezier曲線
    std::vector<cv::Point2f> p;
    for (float t = 0; t <= 1.0; t += 0.01)
        p.push_back(bezier_curve(3, t, px, py));

    // openCVでグラフを描画
    float scale = 50.0;
    float margin = 10.0;

    cv::Mat img(cv::Size(500, 500), CV_8UC3, cv::Scalar(255, 255, 255));

    for (int i = 0; i < 4; i++) 
        cv::circle(img, 
            cv::Point2f(
                px[i] * scale + margin, 
                img.size().height-py[i] * scale - margin), 
            10, cv::Scalar(0, 0, 255));

    for (int i = 0; i < p.size()-1; i++) {
        cv::Point2f p0 = cv::Point2f(
            p[i].x*scale + margin, 
            img.size().height - p[i].y*scale - margin);
        cv::Point2f p1 = cv::Point2f(
            p[i+1].x*scale + margin, 
            img.size().height - p[i+1].y*scale - margin);
        cv::line(img, p0, p1, cv::Scalar(255, 0, 0));
    }

    cv::imshow("image", img);
    cv::waitKey(-1);
}

f:id:FounderLeis:20190902235538p:plain:w400
Bezier curve (cpp)

Python

# "Bezier_curves.py"
# @Fumihachi

import matplotlib.pyplot as plt
import numpy as np
from numpy.random import *
from scipy.special import comb


def bernstein(n, i, t):
    return comb(n, i) * t ** i * (1 - t) ** (n - i)


def bezier_curve(n, t, p):
    return np.dot([bernstein(n, i, t) for i in range(n + 1)], p)


# 制御点をランダムに生成
N = 4  # Number of control points
L = 10  # Max range of X, Y
p = rand(N, 2) * L  # Create control points
p = p[p[:, 0].argsort(), :]  # Sort to x-axis
print(p)

# Calculate
x = np.array([bezier_curve(N - 1, t, p) for t in np.linspace(0, 1, 100)])

# Draw
plt.plot(p[:, 0], p[:, 1], marker='o')
plt.plot(x[:, 0], x[:, 1])
plt.title('Bezier curve')
plt.xlabel('X')
plt.ylabel('Y')
plt.grid('on')
plt.show()

f:id:FounderLeis:20190902235841p:plain:w400
Bezier curve (python)

Julia

# "Bezier_curves.jl"
# @Fumihachi

using PyPlot
using LinearAlgebra

function bernstein(n, i, t)
    return binomial(n, i) * t^i * (1-t)^(n-i)
end

function bezier_curve(n, t, p)
    x = [dot([bernstein(n, i, t) for i = 0:n], p[:,1]) dot([bernstein(n, i, t) for i = 0:n], p[:,2])];
    return x
end

# Create control points at random
N = 4;
L = 10;
p = rand(N, 2) * L;
p = p[sortperm(p[:,1]), :]

# Calculate
nt  = 100
x   = Array{Float64,2}(undef, nt+1, 2)
for k = 1:nt+1
    x[k,:] = bezier_curve(N - 1, (k-1)/100, p)
end

# Draw
plot(p[:,1], p[:,2], marker="o")
plot(x[:,1], x[:,2])
title("Bezier curve")
xlabel("X")
ylabel("Y")
grid("on")
show()

f:id:FounderLeis:20190903000107p:plain:w400
Bezier curve (julia)

C++で任意行数のテキストデータ読み込み

やさしいC++ 第4版 (「やさしい」シリーズ)

やさしいC++ 第4版 (「やさしい」シリーズ)

目次

  • 目次
  • はじめに
  • 任意行数のテキスト読み込み
    • サンプル入力
    • サンプルコード
    • サンプル出力
  • コメントアウト付きテキストの読み込み
  • 最後に

はじめに

テキストファイルに記述された任意の行数の情報をプログラム上で読み取る必要があったので、その際のコードをメモしておきます。VisualStudio2015で動作確認済みです。

特筆すべきことはなく、他にテキスト読み込みのコードを載せている方々と異なるのは、テキスト情報の行数が変わった場合に対応できるよう、格納する型をstd::vector<std::string>としてあるくらいかと思います。

続きを読む

Windows8.1からWindows10へアップグレード【2019年3月版】

久しく使用していなかったWindows8.1のLet's noteをWindows10に今更ながらアップグレードすることしたのでそのメモです。

目次

  • 目次
  • 環境
  • Window10アップグレードツールのダウンロード
  • Window10へアップグレード
  • Intelグラフィックカードが対応していないと言われた場合の対処
    • 対処1 : Intel HD 4000 Graphics Driver For Windows 10
    • 対処2:インテル® HD グラフィックス 4000 用のドライバダウンロード
  • 再度Window10へアップグレード


環境

PC:Panasonic Let's note CF-AX2
OS : Windows8.1 Pro → Windows10 Pro


Window10アップグレードツールのダウンロード

Windows10にアップグレードするためのツールをMicrosoftの公式ページからダウンロードします。以下のリンクから、「ツールを今すぐダウンロード」をクリックしダウンロードできます。
https://www.microsoft.com/ja-jp/software-download/windows10
f:id:FounderLeis:20190317225721p:plain


Window10へアップグレード

以下のようなファイルがダウンロードされるはずなので、実行します。
f:id:FounderLeis:20190317230551p:plain

続きを読む

LaTeX 複数ページPDFから図を挿入する方法

[改訂第7版]LaTeX2ε美文書作成入門

[改訂第7版]LaTeX2ε美文書作成入門

はじめに

LaTeXにPDFから図を入れる際に、複数ページあるPDFファイルから任意のページの図を挿入したいことがあったのでメモしておきます。

環境:

  • Windows10 Pro
  • TeX Live 2017



\includegraphicsにpageオプションを付ける

以下のように\includegraphicsのオプションに"page=<読み込みたいページ番号>"を追加することで任意のページの画像を張り付けることができます。

\documentclass[11pt,a4j]{jarticle}

\usepackage[dvipdfmx,hiresbb]{graphicx}

\title{複数ページPDFから図を挿入する方法}
\author{ふみ八}

\begin{document}

\maketitle

% PDF 1ページ目の画像
\begin{figure}[!hbt]
  \centering
  \includegraphics[width=0.5\textwidth, page=1]{Sample.pdf}
  \caption{Sample p.1}
  \label{Sample p.1}
\end{figure}

% PDF 2ページ目の画像
\begin{figure}[!hbt]
  \centering
  \includegraphics[width=0.5\textwidth, page=2]{Sample.pdf}
  \caption{Sample p.2}
  \label{Sample p.2}
\end{figure}

\end{document}

サンプル用のPDFおよびtexドキュメントは以下においてあります。
Sample.pdf
Topic_Multi_page_PDF.tex




出力結果

上記のコードを実行するとこのようなページが作成されます。
f:id:FounderLeis:20190215163437p:plain
 

LaTexにソースコードを貼る方法

はじめに

LaTexで論文を書く中でプレグラムのソースコードを載せる必要があったので、そのメモです。ソースコードをそのままLaTexに張り付けちゃうと記号とかインデントとかぐちゃぐちゃになってしまうので、コピペで簡単にきれいに貼れる方法を調べました。


ソースコードを貼る方法

まず、LaTexソース内でパッケージ定義をしている部分(\documentclassから\begin{document}の間)に以下の一行を追加します。

<英語フォントのみの場合>
\usepackage{listings}

<日本語フォントを含む場合>
\usepackage{listings, jlisting}

<色を使う場合は以下も追加>
\usepackage{color}

私の場合はlisting.styはデフォで入っていましたが,jlisting.styはなかったので,ダウンロードして追加しました.texliveを利用している場合は、スタイルファイル(.sty)が格納されるディレクトリは以下のところです。

/usr/local/texlive/2017/texmf-dist/tex/latex/listings/

そして、格納したカレントディレクトリ上でGitBashなどで以下のコマンドを打てば使えるようになります。

$ mktexlsr

f:id:FounderLeis:20181212013524p:plain
 
次にLaTexソースの本文中に以下のようにプログラムのソースコードを貼り付けます。これでLatexソースコードを貼れたはずです。

\begin{lstlisting}[basicstyle=\ttfamily\footnotesize, frame=single]
(ここにプログラムソース)
\end{lstlisting}



スタイルファイルのダウンロード

listingsのスタイルファイル >> こちら
jlistingのスタイルファイル >> こちら
 
 

個人的な初期設定

% ソースコードを挿入するための設定
\usepackage{jlisting}
\usepackage{listings}
\usepackage{color}
\definecolor{OliveGreen}{rgb}{0.0,0.6,0.0}
\definecolor{Magenta}{cmyk}{0, 1, 0, 0}
\definecolor{colFunc}{rgb}{1,0.07,0.54}
\definecolor{CadetBlue}{cmyk}{0.62,0.57,0.23,0}
\definecolor{Brown}{cmyk}{0,0.81,1,0.60}
\definecolor{colID}{rgb}{0.63,0.44,0}
\lstset{
language={Matlab},                   %言語の指定
basicstyle={\ttfamily\small},        %書体の指定
backgroundcolor={\color[gray]{.95}}, %背景色と透過度
keywordstyle={\color{blue}},         %キーワード(int, ifなど)の書体指定
commentstyle={\color{OliveGreen}},   %注釈の書体 
stringstyle=\color{Magenta},         %文字列
frame=single,                        %枠縁(leftline,topline,bottomline,lines,trBL,shadowbox, single)
numbers=left,                        %行番号表示
numberstyle={\ttfamily\small},       %行番号の書体指定
breaklines=true,                     %折り返し(自動改行)
breakindent = 10pt,                  %自動改行後のインデント量(デフォルトでは20[pt])	
tabsize=2,                           %タブの大きさ
captionpos=t                         %キャプションの場所(t,b : "tb"ならば上下両方に記載)
}
\renewcommand{\lstlistingname}{Code} % キャプション名の指定

 

MATLABのコード(.m)をきれいに貼る方法

こちらの方のサイトが参考になります。私の環境ではエラーが出てしまったので使わなかったですが…
http://castanophilia.hatenadiary.com/entry/2014/11/24/091708castanophilia.hatenadiary.com

OpenCVでchArUcoマーカー/コーナー検出

使用する関数の説明

  • cv::aruco::detectMarkers(...) : マーカー検出関数

<引数>

  1. 入力画像
  2. 検索するマーカーの種類
  3. 検出されたマーカーコーナーのベクトル(Nx4配列)
  4. 検出されたマーカーIDのベクトル(int Nx1配列)
  5. マーカー検出パラメータ

>>OpenCV: ArUco Marker Detection

  • cv::aruco::PREDEFINED_DICTIONARY_NAME : マーカー種類のインデックス

>>OpenCV: ArUco Marker Detection

  • cv::aruco::drawDetectedMarkers(...) : 検出マーカー描画関数

<引数>

  1. 入出力画像
  2. 検索するマーカーの種類
  3. 検出されたマーカーコーナーのベクトル(Nx4配列)
  4. 検出されたマーカーIDのベクトル(int Nx1配列)

>>OpenCV: ArUco Marker Detection

  • cv::aruco::CharucoBoard::create(...) : ChArUcoボードオブジェクトの生成

<引数>

  1. X方向のパターン数
  2. Y方向のパターン数
  3. パターン1個の物理サイズ [m]
  4. マーカー1個の物理サイズ [m]
  5. マーカー種類のディクショナリ

>>OpenCV: cv::aruco::CharucoBoard Class Reference



C++サンプルプログラム(単純な検出&描画)

#include <iostream>
#include <vector>
#include <opencv2/opencv.hpp>
#include <opencv2/aruco/charuco.hpp>

#ifndef _DEBUG
// Releaseモードのみで動作
#pragma comment(lib,"opencv_calib3d330.lib")
#pragma comment(lib,"opencv_core330.lib")
#pragma comment(lib,"opencv_highgui330.lib")
#pragma comment(lib,"opencv_imgproc330.lib")
#pragma comment(lib,"opencv_imgcodecs330.lib")
#pragma comment(lib,"opencv_aruco330.lib")
#endif

int readImage(cv::Mat &mat_image, char *dire);

int main() {
	// Read ChArUco stereo images
	cv::Mat img, dstimg;
	readImage(img, "< yourpath >");

	// Create dictionary
	const cv::aruco::PREDEFINED_DICTIONARY_NAME  dictionary_name = cv::aruco::DICT_6X6_250;
	cv::Ptr<cv::aruco::Dictionary> dictionary = cv::aruco::getPredefinedDictionary(dictionary_name);

	// Detect markers
	std::vector<int> markerIdx;
	std::vector<std::vector<cv::Point2f>> markerCorners, rejectedImgPoints;
	cv::Ptr<cv::aruco::DetectorParameters> detectorParams = cv::aruco::DetectorParameters::create();
	cv::aruco::detectMarkers(img, dictionary, markerCorners, markerIdx, detectorParams, rejectedImgPoints);
        
       	// create charuco board object
	const int   squaresX     = 8;
	const int   squaresY     = 11;
	const float squareLength = 0.031;
	const float markerLength = 0.0185;
	cv::Ptr<cv::aruco::CharucoBoard> charucoboard_obj =
	     cv::aruco::CharucoBoard::create(squaresX, squaresY, squareLength, markerLength, dictionary);
	cv::Ptr<cv::aruco::Board> charucoboard = charucoboard_obj.staticCast<cv::aruco::Board>();

        // refind strategy to detect more markers
	cv::aruco::refineDetectedMarkers(img, charucoboard, markerCorners, markerIdx, rejectedImgPoints);

	// Draw detected markers
	cv::cvtColor(img.clone(), dstimg, cv::COLOR_GRAY2BGR);
	cv::aruco::drawDetectedMarkers(dstimg, markerCorners, markerIdx);
	cv::imshow("Detected result", dstimg);
	cv::waitKey(0);

	return -1;
}

int readImage(cv::Mat &mat_image, char *dire)
{
	// read stereo images in as grayscale (CV_8U):
	mat_image= cv::imread(dire, 0);
	if (mat_image.empty()) {
		printf("ERROR! failed to read one or both images, exiting...\n");
		return 0;
	}
	return 1;
}

マーカー検出結果

f:id:FounderLeis:20181202171230p:plain

 
 

C++サンプルプログラム(ChArUcoボードのコーナー検出)

        // refind strategy to detect more markers
        ...

	// Interpolate charuco corners
	// if at least one marker detected
	std::vector<cv::Point2f> charucoCorners;
	std::vector<int> charucoIdx;
	if (markerIdx.size() > 0) {
		cv::aruco::interpolateCornersCharuco(
			markerCorners, markerIdx, img, charucoboard_obj, charucoCorners, charucoIdx);
	}
        
        // Draw detected corners
        ...
        if (charucoIdx.size() > 0) 
		cv::aruco::drawDetectedCornersCharuco(dstimg, charucoCorners, charucoIdx, cv::Scalar(0, 0, 255));
        ...

コーナー検出結果

f:id:FounderLeis:20181202171327p:plain
 


説明文の折り畳み方法に関してはこちらの記事を参考にさせていただきました。
はてなブログでソースコードを折りたたむ方法 - おもちゃラボ

 
Amazon: 

詳解 OpenCV 3 ―コンピュータビジョンライブラリを使った画像処理・認識

詳解 OpenCV 3 ―コンピュータビジョンライブラリを使った画像処理・認識

似たような感じの英単語まとめ

個人的に気になった、似てるけど違う用法の英単語や似たような意味の英単語をメモしたものです。メモ書き程度ですが誰かの参考になればと思います。

inversely と conversely の違い

"inversely"と”conversely”どちらも「逆に」という逆接を意味する言葉ですが、使い分けがあるようです。

inversely 一般的に数学用語で用いられる

ex.) inversely proportional : 反比例

conversely 一般的な文章や会話で用いられる

ex.) Our professor said we could take a final exam, or conversely, write a 30-page term paper.

incident と coincident の違い

"incident"と"coincident"は「生じる」ことを意味する言葉ですが、どう違うのでしょうか。

incident 一つのイベントが生じるとき

ex.) Nobody was looking at that incident.

coincident 2つ以上のイベントが同時に生じるとき
(co- : 複数であることを表す接頭語)

ex.) His death was coincident with his son's birth.

hence, therefore, thus, so の違い

hence …だから~(と予想されるだろう)のときに用いられる
therefore …だから~(ならざるを得ないだろう・そうなるのは当然)のときに用いられる
thus ...だから(その結果として)~のときに用いられる


参考:
so, hence, therefore, thusの違い 英語力を上げるには? Vol.6 英会話のマスターはライティングから|神戸 オーパス英語学院
 
 

famous と renowned の違い

"famous"も"renowned"もともに「有名な」ことを意味する言葉ですが、どう違うのでしょう。

famous 一般的によく使われる言葉でとくに用途の決まりは特にない。しいて言えば、良い意味で広く知られているときに使われる言葉です。

ex.) That festival is famous, isn't it ?

renowned 多くの人に知れていて、良い意味を持つときに用いられる。

ex.) He was highly renowned throughout the world as a great pianist.

他にも「有名な」の意味で、以下のような言葉があります。

well-known よく知られた
celebrated 名高い
notorious 評判の良くない
infamous 悪名高い
noted 注目をひいている

 
参考:
famous / well-known / renowned / celebrated / etc... の違い | ER Synonym Dictionary Online
 
 

intriguing と interesting の違い

"intriguing"と"interesting"はどちらも「面白い」の意味を持つ言葉ですが、どう違うのでしょうか。まあ、ほとんど同じ意味で使われるそうですが、強いて言えば以下のような違いがあるそうです。

intriguing もっと深く知りたいと思うような興味をそそられるときに用いられる。

ex.) Your words are intriguing and helpful.

interesting 面白いと思うが、そこまでもっと知りたいと思わないときに用いられる。

ex.) This book is really interesting.

参考:
interesting と intriguing はどう違いますか? | HiNative
 
 

put on, wear, dress の違い

"put on"、"wear"、"dress"はどれも「身に着ける」意味を持つ言葉ですが、それぞれ異なる状況で用いられます。

put on 身に着ける動作を表すときに用いられる

ex.) I put on a jacket this morning.

wear 身に着けている状態を表すときに用いられる

ex.) I'm wearing a jacket now.

dress (誰かに)服を着せるというときに用いられる

ex.) She was dressing her child.
ex.) He can't dress himself.

参考:
「服を着る」のput on / wear / dressの違い | ネイティブと英語について話したこと
 
 

outfit, clothes, clothing, attire の違い

"outfit"、"clothes"、"clothing"、"attire"はいずれも「衣服」を意味する言葉ですが、どのように違うのでしょうか。

outfit 一般的にコーディネート全体を含めた衣服を指すときに用いられる
clothes 身に着けるものであればなんでも表される
clothing clothesと同様
attire フォーマルな衣装の時に用いられる
ex.) business attire, sports attire, formal attire ...


参考:
outfit と clothes と clothing と attire と apparel はどう違いますか? | HiNative

acronym と abbreviation の違い

"acronym"と"abbreviation"はどちらもLOLやJPYといった「省略語」のことを言いますが、ちゃんと使い分けがあります。ちなみに、acronymは発音するとき"r"を発音せずにカタカナで書くと「アクニム」と言いますね。

acronym 頭文字をとった略語に用いられる

ex.) LOL = laugh out loud (日本でいう'(笑)'や'www'と一緒の意味)

abbreviation とにかく省略された言葉全てに用いられる
(数学的に、abbreviation ⊃ acronym )

ex.) JPY= Japan yen

参考:
略語 : abbreviation と acronym - 職業プログラマの休日出勤
学校では教えてくれないacronymランキング | "学者への道" in California Berkeley


英語問題を載せているサイトのリンク

  • 英訳問題集(詳しい解説付き)

 >><英訳:問題一覧>