2

機能システム画像認識システムのバッグを書こうとしています。アルゴリズムの1つのステップは、多数の小さな画像パッチ(たとえば、7x7または11x11ピクセル)を取得し、それらを類似したグループにクラスター化することです。画像からパッチを取得し、それらをグレースケール浮動小数点画像パッチに変換してから、cvKMeans2を取得してそれらをクラスター化しようとします。KMeans2が一貫した結果を返すように入力データをフォーマットするのに問題があると思います。私は以前に2Dおよび3DクラスタリングにKMeansを使用しましたが、49Dクラスタリングは別の獣のようです。

返されたクラスターベクトルのガベージ値を取得し続けるので、明らかにこれはガベージイン/ガベージアウトタイプの問題です。さらに、アルゴリズムは、このような巨大なデータセットの場合よりもはるかに高速に実行されます。

以下のコードでは、ストレートmemcpyは、入力データを正しい形式で取得するための最新の試みにすぎません。組み込みのOpenCV関数を使用してしばらく過ごしましたが、基本タイプがCV_32FC(49)の場合は困難です。

OpenCV 1.1のKMeansアルゴリズムは、この種の高次元分析をサポートできますか?

画像からK-Means入力行列にコピーする正しい方法を誰かが知っていますか?

代わりに使用できる無料の非GPLKMeansアルゴリズムを誰かに教えてもらえますか?

私は今、物事を機能させようとしているだけなので、これは最良のコードではありません。

    std::vector<int> DoKMeans(std::vector<IplImage *>& chunks){
 // the size of one image patch, CELL_SIZE = 7
 int chunk_size = CELL_SIZE*CELL_SIZE*sizeof(float);
 // create the input data, CV_32FC(49) is 7x7 float object (I think)
 CvMat* data = cvCreateMat(chunks.size(),1,CV_32FC(49) );


 // Create a temporary vector to hold our data
 // we'll copy into the matrix for KMeans
 int rdsize = chunks.size()*CELL_SIZE*CELL_SIZE;
 float * rawdata = new float[rdsize];

 // Go through each image chunk and copy the 
 // pixel values into the raw data array.
 vector<IplImage*>::iterator iter;
 int k = 0;
 for( iter = chunks.begin(); iter != chunks.end(); ++iter )
 {

  for( int i =0; i < CELL_SIZE; i++)
  {
   for( int j=0; j < CELL_SIZE; j++)
   {
    CvScalar val;
    val = cvGet2D(*iter,i,j);
    rawdata[k] = (float)val.val[0];
    k++;
   }

  }
 }

 // Copy the data into the CvMat for KMeans
 // I have tried various methods, but this is just the latest.
 memcpy( data->data.ptr,rawdata,rdsize*sizeof(float));

 // Create the output array
 CvMat* results = cvCreateMat(chunks.size(),1,CV_32SC1);

 // Do KMeans
 int r = cvKMeans2(data, 128,results, cvTermCriteria(CV_TERMCRIT_EPS+CV_TERMCRIT_ITER, 1000, 0.1));

 // Copy the grouping information to our output vector
 vector<int> retVal;
 for( int y = 0; y < chunks.size(); y++ )
 {
  CvScalar cvs = cvGet1D(results, y);
  int g =  (int)cvs.val[0];
  retVal.push_back(g);
 }

 return retVal;}

前もって感謝します!

4

2 に答える 2

0

私は「bag of features」に詳しくありませんが、コーナー検出器や SIFT などの特徴点を使用することを検討しましたか?

于 2010-06-30T09:32:38.167 に答える
-1

別のオープン ソース クラスタリング パッケージについては、http://bonsai.ims.u-tokyo.ac.jp/~mdehoon/software/cluster/を参照してください。

このような memcpy の使用は疑わしいようです。

 int rdsize = chunks.size()*CELL_SIZE*CELL_SIZE;

CELL_SIZE と chunks.size() が非常に大きい場合、rdsize に大きなものを作成しています。これが格納可能な最大の整数よりも大きい場合、問題が発生する可能性があります。

この関数の「チャンク」を変更しますか? これはK-meansの問題なので、そうではないと思います。

ここで const への参照渡しを試してみてください。(そして、一般的に言えば、これはあなたがやりたいことです)

代わりに:

std::vector<int> DoKMeans(std::vector<IplImage *>& chunks)

それはそのようになります:

std::vector<int> DoKMeans(const std::vector<IplImage *>& chunks)

この場合も、古い c スタイルのキャストよりも static_cast を使用する方が適切です。(たとえば、 (float)variable ではなく static_cast(variable) )。

また、「生データ」を削除することもできます。

 float * rawdata = new float[rdsize];

次の方法で削除できます。

delete[] rawdata;

そうしないと、ここでメモリリークが発生する可能性があります。

于 2010-06-27T17:20:19.647 に答える