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

opencv批处理提取图像的特征

2018年04月11日 ⁄ 综合 ⁄ 共 5232字 ⁄ 字号 评论关闭

_________________________________________________________________________________________________________________________________

批处理(dir/a/s/b)

例:某目录下有a、b、c、d、e、f、g、h、j的图片和一个文件夹JN,里边包含一张图片john.jpg


我们在该目录下的命令行中 输入:dir/b

b:只显示当前目录下文件名及文件夹名

a-d:只是显示该目录下的文件名(没有了文件夹的名)

我们在该目录下的命令行中 输入:dir/a-d/b

S:显示该目录下的文件名和文件夹名,及子目录下的文件名,并显示这些文件的绝对路径

我们在该目录下的命令行中 输入:dir/s/b


我们在该目录下的命令行中 输入:dir/s/a-d/b(由于a-d的作用,文件夹JN没有显示出来)

我们在该目录下的命令行中 输入:dir/s/a-d/b>F:\目录.txt

就会在F盘生成一个文件名为 目录 的.txt文件,该文件包含上面的命令行打出的内容。


—————————————————————————————————————————————————————

第二步:既然已经生成上述文件 目录.txt,然会我们写程序读取这个 目录.txt 即可。

<span style="font-family:Microsoft YaHei;font-size:14px;"><span style="font-family:Microsoft YaHei;font-size:14px;"><span style="font-family:Microsoft YaHei;font-size:14px;">#include<iostream>
#include<fstream>
#include<string>
using namespace std;
int main(int argc,char* argv[])
{
	if(argc !=2)
	{
		cerr << "Wrong Argument !" <<endl;
		return -1;
	}
	//定义文件流,只能读取
	ifstream inPutFile(argv[1],ios::in);
	if(! inPutFile)
	{
		cerr << "File Open Erro !" <<endl;
		return -1;
	}
	//读取文件流中的每一行,并赋值给fileName,并在命令行中打印
	string fileName ;
	/* 
	测试读取文件中的每一行
	*/
	//行数
	int number = 0;
	while (getline(inPutFile,fileName))
	{
		number ++;
		cout<<"第"<< number << "行"<< fileName <<endl;
	}
    //注意一定要记得关闭文件流
	inPutFile.close();
	return 0;
}</span></span></span>

我们编译一下:


我们看一下输出结果:

好的,这样,说明我们读到了每一行。

————————————————————————————————————————————————————

第三步:配置Opencv,然后,读取显示每一幅图片

<span style="font-family:Microsoft YaHei;font-size:14px;"><span style="font-family:Microsoft YaHei;font-size:14px;">#include<iostream>
#include<fstream>
#include<string>
using namespace std;
#include<opencv2\imgproc\imgproc.hpp>
#include<opencv2\core\core.hpp>
#include<opencv2\highgui\highgui.hpp>
using namespace cv;
int main(int argc,char* argv[])
{
	if(argc !=2)
	{
		cerr << "Wrong Argument !" <<endl;
		return -1;
	}
	//定义文件流,只能读取
	ifstream inPutFile(argv[1],ios::in);
	if(! inPutFile)
	{
		cerr << "File Open Erro !" <<endl;
		return -1;
	}
	//读取文件流中的每一行,并赋值给fileName,读取每一幅图像并显示
	string fileName ;
	Mat image;
	while (getline(inPutFile,fileName))
	{
		
		image = imread(fileName,1);
		namedWindow(fileName,1);
		imshow(fileName,image);
	}
	waitKey(0);
    //注意一定要记得关闭文件流
	inPutFile.close();
	return 0;
}</span></span>


结果:

我们看到我们已经成功把每一幅图像读入到内存中,这样我们就可以求每一幅图像的特征。

—————————————————————————————————————————————————————

第四步:我们计算每一幅图像的直方图特征(当然opencv中sift、surf、densesift等,因为我这里的图片大小不一样,所以我用直方图的特征,使得特征向量的长度一样)

<span style="font-family:Microsoft YaHei;font-size:14px;">#include<iostream>
#include<fstream>
#include<string>
using namespace std;

#include<opencv2\imgproc\imgproc.hpp>
#include<opencv2\core\core.hpp>
#include<opencv2\highgui\highgui.hpp>
using namespace cv;

//计算二维直方图特征
Mat hist2d(const Mat& src);

int main(int argc,char* argv[])
{
	if(argc !=2)
	{
		cerr << "Wrong Argument !" <<endl;
		return -1;
	}
	//定义文件流,只能读取
	ifstream inPutFile(argv[1],ios::in);
	if(! inPutFile)
	{
		cerr << "File Open Erro !" <<endl;
		return -1;
	}
	//读取文件流中的每一行,并赋值给fileName,读取每一幅图像并显示
	string fileName ;
	Mat image;
	Mat featureHist;
	Mat featureHists;
	while (getline(inPutFile,fileName))
	{
		
		image = imread(fileName,1);
		//计算二维直方图特征
		featureHist = hist2d(image);
		//按行存储每一幅图像的二维直方图特征
		featureHists.push_back(featureHist);
	}
    //注意一定要记得关闭文件流
	inPutFile.close();
	return 0;
}

Mat hist2d(const Mat& src)
{
	Mat hsv;

	//颜色空间的转换 BGR2HSV
	cvtColor(src,hsv,CV_BGR2HSV);

	//把H通道分为30个bin,把S通道分为32bin
	int hbins = 30;
	int sbins = 32;
	int histSize[] = { hbins , sbins};

	//H的取值范围 0-179
	float hranges[]= {0,180};
	//S的取值范围 0-255
	float sranges [] ={0,256};
	const float* ranges [] ={hranges,sranges};

	Mat hist2D,histRow,histRowDst;
	//我们根据图像的第一通道和第二通道,计算二维直方图,而且输出的hist2D为32F
	int channels [] ={0,1};
	calcHist(&hsv,1,channels,Mat(),hist2D,2,histSize,ranges,true,false);
	//把直方图特征按一行来存储
	histRow=hist2D.reshape(1,1);

	//把直方图归一化
	normalize(histRow,histRowDst,1,0,NORM_L1);

	return histRowDst;
}</span>

这样就把所有的图像的二维直方图特征按行存储在featureHists中。当然可以把二维直方图特征换成自己想要用的任意特征。

—————————————————————————————————————————————————————

第五步:

我们所有图像的颜色直方图存储到.xml文件中,

#include<iostream>
#include<fstream>
#include<string>
using namespace std;

#include<opencv2\imgproc\imgproc.hpp>
#include<opencv2\core\core.hpp>
#include<opencv2\highgui\highgui.hpp>
using namespace cv;

//计算二维直方图特征
Mat hist2d(const Mat& src);

int main(int argc,char* argv[])
{
	if(argc !=2)
	{
		cerr << "Wrong Argument !" <<endl;
		return -1;
	}
	//定义文件流,只能读取
	ifstream inPutFile(argv[1],ios::in);
	if(! inPutFile)
	{
		cerr << "File Open Erro !" <<endl;
		return -1;
	}
	//读取文件流中的每一行,并赋值给fileName,读取每一幅图像并显示
	string fileName ;
	Mat image;
	Mat featureHist;
	Mat featureHists;
	while (getline(inPutFile,fileName))
	{
		
		image = imread(fileName,1);
		//计算二维直方图特征
		featureHist = hist2d(image);
		//按行存储每一幅图像的二维直方图特征
		featureHists.push_back(featureHist);
	}
    //注意一定要记得关闭文件流
	inPutFile.close();

	/*第五步,把图像特征保存到.xml文件中*/
	FileStorage fs("C:\\Users\\zhaoyuan001\\Desktop\\test\\dirtest\\x64\\Debug\\da.xml",FileStorage::WRITE);
	fs<<"featureHists"<<featureHists;
	fs.release();
	
	return 0;
}

Mat hist2d(const Mat& src)
{
	Mat hsv;

	//颜色空间的转换 BGR2HSV
	cvtColor(src,hsv,CV_BGR2HSV);

	//把H通道分为30个bin,把S通道分为32bin
	int hbins = 30;
	int sbins = 32;
	int histSize[] = { hbins , sbins};

	//H的取值范围 0-179
	float hranges[]= {0,180};
	//S的取值范围 0-255
	float sranges [] ={0,256};
	const float* ranges [] ={hranges,sranges};

	Mat hist2D,histRow,histRowDst;
	//我们根据图像的第一通道和第二通道,计算二维直方图,而且输出的hist2D为32F
	int channels [] ={0,1};
	calcHist(&hsv,1,channels,Mat(),hist2D,2,histSize,ranges,true,false);
	//把直方图特征按一行来存储
	histRow=hist2D.reshape(1,1);

	//把直方图归一化
	normalize(histRow,histRowDst,1,0,NORM_L1);

	return histRowDst;
}

_______________________________________________________________________________________________________________________________

上面已经批处理提取了图像的特征,那么通常我们再做目标识别、检测时,会给训练数据集,准备类标签,下面,继续对上述程序进行拓展。




抱歉!评论已关闭.