奇関数、偶関数

奇関数

となる関数。

 

つまり、関数のグラフが原点に対して対象となります。

 

【例】

y = x, y = x3, y = sinθ など

 

【特徴】

-a ~ a の範囲で積分すると

となります。

 

偶関数

となる関数。

 

つまり関数のグラフがY軸に対して対象となります。

 

【例】

y = x2,  y = x4,  y = cosθ など

 

【特徴】

-a ~ a の範囲で積分すると

となります。

 

計算例

となります。

このように、関数を奇関数と偶関数に分けて積分します。

 

この偶関数・奇関数の特徴を応用すると、関数の合計値をfor文などで計算する場合に、計算量を大きく減らす事ができるので、処理の高速化が期待できます。

 

使える数学へ戻る

 

【OpenCV】アンシャープマスキング(鮮鋭化)

アンシャープマスキング(Unsharp Masking)もOpenCVに無い関数の1つのなのですが、OpenCVには任意カーネルを指定してフィルタ処理を行っているcvFilter2Dという関数があるので、これを使ってアンシャープマスキングを実現する手法を紹介します。

 

アンシャープマスキングのアルゴリズムについては以前、アンシャープマスキング(鮮鋭化フィルタ)のページで紹介しているので、そちらを参照願います。

 

以下、アンシャープマスキングのサンプルプログラムです。OpenCV2.2を用いて、作成しています。

 

// UnsharpMasking.cpp : コンソール アプリケーションのエントリ ポイントを定義します。
//

#include "stdafx.h"

//プロジェクトのプロパティ⇒C/C++⇒全般 の追加のインクルードディレクトリに
// 『C:\OpenCV2.2\include』を追加のこと
#include "opencv2\\opencv.hpp"

#ifdef _DEBUG
    //Debugモードの場合
    #pragma comment(lib,"C:\\OpenCV2.2\\lib\\opencv_core220d.lib")
    #pragma comment(lib,"C:\\OpenCV2.2\\lib\\opencv_imgproc220d.lib")
    #pragma comment(lib,"C:\\OpenCV2.2\\lib\\opencv_highgui220d.lib")
#else
    //Releaseモードの場合
    #pragma comment(lib,"C:\\OpenCV2.2\\lib\\opencv_core220.lib")
    #pragma comment(lib,"C:\\OpenCV2.2\\lib\\opencv_imgproc220.lib")
    #pragma comment(lib,"C:\\OpenCV2.2\\lib\\opencv_highgui220.lib")
#endif

//---------------------------------------------------------------
//【関数名 】:cv_UnsharpMasking
//【処理概要】:アンシャープマスキング
//【引数  】:src        = 入力画像
//      :dst        = 出力画像
//      :k		   = 鮮鋭化の強さ
//【戻り値 】:なし
//【備考  】:
//---------------------------------------------------------------
void cv_UnsharpMasking(IplImage* src, IplImage* dst, float k){
	//カーネルの設定
	float KernelData[] = {
		-k/9.0f, -k/9.0f,			-k/9.0f,
		-k/9.0f, 1 + (8 * k)/9.0f,	-k/9.0f,
		-k/9.0f, -k/9.0f,			-k/9.0f,
	};
	//カーネルの配列をCvMatへ変換
	CvMat kernel = cvMat (3, 3, CV_32F, KernelData);
	//フィルタ処理
	cvFilter2D (src, dst, &kernel);
}

int _tmain(int argc, _TCHAR* argv[])
{

	//画像データの読込
	IplImage* src = cvLoadImage("sample.bmp", CV_LOAD_IMAGE_ANYDEPTH | CV_LOAD_IMAGE_ANYCOLOR);
	if (src == NULL){
		return 0;
	}

	//表示ウィンドウの作成
	cvNamedWindow("src");
	cvNamedWindow("dst");

	//処理後画像データの確保
	IplImage* dst = cvCreateImage(cvGetSize(src), src->depth, src->nChannels);

	//アンシャープマスキング
	cv_UnsharpMasking(src, dst, 2.0f);

	//画像の表示
	cvShowImage ("src", src);
	cvShowImage ("dst", dst);

	//キー入力待ち
	cvWaitKey (0);

	//全てのウィンドウの削除
	cvDestroyAllWindows();

	//画像データの解放
	cvReleaseImage(&src);
	cvReleaseImage(&dst);

	return 0;
}

サンプルプログラムのダウンロードはこちらより。

OpenCV-UnsharpMasking.zip

(OpenCV2.2対応。Visual Studio 2010 C++ Expressにより作成)

 

実行例

 

このサンプルプログラムは、任意カーネルフィルタのサンプルにもなっているので、プログラム中のKernelDataの値をいろいろと変えてみるのも面白いと思います。

 

OpenCVへ戻る

 

【OpenCV】コンピュータにopencv_objdetect220d.dllがないため、

OpenCVのサンプルプログラムなどを動かそうとすると、下図のように

 

コンピュータにopencv_objdetect220d.dllがないため、プログラムを開始できません。
この問題を解決するには、プログラムを再インストールしてみて下さい。

 

 

などと、他にもコンピュータにopencv_core220d.dllがないため、・・・だったりと、ファイル名は違うかもしれませんが、このようなエラーメッセージが表示される場合があります。

 

dllファイルはコンピュータに入っているし、なぜ???と思われる方もいると思いますが、Windowsではダイナミックライブラリファイル(*.dll)は下記の特定のフォルダに入っていないと見つけてくれません。

 

1. アプリケーション(*.exe)と同じフォルダ
2. カレントディレクトリ
3. システムディレクトリ(C:\Windows\System32 など)
4. 16Bitシステムディレクトリ(C:\Windows\System など)
5. Windowsディレクトリ(C:\Windows など)
6. PATH環境変数に列挙されているディレクトリ

 

OpenCV2.2ではインストール時に、OpenCVをPATH環境変数に追加するか?と聞かれるのですが、これを忘れてしまうと、このエラーメッセージが表示されてします。

 

そのため、このエラーが出た時には自分でPATH環境変数にOpenCVのPATH(OpenCVのdllファイルのあるディレクトリ)を設定する必要があります。

 

設定方法は以下の通り。

 

設定方法は、スタートメニューから、コンピュータ右クリックし、プロパティを選択します。

 

次に表示されたウィンドウのシステムの詳細設定をクリック

 

 

詳細設定のタブを選択し、右下の環境変数のボタンをクリック

 

 

すると下図のように××のユーザー環境変数システム環境変数と2種類表示され、両方ともにPathの項目があるのですが、××のユーザー環境変数のPathを設定するとWindowsにログインしたときのユーザーのみでPathの設定が有効となり、システム環境変数のPathを設定すると全ユーザーでPathの設定が有効となります。
私は『ログインしたユーザーを変えるとプログラムが起動しないんだけど?!』とか言われたく無いので、システム環境変数のPathを設定 するようにしています。

 

そして、Pathの項目を選択し、編集ボタンをクリックします。

 

そして、編集値の欄に*.dllファイルがインストールされているパス(フォルダ名のフルパス)をセミコロン(;)に続けて記載します。

 

(例)
;C:\OpenCV2.2\bin

 

この時、元にあった文字は消さないように注意して下さい。
消されたプログラムが起動しなくなります。

 

最後にパソコンを再起動して下さい。

 

これで、 コンピュータに*.dllファイルがないため、 というエラーは無くなると思います。

 

(参考)

ライブラリの使用方法、VisualStudioの設定方法

 

OpenCVへ戻る

 

【OpenCV】ソーベルフィルタ(cvSobel)

OpenCVの関数では、ほとんど入力画像と出力画像のデータはビット数とチャンネル数は等しい場合が多いのですが、ソーベルフィルタの関数(cvSobel)は入力画像が8Bitに対し、出力画像が符号付きの16Bit(IPL_DEPTH_16S)にしないといけません。

 

また、一回のcvSobel関数の処理ではX方向、Y方向のどちらかの方向しか処理できないので、最も一般的?なX方向とY方向を足し合わせた処理を簡単に関数にまとめてみました。

 

// SobelFilter.cpp : コンソール アプリケーションのエントリ ポイントを定義します。
//

#include "stdafx.h"

//プロジェクトのプロパティ⇒C/C++⇒全般 の追加のインクルードディレクトリに
// 『C:\OpenCV2.2\include』を追加のこと
#include "opencv2\\opencv.hpp"

#ifdef _DEBUG
    //Debugモードの場合
    #pragma comment(lib,"C:\\OpenCV2.2\\lib\\opencv_core220d.lib")
    #pragma comment(lib,"C:\\OpenCV2.2\\lib\\opencv_imgproc220d.lib")
    #pragma comment(lib,"C:\\OpenCV2.2\\lib\\opencv_highgui220d.lib")
#else
    //Releaseモードの場合
    #pragma comment(lib,"C:\\OpenCV2.2\\lib\\opencv_core220.lib")
    #pragma comment(lib,"C:\\OpenCV2.2\\lib\\opencv_imgproc220.lib")
    #pragma comment(lib,"C:\\OpenCV2.2\\lib\\opencv_highgui220.lib")
#endif

//---------------------------------------------------------------
//【関数名 】:cv_Sobel
//【処理概要】:ソーベルフィルタ
//【引数  】:src        = 入力画像(8bit)
//      :dst        = 出力画像(8bit)
//【戻り値 】:なし
//【備考  】:
//---------------------------------------------------------------
void cv_Sobel(IplImage* src, IplImage* dst){

    IplImage* xSoble  = cvCreateImage(cvGetSize(src), IPL_DEPTH_16S, src->nChannels);
    IplImage* ySoble  = cvCreateImage(cvGetSize(src), IPL_DEPTH_16S, src->nChannels);
    IplImage* xySoble = cvCreateImage(cvGetSize(src), IPL_DEPTH_16S, src->nChannels);

    //X方向のソーベル
    cvSobel(src, xSoble, 1, 0);
    //Y方向のソーベル
    cvSobel(src, ySoble, 0, 1);

    //X方向 + Y方向
    cvAdd(xSoble, ySoble, xySoble);

    //符号付き16ビット→符号なし8ビットへ
    cvConvertScaleAbs(xySoble, dst);

    //解放
    cvReleaseImage(&xSoble);
    cvReleaseImage(&ySoble);
    cvReleaseImage(&xySoble);

}

int _tmain(int argc, _TCHAR* argv[])
{

	//画像データの読込(グレースケールで読込)
	IplImage* src = cvLoadImage("Lenna.bmp", CV_LOAD_IMAGE_GRAYSCALE);
	if (src == NULL){
		return 0;
	}

	//表示ウィンドウの作成
	cvNamedWindow("src");
	cvNamedWindow("dst");

	//処理後画像データの確保
	IplImage* dst = cvCreateImage(cvGetSize(src), src->depth, src->nChannels);

	//ソーベルフィルタ
	cv_Sobel(src, dst);

	//画像の表示
	cvShowImage ("src", src);
	cvShowImage ("dst", dst);

	//キー入力待ち
	cvWaitKey (0);

	//全てのウィンドウの削除
	cvDestroyAllWindows();

	//画像データの解放
	cvReleaseImage(&src);
	cvReleaseImage(&dst);

	return 0;
}

サンプルプログラムのダウンロードはこちらより。

OpenCV-SobelFilter.zip

(OpenCV2.2対応。Visual Studio 2010 C++ Expressにより作成)

 

実行例

 

今回の例ではソーベルフィルタの結果の絶対値を取りましたが、必ずしもソーベルフィルタは絶対値を取る! とは思わない方が良いかと思います。

 

上図のような処理例を見ても分かるように、ソーベルの絶対値を取ると、狭い間隔の輪郭は白く潰れてしまいます。

 

しかし、絶対値を取らないと、狭い間隔のエッジでも、正の値と負の値とで区別ができるので、エッジ間隔を取得し易くなります。

 

その点、cvSobel関数では、処理結果をあえて符号付きの16ビットで出力するようにしたOpenCVには共感が持てる。

 

OpenCVへ戻る

 

【C++/CLI】配列の配列(ジャグ配列)

配列の配列をジャグ配列と言います。

サンプルコードは以下の通り。

//////////////////////////////////////////////
// 配列の配列(ジャグ配列) その1
//////////////////////////////////////////////
array<array^>^ jag1 = gcnew array<array^>(2);

int index1 = 0;

for (int j = 0; j < jag1->Length; j++)
{
	jag1[j] = gcnew array(3);
	for (int i = 0; i < jag1[j]->Length; i++)
	{
		jag1[j][i] = index1++;
	}
}
// jag1[0][0] = 0  jag1[0][1] = 1  jag1[0][2] = 2
// jag1[1][0] = 3  jag1[1][1] = 4  jag1[1][2] = 5

//////////////////////////////////////////////
// 配列の配列(ジャグ配列) その2
//////////////////////////////////////////////
array<array^>^ jag2 = gcnew array<array^>(3);

int index2 = 0;

for (int j = 0; j < jag2->Length; j++)
{
	jag2[j] = gcnew array(j + 1);
	for (int i = 0; i < jag2[j]->Length; i++)
	{
		jag2[j][i] = index2++;
	}
}

// jag2[0][0] = 0
// jag2[1][0] = 1  jag2[1][1] = 2
// jag2[2][0] = 3  jag2[2][1] = 4  jag2[2][2] = 5

上記の例は、配列の配列までの例ですが、配列の配列の配列も可能です。

array<array<array<int>^>^>^ jag;

 

このジャグ配列は、個人的にはあまり用いていませんが、上記の ジャグ配列 その2 の例でも示しているように、必ずしも1行あたりの配列の要素数は同じである必要は無いので、例えば、CSVファイルなどのように、1行あたりの要素数が不定になる可能性のある配列などに用いると便利です。

 

【OpenCV】ガンマ補正

OpenCVにはcvGammaのようなガンマ補正の関数は無いのですが、ルックアップテーブルを使った輝度値変換の関数(cvLUT)はあるので、これを使ってガンマ補正を行いたいと思います。

 

以下、ガンマ補正のサンプルプログラムです。OpenCV2.2を用いて、作成しています。

#include "stdafx.h"

//プロジェクトのプロパティ⇒C/C++⇒全般 の追加のインクルードディレクトリに
// 『C:\OpenCV2.2\include』を追加のこと
#include "opencv2\\opencv.hpp"
 
#ifdef _DEBUG
    //Debugモードの場合
    #pragma comment(lib,"C:\\OpenCV2.2\\lib\\opencv_core220d.lib")
    #pragma comment(lib,"C:\\OpenCV2.2\\lib\\opencv_imgproc220d.lib")
    #pragma comment(lib,"C:\\OpenCV2.2\\lib\\opencv_highgui220d.lib")
#else
    //Releaseモードの場合
    #pragma comment(lib,"C:\\OpenCV2.2\\lib\\opencv_core220.lib")
    #pragma comment(lib,"C:\\OpenCV2.2\\lib\\opencv_imgproc220.lib")
    #pragma comment(lib,"C:\\OpenCV2.2\\lib\\opencv_highgui220.lib")
#endif
//---------------------------------------------------------------  
//【関数名 】:cv_Gamma  
//【処理概要】:ガンマ補正  
//【引数  】:src        = 入力画像  
//      :dst        = 出力画像  
//      :gamma   = ガンマ補正値  
//【戻り値 】:なし  
//【備考  】:モノクロ/カラー対応可  
//      :カラーの場合はRGB全て同じガンマ補正値  
//---------------------------------------------------------------   
void cv_Gamma(IplImage* src, IplImage* dst, double gamma){  

	int i;  

	uchar LUT[256];  
              
	//ガンマ補正テーブルの作成  
	for (i = 0; i < 256; i++)
	{  
		LUT[i] = (int)(pow((double)i / 255.0, 1.0 / gamma) * 255.0);  
	}  

	//CvMatへ変換  
	CvMat lut_mat = cvMat(1, 256, CV_8UC1, LUT);  

	//ルックアップテーブル変換  
	cvLUT(src, dst, &lut_mat);  
}

int _tmain(int argc, _TCHAR* argv[])
{
	//画像データの読込
	IplImage* src = cvLoadImage("Girl.bmp", CV_LOAD_IMAGE_ANYDEPTH | CV_LOAD_IMAGE_ANYCOLOR);
	if (src == NULL){
		return 0;
	}
 
	//表示ウィンドウの作成
	cvNamedWindow("src");
	cvNamedWindow("dst");
 
	//処理後画像データの確保
	IplImage* dst = cvCreateImage(cvGetSize(src), src->depth, src->nChannels);
 
	//ガンマ補正
	cv_Gamma(src, dst, 2.0);
 
	//画像の表示
	cvShowImage ("src", src);
	cvShowImage ("dst", dst);
 
	//キー入力待ち
	cvWaitKey (0);
 
	//全てのウィンドウの削除
	cvDestroyAllWindows();
 
	//画像データの解放
	cvReleaseImage(&src);
	cvReleaseImage(&dst);

	return 0;
}

サンプルプログラムのダウンロードはこちらより。

gamma-correction-opencv-sample.zip

(OpenCV2.2対応。Visual Studio 2010 C++ Expressにより作成)

 

実行例

 

OpenCV2.2の使用方法および、ガンマ補正については下記のページを参照下さい。

 

OpenCVへ戻る

 

ガンマ補正(ルックアップテーブルの例)

ルックアップテーブルLookup Table【略LUT】)は、ある値の答えが必ず1つの値となる場合、あらかじめ答えを計算しておき、配列に格納しておくことで、毎回の計算をすることなく、 配列(テーブル)を参照することで効率的に処理を行う手法です。

 

画像処理では、コントラスト調整やガンマ補正などによく用いられます。

 

例えば、ガンマ補正の場合、ガンマ補正値をγ、補正前の輝度値をsrc
補正後の輝度値をdstとすると、補正式は

 

 

となりますが、この計算を全ての画素に対して処理を行うのは非常に非効率です。
そこで、例えばLUTという配列に、ガンマ補正の計算結果を以下のように格納しておきます。

 

src 0 1 2 3 ・・・ 252 253 254 255
dst 0 16 23 28 ・・・ 253 254 254 255

 

 

あとは、各画素に対して、

 

dst = LUT[src]

 

という変換をすればよいだけなので、高速に処理を行うことができます。
こうする事でルックアップテーブルを用いない場合は、画素数分のガンマ補正計算をしないといけないのが、ルックアップテールを用いる事で、この例の場合では、たかだか256回の計算だけで済みます。

 

ガンマ補正例

  • ガンマ補正前

 

  • ルックアップテーブル

 

  • ガンマ補正後

 

他にも二値化処理や、輝度値を0~255の範囲内に収めるための if 文の代わりなどにも応用できる場合があるので、処理を高速にしたい場合は、このルックアップテーブルが使えるかどうか?検討してみるのも良いと思います。

 

画像処理アルゴリズムへ戻る

 

【C++/CLI】配列の確保(Arrayクラス)

配列の確保は

 

array<型>^変数名 = gcnew array<型>(要素数);

 

のように行います。

 

多次元の場合は

 

array<型, 次数>^変数名 = gcnew array<型, 次数>(0次の要素数, 1次の要素数, 2次の要素数・・・);

 

コード例は以下の通り

 

///////////////////////////////////////////////
// 配列の初期化
///////////////////////////////////////////////
array^a = gcnew array {0, 1, 2, 3, 4};
// a[0] = 0
// a[1] = 1
// a[2] = 2
// a[3] = 3
// a[4] = 4

///////////////////////////////////////////////
// 配列の確保
///////////////////////////////////////////////
array^b = gcnew array(6);
int Len = b->Length;	// 配列の全個数

for (int i = 0; i < Len; i++)
{
	b[i] = i * 2;
}
// b[0] = 0
// b[1] = 2
// b[2] = 4
// b[3] = 6
// b[4] = 8
// b[5] = 10

///////////////////////////////////////////////
// 二次元配列の確保
///////////////////////////////////////////////
array<int, 2>^c = gcnew array<int, 2>(2, 3);

int iLen = c->GetLength(1);	// 1次の配列の個数  (= 3)
int jLen = c->GetLength(0);	// 0次の配列の個数 (= 2)

for (int j = 0; j < jLen; j++)
{
	for (int i = 0; i < iLen; i++)
	{
		c[j, i] = j * 10 + i;
	}
}
//c[0, 0] = 0	c[0, 1] = 1		c[0, 2] = 2
//c[1, 0] = 10	c[1, 1] = 11	c[1, 2] = 12

///////////////////////////////////////////////
// ポインタで二次元配列を参照し一次元配列へ代入
///////////////////////////////////////////////
pin_ptrp = &c[0, 0];
array^d = gcnew array(6);

for (int i = 0; i < iLen * jLen; i++){
	d[i] = p[i];
}
// d[0] = 0
// d[1] = 1
// d[2] = 2
// d[3] = 10
// d[4] = 11
// d[5] = 12

ここで、多次元配列の場合、メモリに格納されている順番は右側の添え字から順番に格納されているので、ご注意下さい。
ポインタで参照している部分を参考にして下さい。

 

良く使うメソッド、プロパティは以下の通り

メソッド

  • GetLength(dimension)
    指定した次元(dimension)の要素数を取得します。
  • Resize(array, newSize)
    配列(array)のサイズをnewSizeに変更し、各要素は新しい配列へコピーされます。

 

プロパティ

  • Length
    全ての次元内の要素数を取得します。

 

【Word/Excel】4×4以上の行列の入力方法

Word2007、Excel2007以降では数式エディタも数式ツールとして少し使いやすくなりましたが、行列を入力するとき、標準的には3×3までの行列しか表示されていません。

 

4×4以上の行列を入力する場合は以下のようにします。

 

まず、 数式ツール→かっこ より行列のかっこを表示します。

 

 

次に 数式ツール→行列 でとりあえず3×3の行列を表示します。

 

 

次に行列のどれか1の四角(□)を選択し、マウスの右ボタンをクリックします。

 

 

すると、挿入というメニューがあるので、挿入を選択し、次に表示される

 

前に行を挿入
後に行を挿入
前に列を挿入
後に列を挿入

 

のいづれかを選択し、行、もしくは列を挿入します。
次の例を列を挿入した様子

 

 

同様にして行を挿入すると、

 

 

となり、4×4以上、いくらでも?追加する事が可能です。

 

Word/Excelの記事一覧へ戻る

グラフ(関数)の拡大縮小、平行移動

拡大、縮小

XとYであらわせる関数

 

 

X軸方向に SxY軸方向に Sy 倍の拡大縮小すると

 

 

となります。

(拡大の場合、Sx,Syは1以上、縮小の場合、Sx,Syは1以下となります。)

 

回転移動

関数 f(X,Y)を原点周りにθ度回転すると

 

 

となります。

 

平行移動

関数 f(X,Y)をX軸方向に TxY軸方向に Ty だけ平行移動すると

 

 

となります。

 

拡大縮小してから平行移動した場合は

 

 

となります。

 

考え方

グラフ(関数)を拡大、縮小、回転、平行移動するときに、実際にX、Yの値の変換は全て逆!つまり

 

拡大の場合 縮小
θ度回転の場合 -θ度回転
+方向へ移動の場合 -方向へ移動

 

の処理をしています。
何だかとっても違和感がありますが、グラフ(関数)を移動していると思うのではなく、グラフ(関数)はそのままに、XY軸を変換していると思うと、少しはしっくり来るでしょうか...

 

 

また、拡大縮小、回転、平行移動を同時に行う場合は、変換の順番に注意が必要です。

行列の計算と同じように、計算の順番が異なると計算結果も異なります。基本的には

 

拡大縮小 ⇒ 回転 ⇒ 平行移動

 

の順番で変換を行うのが、一番よいでしょう。

もちろん、分かっていて別の順番で変換するのは構いません。

 

具体例

半径1の円の式、グラフは

 

 

となり、このグラフをX軸方向に Sx 、Y軸方向に Sy 倍の拡大縮小すると

 

となります。

 

式を変形すると楕円の公式そのものとなります。

 

 

さらにX軸方向に Tx 、Y軸方向に Ty だけ平行移動すると

 

 

 

となり、円のグラフを拡大縮小、平行移動することで楕円の一般式となります。

 

応用例

2点を通る直線の式を、グラフの平行移動の考え方を用いて求めます。

 

2点を通る直線の式は

 

 

より、よくある直線の式の解き方は、XとYに2点の座標を代入して、2つの式を作成し、連立方程式を用いて、未知数の  と  を求めると思います。

 

しかし、直線の傾き  はグラフを見て分かる通り、(Yの増分)/(Xの増分)であるから

 

 

となり、あとは切片の  を求めるだけになります。

 

ここで、少し見方を変えて、原点を通る傾き  のグラフを下図のように

原点(0,0)から点(X1、Y1)へ平行移動します。

 

 

これを式であらわすと

 

 

となり、直線の式を求めることができます。
この式をそのまま覚えている方もいると思いますが、グラフの拡大縮小、平行移動の
考え方は汎用的に使うことができ、応用範囲がとても広がります。

 

他にも

Y = sinθ

 

という波形に関して、

 

Y軸方向の拡大率は振幅
θ軸方向の拡大率は周期
θ軸方向の平行移動は位相のズレ

 

というように、置き換えて考えることもできます。

 

このように考えるようになると、高校時代に一生懸命覚えたけど、すぐに忘れてしまうこのへんの公式↓

 

sin ( – θ ) = – sin θ cos ( – θ ) = cos θ
sin ( 90°+ θ ) = cos θ sin ( 90°- θ ) = cos θ
cos( 90°+ θ ) = – sin θ cos ( 90°- θ ) = sin θ
sin ( 180°+ θ ) = – sin θ sin ( 180°- θ ) = sin θ
cos ( 180°+ θ ) = – cos θ cos ( 180°- θ ) = – cos θ

 

は全て拡大縮小、平行移動として考えることが出来ます。

 

例えば sin ( 90°- θ ) は sin ( -(θ – 90°) ) と書きかえると

sin波形をθ方向に-1倍(Y軸に対して対称移動)してから、+θ方向に90°平行移動すれば良い事が分かります。

 

最初に手元にsin波形を描いておけば、変換後、どのような波形になるのか?は見ればわかりますよね?!

 

 

使える数学へ戻る

 

標準偏差

標準偏差とは?

標準偏差(Standard Deviation【略】SD)はデータの散らばりぐらいを示す値で σであらわされます。
測定誤差やノイズなどの評価値として用いられます。

 

標準偏差(大) 標準偏差(小)
データ
ヒストグラム

標準偏差の計算

標準偏差は各データを、データの平均値をとすると

を分散といいます。分散の平方根

が標準偏差となります。

この式で数学的には問題は無いのですが、式を見ても分かるように全データから平均値を求めてから各データとの差を求めるため、プログラム的には全データを2回参照することになるため、あまりよろしくありません。

ここで平均値

で求まることから、分散の式は

となり、この式を用いて分散、標準偏差のプログラムを作ると、全データを1回の参照で済むので、より効率的になります。

ポイント!!

分散 = 2乗の平均 - 平均の2乗

標準偏差 = 分散の平方根

正規分布

下図のように、平均値付近にデータの出現頻度が集中し、頻度に偏りが無く、平均値に対して左右対称で、平均値から遠くなればなるほど頻度が少なくなる状態を
「正規分布にしたがう」といいます。

 

この頻度を関数であらわすと

となります。
正規分布はガウス分布とも呼ばれ、画像処理のフィルタ処理にも使われます。

正規分布にしたがう場合のデータは下図のような割合で分布します。

この特性から、測定器の測定精度やカメラで撮影した画像のノイズレベルなどにおいて1σや3σなどであらわされる場合があります。

 

実際に標準偏差を用いる場合の注意点についても以下のページにまとめましたので、合わせてご覧頂けると幸いです。

標準偏差計算の注意点

 

まとめ

標準偏差の計算は、計算の式を暗記しようとするのではなく、計算の方法を言葉で覚える事をおススメします。

そうすると、必然的に標準偏差が何を計算しているのか?理解できるようになると思います。

分散はデータと平均の差の二乗の平均

分散の平方根が標準偏差

分散の計算のプログラムは

分散 = 2乗の平均 - 平均の2乗

で求める。

 

使える数学へ戻る

 

コンピュータビジョン 最先端ガイド 1、2、3

画像処理系の学会などに参加すると、AdaBoostなどこの本に出てくるキーワードがたくさん出てきます。
学会に参加している間は、何も分からず聞いている場合もあるのですが、そんな今時なアルゴリズムが解説されている、数少ない本だと思います。
ただ、難しめの数式がずらずらと並んでいるので、ちょっと難しい。

 

難しいので無駄になるかも?しれませんが、2000円と安いので、買ってみるのもいいかもしれません。
私はとりあえず、全部持ってます。

 

目次

コンピュータビジョン最先端ガイド1

 

第1章 レベルセット法とその実装法について 倉爪 亮(九州大学)

1.はじめに
2.Active Contour Modelとは
3.Snakesの理論と実装
4.Level Set Method
5.Level Set Methodの高速な実装法
6.まとめ
A.Level Set Methodの実装例

第2章 グラフカット 石川 博(名古屋市立大学)

1.はじめに
2.エネルギー最小化
3.グラフカット概観
4.グラフとその最小切断
5.グラフカットによる大域最小化
6.グラフカットを使った近似最小化
7.グラフカットの応用
8.むすび

第3章 パーティクルフィルタとその実装法  加藤 丈和(情報通信研究機構)

1.はじめに
2.時系列フィルタの概要
3.カルマンフィルタ
4.パーティクルフィルタ
5.パーティクルフィルタを用いた追跡
6.パーティクルフィルタの実装
7.まとめ
A.サンプルプログラム

第4章 テンソルと多視点幾何  佐藤 淳(名古屋工業大学)

1.はじめに
2.テンソルの基礎
3.幾何学的拘束とテンソル
4.多視点幾何
5.高次元空間における多視点幾何
6.多焦点テンソルの計算に必要な最小点数
7.多焦点テンソル間の関係
8.多視点幾何の縮退
9.多焦点テンソルの計算法
10.まとめ

第5章 AdaBoost 三田 雄志(東芝)

1.はじめに
2.2クラスを識別できるだけで役に立つのか?
3.AdaBoost
4.訓練誤差の性質
5.汎化誤差の性質
6.まとめ

 

コンピュータビジョン最先端ガイド2

 

第1章 「物体認識のための画像局所特微量」 藤吉 弘亘,山下隆義

1.一般物体認識
2.Scale-Invariant Feature Transform(SIFT)
3.物体検出に有効な特徴量
4.まとめ
A.第二世代の特徴量の実装例

第2章 「ミーンシフトの原理と応用」  岡田 和典

1.はじめに
2.ミーンシフトの原理
3.ミーンシフトの理論
4.ミーンシフトの利点と欠点
5.理論的拡張
6.ミーンシフトの応用
7.むすび

第3章 「カーネル情報処理入門 ―非線形の魅惑―」 前田 英作

1.はじめに
2.線形から非線形へ
3.カーネル関数
4.ベクトルデータに対するカーネル法(Ⅰ)
5.ベクトルデータに対するカーネル法(Ⅱ)
6.構造化データに対するカーネル法
7.まとめと数学的補足
8.より深い理解のために

第4章 「画像処理とコンピュータビジョンのためのGPU」 ノジク・ヴァンソン,石川 尋代,ドゥソルビエ・フランソワ

1.はじめに
2.コンピュータグラフィックスの基礎
3.GLSL(OpenGL Shading Language)
4.Shaderプログラム
5.画像処理
6.幾何学的処理
7.コンピュータビジョン ツール
8.Virtual Reality
9.General Purpose GPU(GPGPU)
10.How to start
11.まとめ

 

コンピュータビジョン最先端ガイド3

 

1章 バンドルアジャストメント

1.はじめに
2.バンドル調整の概要
3.最小化のための数値計算
4.バンドル調整と統計的推測
5.ゲージの自由度
6.逐次計算と再帰的計算
7.おわりに

2章 ICPアルゴリズム

1.はじめに
2.ICPアルゴリズム
3.派生ICPアルゴリズム
4.おわりに

3章 Bag-of-Featuresに基づく物体認識(1) - 特定物体認識 –

1.まえがき
2.処理の流れ
3.特徴抽出
4.画像表現
5.索引付けと照合
6.その他の工夫
7.検証
8.特定物体認識を作ってみる
9.むすび

4章 Bag-of-Featuresに基づく物体認識(2) - 一般物体認識 –

1.はじめに
2.一般物体認識とは?
3.局所特徴量とbag-of-features
4.分類手法
5.特徴統合による分類
6.対象位置の検出とコンテキストを利用したシーン認識
7.データセット
8.おわりに

5章 最近傍探索の理論とアルゴリズム

1.はじめに
2.最近傍探索問題
3.最近傍探索アルゴリズム
4.近似最近傍探索アルゴリズム
5.次元の呪縛を解くために
6.まとめ

6章 大規模確率場と確率的画像処理の深化と展開

1.はじめに
2.画像生成モデルと大規模確率場
3.ノイズ生成モデルとベイズ推定
4.確率伝搬法
5.情報統計力学と統計的性能評価
6.統計的機会学習理論を用いた確率的画像処理
7.おわりに

 

光学部品/カメラバイヤーズガイド

マシンビジョンで使われるFA用のレンズ、照明、キャプチャボードなど紹介します。

 

ラインセンサ用レンズ

ニコン Fマウントレンズ
栃木ニコン 高性能、高精細ラインセンサ用レンズ
Fマウント、M72マウントなど
ラインセンサ用レンズとしては超高性能
ペンタックス Fマウント、Kマウント、Cマウントレンズなど
シグマ Fマウント、Kマウントレンズなど
タムロン Fマウント、Kマウントレンズなど
シュナイダー 高精細ラインセンサ用レンズ
京セラ Fマウント、M72マウントなど

 

Cマウントレンズ

ミュートロン Cマウント、M72レンズ、M42レンズ、テレセントリックレンズ
杉藤 Cマウントレンズ
ヴイ・エス・テクノロジー Cマウント、M72レンズ、テレセントリックレンズ
オプトアート Cマウントレンズ、テレセントリックレンズ、
ハロゲン、メタルハライド照明、ライトガイド、
LED照明などなど
東京パーツセンター Cマウントレンズ、近赤外用レンズ
興和オプトロニクス Cマウントレンズ、Fマウントレンズ

 

照明

シーシーエス LED照明
シマテック LED照明
1つのLED照明でローアングルから通常のリング照明までをカバーした
ドーナツ形状の「マルチライティング」が特徴的。
日進電子 LED照明、ストロボ光源
京都電機器 LED照明、高周波蛍光灯
電通産業 高周波蛍光灯、LED照明
レボックス LED照明
ラインセンサ用として、3Mを超えるシームレスな照明もあり。
アイテックシステム LED照明
比較的安価。通販サイトもあり。光ショップ

 

カメラ

アバールデータ 近赤外カメラ、ハイパースペクトルカメラ
Teledyne DALSA ラインセンサ(モノクロ、カラー(3ライン、3CCD))
TDIカメラ、HS Linkカメラ
エリアセンサ(モノクロ)、GigEカメラ
ほぼ全てアンチブルーミング機能付き
オムロンセンテック エリアンセンサ、ラインセンサ
CameraLink, CoaXPress, Opet-C:Link,GigE, USB
日本センサリデバイス(NED) ラインセンサ(モノクロ、カラー(3ライン))
高速CMOSラインセンサ
竹中システム機器 ラインセンサ(モノクロ、カラー(3ライン))
エリアセンサ(モノクロ、カラー)
東芝テリー ラインセンサ(モノクロ、カラー(3ライン))
エリアセンサ(モノクロ、カラー)
ソニー エリアセンサ(モノクロ、カラー)、
インテリジェントカメラ
日立国際電気 エリアセンサ(モノクロ、カラー)
Adimec エリアセンサ(モノクロ、カラー)
CameraLink、Geg-E、CoaXPress
e2v ラインセンサ(モノクロ、カラー(3ライン))
Basler エリアセンサ、ラインセンサ
CameraLink、Gig-E
JAI ラインセンサ(モノクロ、カラー(3CCD、4CCD))
エリアセンサ(モノクロ、カラー(Bayer、3CCD))
cis エリアセンサ(モノクロ、カラー(Bayer、3CCD))
フローベル エリアセンサ(モノクロ、カラー)
センサーテクノロジー エリアセンサ(モノクロ、カラー)
IDT エリアセンサ(ハイスピード)
アプロリンク エリアセンサ(モノクロ、カラー)

 

キャプチャボード

アバールデータ 画像入力ボード(エリアセンサ、ラインセンサ、カメラリンク、
アナログ、デジタル)
10TapCameraLink対応品、FPGA処理ボードなどもあり。

大人の事情により、一社のみの紹介です。って、私の会社だから...

 

その他

ミスミ カメラ、照明固定用ブラケットなど
エドモンド レンズ、ミラー、光学ベンチなど
光学界のミスミ的存在。ほとんど揃います。
シグマ光機 光学部品(レンズ、ミラー、プリズムなど)
精密ステージ、ハロゲン、メタルハライド光源、ライトガイド
モリテックス Cマウントレンズ、テレセントリックレンズ、
ハロゲン、メタルハライド照明、ライトガイド、LED照明などなど
品揃え豊富
エス・エフ・シー カメラ、照明スタンド
ケンコー 各種レンズフィルタなど
F-Cマウントアダプタなどもあり。
SUS アルミフレーム、リニアアクチュエータなど
ラインセンサの撮影システムを組む時に安価に組むことができます。

 

お問い合わせについて

本ページは会社とは関係なく非公認なのですが、公知ではあるので、キャプチャボードをご検討の場合、レンズやなども含めてご質問などありましたら、弊社の問い合わせページ製品についての問い合わせはよりお問い合わせ下さい。

「イメージングソリューションというHPを見たのですが...」と言って頂けると、話が早いかも?しれません。

 

マシンビジョンへ戻る

焦点深度、被写界深度とは何か?絞りとの関係

焦点深度、被写界深度などの各名称の位置については、下図は参照ください。

 

 

上図の物体面(左側)が被写体側で、像面(右側)がカメラのセンサ側です。

 

許容錯乱円

物体面上の点を撮影したときに、像面上では点として結像し、像面から前後に外れると
円として結像します。
この円のことを錯乱円といい、ピントが合っているとみなされる最大の円を許容錯乱円といいます。
マシンビジョンでCCDカメラを用いる場合、許容錯乱円にCCD画素の大きさが用いられる場合が
多いようです。

被写界深度

物体面(被写体側)において、ピントが合って見える範囲のことを被写界深度といいます。

焦点深度

ピントが合って見える範囲において、像面側(CCDなど)の結像範囲を焦点深度といいます。
被写界深度と混同する人が多いのでご注意下さい。
通常、被写体の撮影で大事な深度は被写界深度となります。

絞りと被写界深度との関係

レンズの絞りは 明るさを調整するもの という役目もありますが、被写界深度を調整するものという大事な役割があります。

例えば、人物の撮影などでは、人物の背景をボカして撮影するには、レンズの絞りを開いて撮影します。
背景がボケるということは、被写界深度が浅い事を意味しています。

しかしながらカメラを使った画像検査をする場合、被写界深度が深い方が理想的です。

被写界深度を深くするには絞りを小さく閉じると被写界深度は深くなります。
しかしながら、そうすると画像が暗くなります。

画像が暗くなるので、画像を明るくするには

  • 照明を明るくする
  • 露光時間を長くする
  • ゲインを上げる

のいづれかの対応が必要となります。
しかしながら、それとは逆に、

  • 照明は安い物を使いたい → すごく明るい照明は高い
  • 高速に撮影したい → 露光時間は短くしないと高速に撮影できない
  • ノイズは少なくしたい → ゲインを上げるとノイズが増える

と、相反する要求もあります。

そのため総合的にカメラの撮影システムを捉え、絞りを調整する必要があります。

撮影する画像の明るさを一定にしようとすると、一般的に以下のような関係になります。

絞り 大(開) 小(閉)
深度 浅い 深い
ゲイン
ノイズ 少ない

これらの関係がどのように画像へ影響を及ぼすか?をシュミレーションできるサイトがありますので、いろいろお試し下さい。

http://camerasim.com/camera-simulator.html

上記の設定値はカメラ用語なので、用語を置き換えるなら、
Lighting(照明の明るさ)、Disatance(撮影距離、ワーキングディスタンス)、Focal Length(焦点距離)
ISO(ゲイン)、Aperture(絞り)、Shutter Speed(露光時間)
という感じでしょうか。

 

 

ただし、この計算は収差のない理想的なレンズの場合の話で、実際には像面湾曲の影響により、
像を結ぶ位置が平面からズレてしまいます。

 

このズレ量がレンズメーカに聞いてもあまり教えてくれないので、結局は全視野において
像がボケることなく撮影できるか?は撮影してみないと分からない場合がほとんどです。

 

被写界深度の計算

<計算例>
画像数2353×1728mm、画素サイズ7.4×7.4μmのカメラを用い、
レンズの焦点距離が55mmのレンズを用い、物体距離(≒ワーキングディスタンス)
300mmで撮影を行いたい場合の被写界深度の計算

 

設定条件より
許容錯乱円 =7.4μm
F=2.8の場合

 

この計算はレンズ選定(視野、撮影距離など)のページで出来るようになりました。

レンズ選定上の注意

  • 各レンズには被写体にレンズを一番近づけることの出来る距離(最短撮影距離)が設定されています。
    撮影距離Dが最短撮影距離を下回らないようにレンズを選定して下さい。
  • レンズの許容カメラフォーマットもしくはイメージサークルがCCDのサイズ以上となるレンズを選定してください。
  • レンズの公式の計算は薄肉レンズモデルの計算です。計算結果には誤差が含まれます。

 

 

余談ですが...
35mmフィルムは35mmって言っているのに、なんで36mm???と思ったりもしますが、
35mmなのはフィルムの幅で撮影領域は36mm×24mmとなります。

 

 

レンズ選定(焦点距離、WD、被写界深度の計算)

下図のような、レンズの焦点距離 f やワーキングディスタンスの求め方を紹介します。

レンズの計算には、下図のような薄肉レンズモデルを用いて計算します。

計算に必要なのは、レンズの公式と倍率の計算式です。

レンズの公式 倍率

下記、表中に数値を入力し×××計算ボタンをクリックすると、それぞれの値を計算することが出来ます。

以下、物体距離 ≒ ワーキングディスタンスとして計算します。
また、下記計算中の『センサ幅 ℓ (mm)』の値はセンサの物理的な大きさを指定するのではなく、実際の撮影に使用するセンサの領域を指定します。
例)CCD素子サイズが7μmのセンサで5000画素使用する場合、センサ幅 ℓ (mm)は
7μm × 5000画素 = 35mm
とします。

ただし、ラインセンサでラインセンサの専用レンズでなく、一眼レフカメラ用のFマウント、Kマウントレンズを用いる場合は、経験的に、ここで説明している計算でレンズを選定するよりも、マクロのf=55mmぐらいのレンズを用い、ワーキングディスタンスで視野を調整した方がきれいな画像が撮影できると思います。

 

焦点距離 f を求める場合

レンズの公式、倍率の式を変形して、

として焦点距離を求めます。

センサ幅 ℓ (mm)
視野幅 L(mm)
ワーキングディスタンス a(mm)
焦点距離 f(mm)

ワーキングディスタンス a を求める場合

レンズの公式、倍率の式を変形して、

としてワーキングディスタンスを求めます。

センサ幅 ℓ (mm)
視野幅 L(mm)
焦点距離 f(mm)
ワーキングディスタンス a(mm)

被写界深度を求める場合

被写界深度は下図のように求めます。

として被写界深度を求めます。
CCDカメラの場合、許容錯乱円 ≒ CCDの画素サイズと して計算します。

ワーキングディスタンス a(mm)
許容錯乱円 ε(μm)
F値
焦点距離 f(mm)
前側被写界深度(mm)
後側被写界深度(mm)
被写界深度(mm)


※本計算は薄肉レンズモデルの計算です。計算値には誤差が含まれます。
計算結果は参考程度に参照して下さい。

 

備考

レンズ選定の式にはここに記載してある式とは別に

という図の場合、

の関係式から、焦点距離は

として求める!

というような説明も多いかと思います。 むしろ、こちらの方が多い?!

なぜか、カメラレンズメーカーのレンズ選定の式ではこちらの式を用いる場合が多く、
ガラスレンズメーカーは最初に紹介したレンズの公式を用いて紹介している場合が多いようです。
試しに両方計算してみると分かりますが、計算結果はさほど変わりません。
おそらく、薄肉レンズモデル計算の誤差範囲???

ということから、レンズの選定の場合には計算の簡単な、こちらの式を用いるのかもしれませんが、
どうにも、焦点距離fの示している距離が気持ち悪くて、最初に説明しているレンズの公式を用いた
説明としました。
本来、焦点距離fは無限遠からの光(平行光)が入射した時に、レンズの主点から光が1点に集まる場所までの
距離を現します。
ワーキングディスタンスもレンズ本体(筐体)の先端からの距離ですが…
この辺の名称の詳細はレンズ周りの名称のページを参照願います。