现在的位置: 首页 > 综合 > 正文

SIFT特征基于OpenCV的BOW程序

2013年10月10日 ⁄ 综合 ⁄ 共 3781字 ⁄ 字号 评论关闭

-----------------------------------------------------------------------------

已经提取的SIFT特征文件格式:

 

<N>:所有图片的数量

      <M1>:每一张图片的SIFT特征数

              <1>:第一个1个128维sift特征

              <2>第二个...

              < . >

              < . >

              <m0>第m0个...

      <M2>

              .

              .

              .

      <MN>

----------------------------------------------------------------------------

CHistogram.h

#ifndef _C_HISTOGRAM_H
#define _C_HISTOGRAM_H

#include <cv.h>
#include <vector>

const int cnFeatureDimension = 128; //特征向量的维数
const int cnClusterNumber = 100;  //K_Means中k的数量

using namespace std;

class CHistogram{
public:
	CHistogram():cnImageNumber(0),cnFeatrueNumber(0){};
	void ReadFeaturesVector();
	void FormHistogram();
	void WriteHistogramToFile();
private:

	int cnImageNumber;                        //全部图片的数量
	int cnFeatrueNumber;                      //全部特征的数量

	vector<int> everyImageFeatureNumber;          //存储每幅图片的特征点数目
	//double (*featureArray)[cnFeatureDimension]; //用来把所有特征存储到此数组
	vector<vector<double>> featureVector;
 	//int (*historgram)[cnClusterNumber];         //用来存储生成的直方图
	vector<vector<int>> histogramVector;
};

#endif

 

CHistogram.cpp

#include "CHistogram.h"

#include <string>
#include <iostream>
#include <fstream>

using namespace std;

void CHistogram::ReadFeaturesVector()
{
 string filePath("F:\\Documents\\cv\\source code\\myCode\\MySIFT\\");
 string fileName;//("myImage.sift");
 cout << "Please input the file to read: " << endl;
 cin >> fileName;
 ifstream infile((filePath+fileName).c_str());

 if(!infile)
 {
  cerr << "Open the file failed!" << endl;
 }
 infile >> cnImageNumber;
 int imageFeatureNum;//表示每幅图像的特征数;
 
 for(int i = 0; i != cnImageNumber; ++i)
 {
  infile >> imageFeatureNum;
  everyImageFeatureNumber.push_back(imageFeatureNum);//统计此图片的特征数量
  cnFeatrueNumber += imageFeatureNum;//统计所有特征的数量,聚类时用到
  for(int j = 0; j != imageFeatureNum; ++j)
  {
   vector<double> tempVec(cnFeatureDimension);

   for(int k = 0; k < cnFeatureDimension; ++k)
   {
    infile >> tempVec[k];
   }
   featureVector.push_back(tempVec);
  }
 }
 //double (*featureArray)[cnFeatureDimension] = new double[cnFeatrueNumber][cnFeatureDimension];
 //把存储在vector中的特征向量复制到featureArray数组中
 //for(int i = 0; i < tempVec.size(); ++i)
 // for(int j = 0; j < cnFeatureDimension; ++j)
 //  featureArray[i][j] = tempVec[i][j];

}

void CHistogram::FormHistogram()
{
 //聚类中心矩阵
 CvMat *clusterCenters = cvCreateMat(cnClusterNumber, cnFeatureDimension, CV_32FC1);
 //所有特征矩阵
 CvMat featureMat;

 //必须是float才能进行运算!!!!!!!!!!!!!!!!妹的被坑了!!!!!
 float *tempDoubleArray = new float[cnFeatrueNumber * cnFeatureDimension];
 //ZeroMemory(tempDoubleArray, sizeof(double) * cnFeatrueNumber * cnFeatureDimension);
 for(int i = 0; i < cnFeatrueNumber; ++i) 
  for(int j = 0; j < cnFeatureDimension; ++j)
   tempDoubleArray[i*cnFeatureDimension+j] = featureVector[i][j];

 //初始化featureMat----------特别注意:第五个参数必须为一维数组!
 cvInitMatHeader(&featureMat, cnFeatrueNumber, cnFeatureDimension, CV_32FC1, tempDoubleArray);
 //输出整数向量:每个样本对应的类别标识,在 cnClusterNumber  内。
 CvMat *labels = cvCreateMat(cnFeatrueNumber, 1, CV_32SC1);
 //函数 cvKMeans2 执行 k-means 算法 搜索 cnClusterNumber 个类别的中心并对样本进行分类,输出 labels(i) 为样本 i 的类别标识。
 cvKMeans2(&featureMat, cnClusterNumber, labels, 
   cvTermCriteria( CV_TERMCRIT_EPS+CV_TERMCRIT_ITER, 1, 0.1)); 

 int (*historgram)[cnClusterNumber] = new int[cnImageNumber][cnClusterNumber];
 ZeroMemory(historgram, sizeof(int) * cnImageNumber * cnClusterNumber);
 
 int index = 0;//用于访问labels的游标
 for(int i = 0; i < cnImageNumber; ++i)
 {
  for(int j = 0; j < everyImageFeatureNumber[i]; ++j)
  {
   int *data_ = labels->data.i;
   int temp = data_[index++];
   //int temp = (labels->data.i)[index++];
   ++historgram[i][temp];
  }
 }
 for(int i = 0; i  < cnImageNumber; ++i)
 {
  vector<int> tempIntVector;
  for(int j = 0; j < cnClusterNumber; j++)
  {
   tempIntVector.push_back(historgram[i][j]);
  }
  histogramVector.push_back(tempIntVector);
 }
 delete[] tempDoubleArray;
 delete[] historgram;
 cvReleaseMat(&labels);
 cvReleaseMat(&clusterCenters);
}

void CHistogram::WriteHistogramToFile()
{
 string fileName;
 cout << "Please input the file to write: " << endl;
 cin >> fileName;
 ofstream outfile(fileName.c_str());

 outfile << cnImageNumber << endl;
 for(int i = 0; i < cnImageNumber; ++i)
  for(int j = 0; j < cnClusterNumber; j++)
   outfile  << histogramVector[i][j] << endl;

}

 

抱歉!评论已关闭.