问题提出:
在实际的编程过程中,有时候单纯的让一个函数产生一个返回值已经不能满足实际的需要,但是又不能将函数执行两次,或者多次,返回不同的变量。这样就需要使函数同时返回多个变量,需要将返回值定义成类的形式,也就是说定义了一个类的对象,返回的就是一个对象,这样这个对象就可以包含多个变量了。例如:
首先在字符识别的头文件(OCR.h)中定义类:
class CharSegment{
public:
CharSegment();
CharSegment(Mat i, Rect p);
Mat img;
Rect pos;
CharSegment(string str,int y0,int y1,int y2,int height);
string Char_str;
int y0_pos;
int y1_pos;
int y2_pos;
int Char_height;
};
这个类中包含三种成员函数,2+4个成员变量(CharSegment(Mat i, Rect p)两个变量,CharSegment(string str,int y0,int y1,int y2,int height)4个变量;
在OCR.cpp文件中是成员函数的实现,如下:
CharSegment::CharSegment(){}
CharSegment::CharSegment(Mat i, Rect p)
{
img=i;
pos=p;
}
CharSegment::CharSegment(string str,int y0,int y1,int y2,int height)
{
Char_str=str;
y0_pos=y0;
y1_pos=y1;
y2_pos=y2;
Char_height=height;
}:
由类名定义的函数的声明:
class OCR{
public:
bool DEBUGTEST;
bool saveSegments;
string filename;
static const int numCharacters;
static const char strCharacters[];
OCR(string trainFile);
OCR();
CharSegment run(Plate *input);//由类名定义的函数的声明
int charSize;
Mat preprocessChar(Mat in);
int classify(Mat f);
void train(Mat trainData, Mat trainClasses, int nlayers);
int classifyKnn(Mat f);
void trainKnn(Mat trainSamples, Mat trainClasses, int k);
Mat features(Mat input, int size);
private:
bool trained;
vector<CharSegment> segment(Plate input);
Mat Preprocess(Mat in, int newSize);
Mat getVisualHistogram(Mat *hist, int type);
void drawVisualFeatures(Mat character, Mat hhist, Mat vhist, Mat lowData);
Mat ProjectedHistogram(Mat img, int t);
bool verifySizes(Mat r);
CvANN_MLP ann;
CvKNearest knnClassifier;
int K;
};
函数的具体实现:
CharSegment OCR::run(Plate *input) //注意函数类型
{
vector<int>xpositions;
vector<int>orderIndex;
CharSegment output; //定义函数返回值
//Segment chars of plate
vector<CharSegment> segments=segment(*input);
for(int i=0; i<segments.size(); i++){
//Preprocess each char for all images have same sizes
Mat ch=preprocessChar(segments[i].img);
if(saveSegments){
stringstream ss(stringstream::in | stringstream::out);
ss << "tmpChars/" << filename << "_" << i << ".jpg";
imwrite(ss.str(),ch);
}
//For each segment Extract Features
Mat f=features(ch,15);
//For each segment feature Classify
int character=classify(f);
input->chars.push_back(strCharacters[character]);
input->charsPos.push_back(segments[i].pos);
xpositions.push_back(segments[i].pos.x);
orderIndex.push_back(i);
}
string str="";
float min=xpositions[0];
int minIdx=0;
for(int i=0; i<4; i++)
{
min=xpositions[i];
minIdx=i;
for(int j=i; j<4; j++)
{
if(xpositions[j]<min)
{
min=xpositions[j];
minIdx=j;
}
}
int aux_i=orderIndex[i];
int aux_min=orderIndex[minIdx];
orderIndex[i]=aux_min;
orderIndex[minIdx]=aux_i;
float aux_xi=xpositions[i];
float aux_xmin=xpositions[minIdx];
xpositions[i]=aux_xmin;
xpositions[minIdx]=aux_xi;
}
//第二行
for(int i=4; i<8; i++)
{
min=xpositions[i];
minIdx=i;
for(int j=i; j<8; j++)
{
if(xpositions[j]<min)
{
min=xpositions[j];
minIdx=j;
}
}
int aux_i=orderIndex[i];
int aux_min=orderIndex[minIdx];
orderIndex[i]=aux_min;
orderIndex[minIdx]=aux_i;
float aux_xi=xpositions[i];
float aux_xmin=xpositions[minIdx];
xpositions[i]=aux_xmin;
xpositions[minIdx]=aux_xi;
}
//第一行
for(int i=8; i<12; i++)
{
min=xpositions[i];
minIdx=i;
for(int j=i; j<12; j++)
{
if(xpositions[j]<min)
{
min=xpositions[j];
minIdx=j;
}
}
int aux_i=orderIndex[i];
int aux_min=orderIndex[minIdx];
orderIndex[i]=aux_min;
orderIndex[minIdx]=aux_i;
float aux_xi=xpositions[i];
float aux_xmin=xpositions[minIdx];
xpositions[i]=aux_xmin;
xpositions[minIdx]=aux_xi;
}
for(int j=0;j<4;j++)
{
char temp[4];
temp[j]=orderIndex[j];
orderIndex[j]=orderIndex[j+8];
orderIndex[j+8]=temp[j];
}
for (int i = 0; i <12;i++)
{
str=str+input->chars[orderIndex[i]];
if((i==2)||(i==6)||(i==10))
{
str=str+".";
}
if((i==3)||(i==7)||(i==11))
{
str=str+"\r\n";
}
}
int y0_mean=((segments[0].pos.y+segments[0].pos.height)+(segments[1].pos.y+segments[1].pos.height)+ (segments[2].pos.y+segments[2].pos.height)+(segments[3].pos.y+segments[3].pos.height))/4;
int y1_mean=((segments[4].pos.y+segments[4].pos.height)+(segments[5].pos.y+segments[5].pos.height)+ (segments[6].pos.y+segments[6].pos.height)+(segments[7].pos.y+segments[7].pos.height))/4;
int y2_mean=((segments[8].pos.y+segments[8].pos.height)+(segments[9].pos.y+segments[9].pos.height)+ (segments[10].pos.y+segments[10].pos.height)+(segments[11].pos.y+segments[11].pos.height))/4;
int height_mean=(segments[0].pos.height+segments[4].pos.height+segments[8].pos.height)/3;
output=CharSegment(str,y0_mean,y1_mean,y2_mean,height_mean);
return output;//input->str();
}
函数的调用:
CharSegment plateNumber=ocr.run(&plate);
函数成员变量的使用:
CString CSstr=_T("");
CSstr.Format(_T("%s"),plateNumber.Char_str.c_str());
ResultBox->SetWindowText(CSstr);