円周率を計算する その3

前回の続き

円周率をPCで計算する。 実際、円周率計算ソフトなどをつかって円周率を求めることができるが
クラッチ状態から円周率プログラムを組んだことがなかったので実際にやってみた。

前回はdouble型の精度の問題で15桁までしか計算できなかった。 今回は多倍長ライブラリ(GMP)を使って任意の精度まで計算するように変更。
以下がそのソース。
digits 変数で任意に精度を設定 今回は 200 でやってみる。

続きを読む

円周率を計算する その2

前回の続き

円周率をPCで計算する。 実際、円周率計算ソフトなどをつかって円周率を求めることができるが
クラッチ状態から円周率プログラムを組んだことがなかったので実際にやってみた。

前回は一回しか計算できないプログラムなので 今回は n回 計算できるようにソースを改変 以下がそのソース。

続きを読む

円周率を計算する その1

円周率をPCで計算する。 実際、円周率計算ソフトなどをつかって円周率を求めることができるが
クラッチ状態から円周率プログラムを組んだことがなかったので実際にやってみた。

どうやって円周率を求めるのか、そのアルゴリズムを検索。
「円周率 アルゴリズム」でググってみると最初に出てくるのが

ガウス=ルジャンドルのアルゴリズム - Wikipedia

なるほど、 初期値

 \displaystyle
  a_0 = 1\\
  b_0=\frac{1}{\sqrt{2}}\\
  t_0 =\frac{1}{4}\\
  p_0 = 1\\

反復式

 \displaystyle
 a_{n+1}=\frac {a_{n}+b_{n}}{2}\\
 b_{n+1}=\frac {2}{\sqrt{a_nb_n}}\\
 t_{n+1}=t_n-p_n(a_n-a_{n+1})^2\\
 p_{n+1}=2p_n\\

を何回か繰り返して

PIを計算

 \displaystyle
  \pi\approx\frac{(a+b)^2}{4t}

する。

ループなしで一回のみ計算(n+1回目のみ)してみて円周率をもとめてみた。
以下がそのソース。

続きを読む

OpenCVを使っ輪郭を書いてみる

輪郭とは~~。となりのピクセルの差が大きいところ。 でこうなる。

//画面をだすよ
void display(cv::Mat image) {
    //まえの記事をみてね
}

//
// ここから
//
int main(int argc, char** argv) {

    cv::Mat opencv = cv::imread("OpenCv.png",0);
    cv::Mat image  = cv::Mat::zeros(opencv.rows, opencv.cols, CV_8UC1);

     uchar up,down,left,right;
     uchar upleft,downleft;
     uchar upright,downright;
     uchar anchor;

     int cols = opencv.cols;
     int rows = opencv.rows;

     for (int j = 1; j < rows  - 1; j++) {
         for (int i = 1; i < cols  - 1; i++) {
             up = lena.at<uchar>(j - 1, i);
             down = lena.at<uchar>(j + 1, i);
             left = lena.at<uchar>(j, i - 1);
             right = lena.at<uchar>(j, i + 1);

             upleft = lena.at<uchar>(j - 1, i-1);
             upright = lena.at<uchar>(j - 1, i+1);
             downleft = lena.at<uchar>(j + 1, i-1);
             downright = lena.at<uchar>(j + 1, i+1);

             anchor = lena.at<uchar>(j, i);

             image.at<uchar>(j, i) =
                         cv::saturate_cast<uchar>(
                                 anchor*-4
                                 +up*1
                                 +down*1
                                 +left*1
                                 +right*1
                                 +upleft*0
                                 +upright*0
                                 +downleft*0
                                 +downright*0
                 );
         }
     }

    //画面に出して!!
    display(image);

}

オリジナル画像

f:id:treehitsuji:20150211150256p:plain

輪郭画像

f:id:treehitsuji:20150211150320p:plain

OpenCVを使ってLenaさんを拡大する2。

前回は隙間が黒かったので今度は隙間を埋めてさらに
ぼかしをいれてなめらか拡大Lenaさんにしてみる。

//画面をだすよ
void display(cv::Mat image) {
    //まえの記事をみてね
}

//
// ここから
//
int main(int argc, char** argv) {
    //lenaさん登場!!
    cv::Mat lena = cv::imread("lena.jpg");
    //lenaさん白黒レトロ
    cv::cvtColor(lena, lena, CV_RGB2GRAY);
    //lenaさんの2倍のサイズの画像
    cv::Mat image  = cv::Mat::zeros(lena.cols * 2, lena.rows * 2, CV_8UC1);

    int cols = lena.cols;
    int rows = lena.rows;
    for (int j = 1; j < rows - 1 ; j++) {
        for (int i = 1; i < cols - 1; i++) {
            for (int k = -1; k < 2; k++) {
        //八方の隙間を同じ色でぬる!!
                for (int l = -1; l < 2; l++) {
                    image.at<uchar>(j*2 - k, i*2 - l) = cv::saturate_cast<uchar>(lena.at<uchar>(j, i));
                }
            }
        }
    }

    //ガウスぼかし!!でごまかし!!
     uchar up,down,left,right;
     uchar upleft,downleft;
     uchar upright,downright;
     uchar anchor;

     //lenaさんの2倍のサイズの画像
     cv::Mat image2  = cv::Mat::zeros(lena.cols * 2, lena.rows * 2, CV_8UC1);
     for (int j = 1; j < rows * 2 - 1; j++) {
         for (int i = 1; i < cols * 2 - 1; i++) {
             up = image.at<uchar>(j - 1, i);
             down = image.at<uchar>(j + 1, i);
             left = image.at<uchar>(j, i - 1);
             right = image.at<uchar>(j, i + 1);

             upleft = image.at<uchar>(j - 1, i-1);
             upright = image.at<uchar>(j - 1, i+1);
             downleft = image.at<uchar>(j + 1, i-1);
             downright = image.at<uchar>(j + 1, i+1);
             anchor = image.at<uchar>(j, i);

             image2.at<uchar>(j, i) =
                         cv::saturate_cast<uchar>(
                                 anchor*4/16
                                 +up*2/16
                                 +down*2/16
                                 +left*2/16
                                 +right*2/16
                                 +upleft*1/16
                                 +upright*1/16
                                 +downleft*1/16
                                 +downright*1/16
                 );
         }
     }

    //画面に出して!!
    display(image2);
}

2倍Lenaさん

f:id:treehitsuji:20150208185143p:plain

OpenCVを使ってLenaさんを拡大する。

こんどはLenaさんを拡大してみる。
縦の0行目と1行目の間に1行追加、1行目と2行目の間に1行追加・・・・・・
横の0列目と1列目の間に1列追加、1列目と2列目の間に1列追加・・・・・・
広げてみた。

//画面をだすよ
void display(cv::Mat image) {
    //まえの記事をみてね
}

//
// ここから
//
int main(int argc, char** argv) {
    //lenaさん登場!!
    cv::Mat lena = cv::imread("lena.jpg");
    //lenaさん白黒レトロ
    cv::cvtColor(lena, lena, CV_RGB2GRAY);
    //lenaさんの2倍のサイズの画像
    cv::Mat image  = cv::Mat::zeros(lena.cols * 2, lena.rows * 2, CV_8UC1);

    int cols = lena.cols;
    int rows = lena.rows;
    for (int j = 0; j < rows ; j++) {
        for (int i = 0; i < cols; i++) {
            image.at<uchar>(j*2, i*2) = cv::saturate_cast<uchar>(lena.at<uchar>(j, i));
        }
    }
    //画面に出して!!
    display(image);
}

なんか変!!

f:id:treehitsuji:20150208181136p:plain

OpenCVを使ってLenaさんを半分のサイズにする。

Lenaさんを半分のサイズにするには縦、横を交互に間引く
縦の1行目と3行目と・・・・
横の1列目と3列目と・・・・
つめる!!!

//画面をだすよ
void display(cv::Mat image) {
    //まえの記事をみてね
}

//
// ここから
//
int main(int argc, char** argv) {
    //lenaさん登場!!
    cv::Mat lena = cv::imread("lena.jpg");
    //lenaさん白黒レトロ
    cv::cvtColor(lena, lena, CV_RGB2GRAY);
    //lenaさんの半分のサイズの画像
    cv::Mat image  = cv::Mat::zeros(lena.cols / 2, lena.rows / 2, CV_8UC1);

    int cols = lena.cols;
    int rows = lena.rows;
    for (int j = 0; j < rows ; j+=2) {
        for (int i = 0; i < cols; i+=2) {
            image.at<uchar>(j/2, i/2) = cv::saturate_cast<uchar>(lena.at<uchar>(j, i));
        }
    }
    //画面に出して!!
    display(image);
}

f:id:treehitsuji:20150118142431p:plain

半分Lenaさん

f:id:treehitsuji:20150208175141p:plain