プログラミングを解説したり、音楽の紹介とか、スポーツ・趣味の紹介とか。1人でも見てくれる人がいる限り、更新を続けます。
上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。
アフィン変換は、ある点Pを線形変換で、ある点Qに、写像する座標変換です。画像分野では、画像の拡大・縮小・回転・移動や画像処理で使われます。ここでは、アフィン変換(画像処理関係なし次回やるかも・・・)だけのC言語プログラムを紹介したいと思います。


アフィン変換の詳しい説明は、wikipediaでも見てもらって、要は、下記のような行列演算で、ある座標x,y,zを新しい座標cx,cy,czに変換することになります。
アフィン変換式

式を見ればわかるように、a11〜a34までの8個のパラメータを指定するだけで、3次元画像の座標変換ができてしまいます。どこを変えれば、回転とか、拡大とかは、他のサイトを見てください。

作成したC言語プログラムは、アフィン変換を使用しやすいように、行列の設定で回転や平行移動や拡大縮小専用の関数を作っています。座標変換をするときは、まずSetMatrix〜関数で行列を設定して、ConvertCoordinate関数で変換座標を取得するというようにしてください。


// C言語、アフィン変換プログラム
#include "stdafx.h" // VisualStudio2008でCプログラムを作成するのに必要
#include <malloc.h> // malloc/callocといった動的メモリ確保のために必要
#include <math.h> // 数学関数を使用するためのヘッダ
#include <iostream>
using namespace std; // VisualStudio2008でCプログラムを作成するのに必要
using namespace System;

#define PI 3.1415

// double型の二次元配列動的メモリ確保
double** GetDoubleArrayMemory(int xSize, int ySize)
{
int i;
double** arraydata;

// 2次元配列を動的に確保
// callocで縦方向の動的メモリ確保。
arraydata = (double**)calloc(ySize, sizeof(double*));
if(arraydata == NULL) // メモリが確保できなければ終了
{
printf("縦方向の動的メモリが確保できません。\n");
}
for(i = 0; i < ySize; i++)
{
// callocで横方向の動的メモリ確保。
arraydata[i] = (double*)calloc(xSize, sizeof(double));
if(arraydata[i] == NULL) // メモリが確保できなければ終了
{
printf("横方向の動的メモリが確保できません。\n");
}
}
return arraydata;
}

// degreeからradianに変換
double ConvertAngleToRadian(double angle)
{
return angle * PI / 180;
}

// X軸回りの回転設定
double** SetMatrixXRotate(double angle)
{
double** matrix = GetDoubleArrayMemory(4, 4);
matrix[0][0] = 1;
matrix[1][1] = cos(ConvertAngleToRadian(angle));
matrix[2][1] = -sin(ConvertAngleToRadian(angle));
matrix[1][2] = sin(ConvertAngleToRadian(angle));
matrix[2][2] = cos(ConvertAngleToRadian(angle));
matrix[3][3] = 1;
return matrix;
}

// Y軸回りの回転設定
double** SetMatrixYRotate(double angle)
{
double** matrix = GetDoubleArrayMemory(4, 4);
matrix[0][0] = cos(ConvertAngleToRadian(angle));
matrix[2][0] = sin(ConvertAngleToRadian(angle));
matrix[1][1] = 1;
matrix[0][2] = -sin(ConvertAngleToRadian(angle));
matrix[2][2] = cos(ConvertAngleToRadian(angle));
matrix[3][3] = 1;
return matrix;
}

// Z軸回りの回転設定
double** SetMatrixZRotate(double angle)
{
double** matrix = GetDoubleArrayMemory(4, 4);
matrix[0][0] = cos(ConvertAngleToRadian(angle));
matrix[1][0] = -sin(ConvertAngleToRadian(angle));
matrix[0][1] = sin(ConvertAngleToRadian(angle));
matrix[1][1] = cos(ConvertAngleToRadian(angle));
matrix[2][2] = 1;
matrix[3][3] = 1;
return matrix;
}

// 拡大・縮小設定
double** SetMatrixScale(double s1, double s2, double s3)
{
double** matrix = GetDoubleArrayMemory(4, 4);
matrix[0][0] = s1;
matrix[1][1] = s2;
matrix[2][2] = s3;
matrix[3][3] = 1;
return matrix;
}

// 平行移動設定
double** SetMatrixTranslate(double t1, double t2, double t3)
{
double** matrix = GetDoubleArrayMemory(4, 4);
matrix[0][0] = 1; matrix[3][0] = t1;
matrix[1][1] = 1; matrix[3][1] = t2;
matrix[2][2] = 1; matrix[3][2] = t3;
matrix[3][3] = 1;
return matrix;
}

// 座標変換(アフィン変換実行)
void ConvertCoordinate(
double** matrix,
double x,
double y,
double z,
double *cx,
double *cy,
double *cz)
{
*cx =
matrix[0][0] * x +
matrix[1][0] * y +
matrix[2][0] * z +
matrix[3][0] * 1;
*cy =
matrix[0][1] * x +
matrix[1][1] * y +
matrix[2][1] * z +
matrix[3][1] * 1;
*cz =
matrix[0][2] * x +
matrix[1][2] * y +
matrix[2][2] * z +
matrix[3][2] * 1;
}

int main(array<System::String ^> ^args)
{
// 変換前座標
double x = 1;
double y = 1;
double z = 1;

// 変換後座標
double cx, cy, cz;

// 変換設定(x軸90度回転)
double** matrix = SetMatrixXRotate(90);

// 変換実行
ConvertCoordinate(matrix, x, y, z, &cx, &cy, &cz);

// 結果出力
printf("変換前: (x, y, z) = (%f, %f, %f)\n", x, y, z);
printf("変換後: (cx, cy, cz) = (%f, %f, %f)\n", cx, cy, cz);

return 0;
}

実際に画像拡大縮小する場合は、座標アフィン変換後、飛び飛びになったピクセル間を補間する必要がありますが、それについては次回やります。

ちなみにC#で書くと
http://colnagow61s.me.land.to/affine_transform.zip
ソースコードを置いておきます。

詳解 画像処理プログラミング C言語で実装する画像処理アルゴリズムのすべて
詳解 画像処理プログラミング C言語で実装する画像処理アルゴリズムのすべて昌達 慶仁

ソフトバンククリエイティブ 2008-03-27
売り上げランキング : 5054

おすすめ平均 star
starとてもわかりやすくて、多くのアルゴリズムを網羅しています。

Amazonで詳しく見る


新版 明解C言語 入門編
新版 明解C言語 入門編柴田望洋

ソフトバンククリエイティブ 2004-08-28
売り上げランキング : 1324

おすすめ平均 star
star満足
star見易さ・解説の徹底具合
star十分明解だが…

Amazonで詳しく見る
コメント
この記事へのコメント
コメントを投稿する
URL:
Comment:
Pass:
秘密: 管理者にだけ表示を許可する
 
トラックバック
この記事のトラックバックURL
http://thorshammer.blog95.fc2.com/tb.php/246-eafed393
この記事にトラックバックする(FC2ブログユーザー)
この記事へのトラックバック
QLOOKアクセス解析