opencv批處理提取圖像的特征


_________________________________________________________________________________________________________________________________

批處理(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;
}
_______________________________________________________________________________________________________________________________

上面已經批處理提取了圖像的特征,那么通常我們再做目標識別、檢測時。會給訓練數據集,准備類標簽。以下,繼續對上述程序進行拓展。





免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM