2014-03-31 5 views
0

SURF 및 Naive Bayesian을 사용하여 분류 자 ​​/ 예측자를 만들려고합니다. 나는 Dance, Csurka의 "Keypoints 가방으로 시각적 분류"라는 기술을 거의 따르고 있습니다 ... 나는 SIFT 대신 SURF를 사용하고 있습니다.내 SURF/KMeans classifier에 문제가 있습니다

내 결과는 꽤 끔찍하며 내 오류가 어디에 있는지 잘 모르겠습니다. CalTec 세트에서 20 개의 자동차 샘플 (햄)과 20 개의 오토바이 샘플 (스팸)을 사용하고 있습니다. 나는 내가 어휘를 만드는 방식에 있다고 생각한다. 내가 볼 수있는 것은 EMGU/OpenCV kmeans2 분류기가 동일한 SURF 디스크립터 입력에서 다른 결과를 반환한다는 것입니다. 그것은 나를 의심스럽게 만든다. 지금까지 제 코드가 있습니다.

public Matrix<float> Extract<TColor, TDepth>(Image<TColor, TDepth> image) 
     where TColor : struct, Emgu.CV.IColor 
     where TDepth : new() 
    {    
     ImageFeature[] modelDescriptors; 

     using (var imgGray = image.Convert<Gray, byte>()) 
     { 
      var modelKeyPoints = surfCPU.DetectKeyPoints(imgGray, null); 
      //the surf descriptor is a size 64 vector describing the intensity pattern surrounding 
      //the corresponding modelKeyPoint 
      modelDescriptors = surfCPU.ComputeDescriptors(imgGray, null, modelKeyPoints); 
     } 

     var samples = new Matrix<float>(modelDescriptors.Length, DESCRIPTOR_COUNT);//SURF Descriptors have 64 samples 
     for (int k = 0; k < modelDescriptors.Length; k++) 
     { 
      for (int i = 0; i < modelDescriptors[k].Descriptor.Length; i++) 
      { 
       samples.Data[k, i] = modelDescriptors[k].Descriptor[i]; 
      } 

     } 

     //group descriptors into clusters using K-means to form the feature vectors 
     //create "vocabulary" based on square-error partitioning K-means 
     var centers = new Matrix<float>(CLUSTER_COUNT, samples.Cols, 1); 
     var term = new MCvTermCriteria(); 
     var labelVector = new Matrix<int>(modelDescriptors.Length, 1); 
     var cluster = CvInvoke.cvKMeans2(samples, CLUSTER_COUNT, labelVector, term, 3, IntPtr.Zero, 0, centers, IntPtr.Zero); 

     //this is the quantized feature vector as described in Dance, Csurska Bag of Keypoints (2004) 
     var keyPoints = new Matrix<float>(1, CLUSTER_COUNT); 

     //quantize the vector into a feature vector 
     //making a histogram of the result counts 
     for (int i = 0; i < labelVector.Rows; i++) 
     { 
      var value = labelVector.Data[i, 0]; 
      keyPoints.Data[0, value]++; 
     } 
     //normalize the histogram since it will have different amounts of points 
     keyPoints = keyPoints/keyPoints.Norm; 
     return keyPoints; 
    } 

출력이 NormalBayesClassifier로 입력됩니다. 이것이 내가 그것을 훈련시키는 방법이다.

Parallel.For(0, hamCount, i => 
      { 
       using (var img = new Image<Gray, byte>(_hams[i].FullName)) 
       { 
        var features = _extractor.Extract(img); 
        features.CopyTo(trainingData.GetRow(i)); 
        trainingClass.Data[i, 0] = 1; 
       } 
      }); 

     Parallel.For(0, spamCount, j => 
     { 
      using (var img = new Image<Gray, byte>(_spams[j].FullName)) 
      { 
       var features = img.ClassifyFeatures(_extractor); 
       features.CopyTo(trainingData.GetRow(j)); 
       trainingClass.Data[j + hamCount, 0] = 0; 
      } 
     }); 

     using (var classifier = new NormalBayesClassifier()) 
     { 
      if (classifier.Train(trainingData, trainingClass, null, null, false)) 
      { 

       classifier.Save(_statModelFilePath); 
      } 
     } 

나는 훈련 샘플의 모든 ... 햄과 스팸은 1 (경기를) 반환 NormalBayesClassifier을 사용하여 예측 호출 할 때.

도움을 주시면 감사하겠습니다.

편집. 한 가지 다른 참고 사항은 5 ~ 500 개의 CLUSTER_COUNT를 모두 동일한 결과로 선택했다는 것입니다.

답변

0

문제는 기술적 인 것보다 개념적이었습니다. 나는 K Means 클러스터가 "전체"데이터 세트에 대한 어휘를 구축하고 있다는 것을 이해하지 못했습니다. 이 작업을 올바르게 수행하는 방법은 CvInvoke.cvKMeans2 호출에 모든 이미지의 모든 기능을 포함하는 학습 행렬을 제공하는 것입니다. 저는 한 번에 하나의 이미지를 토대로 어휘를 만들었습니다.

최종 해결책에는 SURF 코드를 자체 메서드로 가져 와서 각 햄 및 스팸 이미지에서 실행하는 것이 포함됩니다. 그런 다음 대규모 결과 집합을 사용하여 교육 매트릭스를 작성하고이를 CvInvoke.cvKMeans2 메소드에주었습니다. 훈련을 끝내는 데 꽤 오랜 시간이 걸렸습니다. 약 3000 이미지가 있습니다.

내 결과가 더 좋았습니다. 예측 데이터는 학습 데이터로 100 % 정확했습니다. 내 문제는 지금 예측할 수있는 비율이 훈련 데이터가 아닌 경우에도 여전히 좋지 않기 때문에 피팅으로 인해 어려움을 겪을 가능성이 높다는 것입니다. SURF 알고리즘의 헤센 임계 값 및 클러스터 수를 사용하여 오버 피팅을 최소화 할 수 있는지 확인합니다.