1. Top » 
  2. 画像処理

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。
  • Genre:

画像処理論の話、試験前のダイジェスト版。

試験前のダイジェスト版です。

セグメンテーション
 画像中から、ある規則性をもったパターンを抽出する。
 2次元パターンのことを領域、1次元パターンのことを線分と呼ぶ。

セグメンテーションの主な処理
 閾値処理、クラスタリング、領域分割、エッジ検出、線分検出

閾値処理
 画素値に基づいて、画像を2つ異常の領域にわけること
 単純閾値法
 pタイル法
  画像全体のp%が1つの山になっていることが分かっているときの手法
  ほとんど使えない
 モード法
  二つの山のピークの間のもっとも深い谷になる部分を閾値として2分割する。
  このとき、その閾値の画素の個数は最大値の何分の一倍かにする。
 正規分布の当てはめ
  二つの正規分布が重なっていると仮定して、重みθを用いた和を考えて分割する。
  二つの平均値の差は十分大きく、また分散は出来るだけ近いこと
 判別分析
  ロバストな処理
  ヒストグラムを二つのクラスC0とC1に分けて、二つのクラス間分散が最大になるように
  閾値を変えながら最良の分割を探す。

クラスタリング
 固まっている点を見つける
 K-means法

領域分割処理
 領域拡張法
  ある点を初期値として選び、そこから似ている画素を取り込んで領域を広げていく
 再帰的閾値処理
  画像全体から処理を初めて、再帰的に小さくなるように分割していく

エッジ検出
 勾配、微分を用いる。それを計算するための移動平均用の行列=フィルタがある。
 一階微分には様々な種類があるが、もっとも優れているモノはSobelフィルタである。
 二階微分に相当するフィルタはラプラシアンである。
 より優れた処理をするためにラプラシアンに平滑化を合わせて行う作用素があり
 ラプラシアンガウシアン作用素と呼ぶ。
 他の考え方から作られた作用素としてヒュッケル作用素、キャニー作用素があるが
 もっとも優れているモノはラプラシアンガウシアン作用素であると近似できる。

線分抽出
 ノイズを含むもの、ノイズを含まないモノの違いがある。
 ノイズを含まなければ、繰り返し折れ線近似をする。
 繰り返し折れ線近似
  遠いところと最初に結び、別の点を考えて、それとの距離がある値以上なら
  それを折れ線の中に入れる
 Hough変換 
  ノイズに強い手法の1つ。
  ある直線をy=ax+bではなく、ヘッセの標準形としてρ=x1cosθ+y1sinθで表す。
  ある直線上の点x1,y1を用いてρ-θ曲線が引ける。
  ある直線上の点から引いた複数のρ-θ曲線は、ρ-θ平面で一点で交わることを用いる。
  ρとθを配列的に準備して、相当する部分を投票していく
  もっとも個数がある配列の位置にあるρとθによって直線が復元できるはず。
  このときρが最大でも画像の対角線と、有限値になるためパソコンで用いることが出来る
 アウトフライヤ
  だいたいの似たようなデータから一つだけ飛び出たノイズのこと
 アウトフライヤを取り除く
  通常の最小二乗法では、アウトフライヤの影響が強く出てしまう。
  これを取り除くためには、なるべく近いところの重みを大きくしたり
  またメジアンフィルタを用いてアウトフライヤを弾く処理を行う


前処理
 画像を実際にパターン認識やセグメンテーション処理を行うときに用いる形式へ修正する。
 カメラなどから入ってきた画像を、扱いやすいようにノイズやずれを解消する課程

前処理の考え方
 空間領域での処理、移動平均(フィルタリング)と、周波数領域での処理、周波数フィルタの
 2つで考えることが出来る。昔は画像をFourier変換した後でフィルタをかまして、その後
 逆Fourier変換を行う処理の方が早かった。二つの考え方で取り除きやすいノイズの種類が変わる。

平滑化
 移動平均であれば均一値のフィルタ、または中心に重みをつけたフィルタになり
 これは周波数領域におけるLPFに相当する。

画像復元の枠組み
 取得画素値fdはオリジナルの値fにある劣化関数hがかかり、ノイズnが乗ったモノである。
 劣化関数hが相対位置のみに依存するなら、fdはfとhのコンボリューションにnを加えたモノになる。
 fdの復元の考え方としては逆フィルタとウィーナーフィルタがある。

逆フィルタ
 逆Fourier変換によってfを求める。
 ノイズがある場合とない場合で少し変わる。
 
ウィーナーフィルタ
 復元画素値Fと新しい画素値Fdの絶対値がもっとも小さくなるようなフィルタMを
 求める。このとき、単純に求めるのではなく、その平均値E[||F-Fd||]が最小になるようにする。

復元の種類
 幾何的復元と光学的復元がある。

画素値が足りない場合
 補間処理を行う。
  最近隣補間       もっとも近い画素値を採用
  共一次補間       周り4点の画素値と、距離を用いた重みによって画素値を作る 
  3次たたみ込み補間  Sinc関数、またはその近似関数を用いて画素値を作る
 がある。
スポンサーサイト

Hough変換

次の図を用います。

eye.jpg

前回からよく使っているおめめ画像。
小さいものを利用するのは、ようするに処理をあまり膨大にさせないため。
これをそれを、おそらくエッジかなにか掛けて先鋭化して
それを2値化したもの。
これにHough変換を用いて円、おめめを検出する。

ようするに白い部分な何かしらの円の一部であると過程して解く。
実際には三次元配列を用いると任意の大きさの円だって大丈夫なわけだが
今回はおめめが20pxと分かっている仮定でやる。


counter.jpg



これが円の中心のカウントを20倍ぐらいして見やすくしたもの。
白い点を見つけたとき、そこを中心とした半径20pxの円をカウントする。
この投票情報の最高の値をもつ部分を探して、実際に円を描く


bin.jpg

おおぉ。
おめめの円の部分が細いながらも復活。

デジタル画像処理における色表現の談話 三回目

考え方を変えた色の表現には星の温度と色の関係などでも知られている
色温度というものがあり、低い温度ほど赤く、高い温度ほど青白くなることはよく知られています。

 以上まとめますと、色が存在する色空間というものを私たちの尺度で上手く表現する。
かつデジタル画像処理に利用出来るように定量的に表現するための軸が表色系であり、
軸のとり方によって様々な表色系が存在するということが分かります。

 また表色系によって表現できる色の違いがあり、またその表現がどれだけ
人の感覚に近いかどうかなどの違いもあります。

 例えば LAB 均等色空間やもっと難しい変換式を用いた六角錐カラーモデルなどは
人の感覚に近い表色系と言われています。

 色の表現においては、色の文化差や照明などによる色相の変化など、色を事細かく
完全に表現するのは難しいことも多いですが、どのような表色系で考えているのか
どれだけの色を表現できているか、またこの色は人間の感覚に近いのかどうかなどを
意識することが必要だということです。

 最後に余談ですが、例えば Java で画像を扱うとき、主に BufferedImage というクラスを
使うことが多いですが、BufferedImage を作成するとき、様々な ColorSpace を選んで画像を
初期化する必要があります。例えば

  TYPE RGB
  TYPE XYZ
  TYPE YCbCr
  TYPE HSV


などです。
話に出てきたRGB表色系、XYZ表色系、HSV表色系などが利用できるのですね。

 このようにデジタル画像処理にとって色表現の考え方は切り離せないものだということです。

デジタル画像処理における色表現の談話 二回目

 色というものを史的に最初に考え始めたマンセルという人だと言われています。
マンセルが、最初に色の表現法として考案したものがマンセル色相環と言われているものです。
この表色に関する考え方は現在でも芸術等の分野で利用されています

 http://ja.wikipedia.org/wiki/マンセル・カラー・システム

を参考にするといいでしょう。
 マンセル色相環はある立体を上から見たものと解釈されます。
この立体のことをマンセル色立体と呼びます。
もしかしたらこの二つはどこかで目にしたことがあるかもしれませんね。

 ここで色立体が示すような新しい色の表現を利用することが出来ます。
それは色を「色相 (Hue)」「明度 (Value)」「鮮度 (Saturation)」の HVS という三つの量の
組み合わせで表現する方法です。この表現法式のことをマンセル表色系と呼びます。

 RGB 表色系は広い範囲の色を表現出来ます。
しかしRGB表色系では一部表現できない色があると指摘されています。
また画像処理で頻繁に扱われる人の顔を表現する際の肌色の表現も
RGB 表色系では不完全であると指摘されています。一方、マンセル表色系は
RGB 表色系よりも肌色や花の色などをを上手く表現できると言われています。

 これらの表色系は、様々な変換式で変換することで別の表色系として用いられることがあり
例えば RGB 座標系をある定数行列で線形変換した XYZ 座標系があります。
なお人工的に作った XYZ 表色系では、RGB 表色系よりも広く色を表現出来ると
言われています。
 この XYZ を用いてあるパラメータxyzを作り、それを平面にプロットしたものを色度図と言います。
色度図はおそらく多くの人が見たことがあるのではないでしょうか。
色度図ではどれだけの範囲の色を表現できるかを平面的に見ることができます。
プリンタやそういったたぐいのもののマニュアルなんかにあるかもしれません。

 この表色系の変換は、線形変換であることが前提になっています。
しかし変換には非線形な変換を用いたCIELAB 均等色空間なども有名です。
それらの変換は人間の感覚に色を近づけることを主な目的として行います。

 またそれとは逆に、機械側が扱いやすいようにとした変換もあり
カラーテレビと白黒テレビが混在していた時代に使われていたようです。
この変換によって作られる表色系は YIQ 表色系と呼びます。

デジタル画像処理における色表現の談話 一回目

 「色(Color)」というものは人によって見え方が異なります。
そのことから例えば「赤色」一つ取ってみても
 
 「鮮やかな赤」
 「燃えるような赤」
 「紅」

など、様々な慣用的な色の表現、慣用色名がついています。
画像というものは結局のところ様々な色を持っている「画素(Pixel)」という単位の
集合である 2 次元データなわけですから、それぞれの画素がどのような色をであるかを、
慣用色名のような定性的な表現ではなく定量的に扱う必要があります。

 実際色というものは、その場の光源や背景色などでも見え方がことなってくるのですが
こういったものを上手く数値として表現することがデジタル画像処理には必要不可欠になります。

 また色は様々な色が混ざりあって出来ているのですが
色の混ざり方も大きくわけて二つの方式に分けられます。
その一つが「加法混色」と呼ばれ、もう一方が「減法混色」と呼ばれます。

 色の元として絵の具やインクなど現実の印刷物で用いられているものを用いる場合
色の混ざり方は減法混色になり、逆にディスプレイのように光を混ぜたときに出来る色は
加法混色になります。
つまり減法混色では色を混ぜれば混ぜるほど色がくすみ、黒色に近くなります。
また逆に加法混色では色を重ねて幾度に明るくなり、最終的に白色に近づきます。

 以上のことを踏まえて、数値的な色の表現を考えて行きます。
まず数値で色を表現するということは、ある数値に色を対応させる写像と考えることができますが
その色が存在している空間を色空間(Color Space)と呼び、ある立体で表されます。
 そして色空間を構成し、「色」というものを定量的に心理的概念に基づいて表現する系のことを
一般的に「表色系」と呼びます。

 表色系にも様々ありますが、もっとも一般的に知られているものは、色の三原色と呼ばれ
ている赤、緑、青色の光を元にして全ての色を表現する RGB 表色系です。
RGB 表色系は国際照明委員会 (CIE) の定めた表色系の一つです。
 またプリンタのインクに利用されているようにYellow/Magenta/Cyan の三つを基本色として
色を表現する CMY 表色系も有名で身近に利用されています。

おめめのエッジ、比較中

画像処理論の課題中。
おめめのエッジを比較しています。

compare_eye.png

ディザ法

ディザ法、二値化する課題で書きましたが・・・。
なんとも適当だな。
C言語なんてこのありざまだよ。

void improc(int *image, int width, int height){
// ディザ行列を閾値にして二値化して値を設定する

// 行列の定義
int dither[2][2] = { { 51, 153}, { 204, 102} };

// 配列で処理
int i, j;
for( i = 0; i < width * height - 3; i+=2 ){
// 0/2/4,,,行目は行列の一行目で行う
if( ( i / width ) % 2 == 0 ){
//printf("A:%d %d\n", i, i+1);
image[i] = image[i] > dither[0][0] ? 255 : 0;
image[i+1] = image[i+1] > dither[0][1] ? 255 : 0;

// 1/3/5,,,行目は行列の二行目で行う
}else{
//printf("B:%d %d\n", i, i+1);
image[i] = image[i] > dither[1][0] ? 255 : 0;
image[i+1] = image[i+1] > dither[1][1] ? 255 : 0;
}
}
}



入力画像はこんなやつ。
rackey.jpg

犬。
出力するとこんなんなっちゃうよ。
kadai1.jpg

画像処理論でよく使っているPGMファイル

画像処理論(火曜一限)で、時々プログラムの課題が出るのだよ。
それ自体は別に難しいこともないのですがPGMファイルというのをよく使っています

ld.jpg

たとえばこのような画像。
ようするに白黒に近いモノクロ画像なんですがWindows標準では開けません。
Linuxでは標準で使えるんだけどねー。

中身は

 55 62 120 255 ・・・

みたいな感じで値が並んでいるのです。
これを読み込んで処理するのが課題なのだよー。
読み込むのは標準で与えられてるんだけどね。


#define STRING_BUFFER  24
#define PGM_MAXNUM 16

int getsize(char* name, int *width, int *height){
FILE *fi;
char buffer[STRING_BUFFER];
int point = 0;
int counter= 0;

if((fi = fopen(name,"r")) == NULL){
fprintf(stderr, "File not found. - %s -\n",name);
exit(1);
}

while(!feof(fi)){
while((buffer[point] = (char)getc(fi)) != ' '
&& buffer[point] != '\n' && !feof(fi)){
point++;
if(point > STRING_BUFFER){
fprintf(stderr, "Buffer Overflow\n");
exit(1);
}
}
if(buffer[0] >= (int)'0' && buffer[0] <= (int)'9'){
counter++;
if(counter == 1){
*width = atoi(buffer);
}else if(counter == 2){
*height = atoi(buffer);
}else{
fclose(fi);
return 0;
}
}
point=0;
}

fclose(fi);

return 1;
}

void input(char* name, int *image, int width, int height)
{
FILE *fi;
char buffer[STRING_BUFFER];
int point = 0, counter = -4;
if((fi = fopen(name,"r")) == NULL){
fprintf(stderr, "File not found. - %s -\n",name);
exit(1);
}
while(!feof(fi)){
while((buffer[point] = (char)getc(fi)) != ' '
&& buffer[point] != '\n' && !feof(fi)){
point++;
if(point > STRING_BUFFER){
fprintf(stderr, "Buffer Overflow\n");
exit(1);
}
}
buffer[point] = '\0';
if(buffer[0] >= (int)'0' && buffer[0] <= (int)'9'){
counter++;
if(counter >= 0 && counter < height*width){
image[counter] = atoi(buffer);
}
}
point = 0;
}
fclose(fi);
return;
}

void output(char* name, int *image,int width, int height)
{
FILE *fo;
int i = 0;
if((fo = fopen(name,"w")) == NULL){
fprintf(stderr, "File not found. - %s -\n",name);
exit(1);
}
fprintf(fo,"P2\n%d %d\n255\n",width,height);
for(i = 0; i < height*width; i++){
if(i != 0 && i % PGM_MAXNUM == 0){
fprintf(fo, " \n");
}else if(i != 0){
fprintf(fo, " ");
}
fprintf(fo, "%d", image[i]);
}
fprintf(fo," \n");
fclose(fo);
return;
}


まぁ、一切読んでないけど・・・。
余裕が出たら読んでみますかね?

OpenCVでのカメラの初期化を見直す

必要なもの

 #include <stdio.h>
 #include <highgui.h>



変数宣言

 int key; // キー入力用の変数
 CvCapture *capture; // カメラキャプチャ構造体
 IplImage *frameImage; // キャプチャ画像用IplImage
 char windowNameCapture[] = "capture"; // ウィンドウの名前



カメラの初期化-NULLだったら使っちゃだめ!-

 if( ( capture = cvCreateCameraCapture( -1 ) ) == NULL ){
  printf("カメラが見つかりません。\n");
  return -1;
 }



ウィンドウを作る-きっとhighgui.hを使うのだろう。-

 cvNamedWindow( windowNameCapture, CV_WINDOW_AUTOSIZE );



メインの処理

 // 入力画像の1フレームをframeImageに格納する
 frameImage = cvQueryFrame( capture );

 // 画像の表示
 cvShowImage( windowNameCapture, frameImage );


 // 'q'でループを抜ける
 key = cvWaitKey( 1 );
 if( key == 'q' ){
  break;
 }




後処理

 // キャプチャを解放する
 cvReleaseCapture( &capture );
 
 // ウィンドウを破棄する
 cvDestroyWindow( windowNameCapture );




これだけでカメラが使えるなんて!

OpenCVの開発をBccDeveloperで行う。

BccDeveloperとはフリーのコンパイラを統合開発環境っぽく使えるフリーソフト。
これと、Borland C++ Compiler 5.5を用いてOpenCVを使い方。
わざわざVisualSdudioなんかいれないよ!って人にはよい(私)

とりあえず
・Borland C++ Compiler 5.5
・Bcc Developer
をインストールして
・SetBcc
というフリーソフトを使って環境をインストール済みの人を前提。
ちなみに私は両方ともDドライブにインストールしてますので、適宜読みかえお願いします。

「d:\borland\bcc55\bin」にパスが通っているか?


OpenCVのlibをBcc用に変換。


 ※適当にドライブなどにコピーして作業する(プログラムが上書きできない)
 私は
  C:\opencvlib
  C:\opencvlib\lib
 の二つを利用してしました。

 coff2omf cv.lib lib\cv.lib
 coff2omf cvaux.lib lib\cvaux.lib
 coff2omf cvcam.lib lib\cvcam.lib
 coff2omf cvhaartraining.lib lib\cvhaartraning.lib
 coff2omf cxcore.lib lib\cxcore.lib
 coff2omf cxts.lib lib\cxts.lib
 coff2omf highgui.lib lib\highgui.lib
 coff2omf ml.lib lib\ml.lib

 これで
  C:\opencvlib\lib
 にBcc用のlibができました。
 
 これを
  D:\Program Files\OpenCV\bcc_lic
 に移しておきます。



Bccの設定 一応しましょう。


 D:\borland\bcc55\bin\bcc32.cfg
に以下を記述します。(はじめから入っているものは、そのまま!)


 -I"C:\borland\bcc55\include"
 -L"C:\borland\bcc55\lib"
 -I"D:\Program Files\OpenCV\cv\include"
 -I"D:\Program Files\OpenCV\cxcore\include"
 -I"D:\Program Files\OpenCV\otherlibs\highgui"
 -L"D:\Program Files\OpenCV\lib"



 C:\borland\bcc55\bin\ilink32.cfg
に以下を記述します(はじめから入っているものは、そのまま!)


 -L"C:\borland\bcc55\lib";"D:\Program Files\OpenCV\bcc_lib"



Bcc Developer


1.プロジェクトの作成
2.プロジェクトの設定
 → リンカ
ここで、今作ったlibファイルを追加します(全部)
 ※私は一つだけ cvhaartraining.のdllがエラーが発生したのではずしました。

3.お約束通り、dllをプロジェクト下のDebug(またはRelease)の
 実行ファイルが存在する場所にコピー

たぶん。
大丈夫。
適宜再起動必要。

Page Top

訪問者

お引っこし。 http://parabola.sblog.jp/

プロフィール

parabola0

Author:parabola0
Twitter用ですが…。
プロフィール

最新記事
最新コメント
最新トラックバック
カテゴリ
月別アーカイブ
検索フォーム
リンク

このブログをリンクに追加する

QRコード
QRコード
RSSリンクの表示
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。