OpenCV——手势识别
使用ANN神经网络训练数据后进行手势识别。
#include "header.h" int main() { const int sample_num = 10; //训练每类图片数量 const int class_num = 3; //训练类数3:石头剪刀布 const int image_cols = 30; const int image_rows = 30; string Name, Path; float trainingData[class_num * sample_num][image_cols * image_rows] = { { 0 } }; //每一行一个训练样本 float labels[class_num * sample_num][class_num] = { { 0 } }; //训练样本标签 cout << "training Data.........\n"; for (int i = 0; i < class_num; i++){ int j = 0; Path = getstring(i + 1) + "/" + "*.*"; HANDLE hFile; LPCTSTR lp = StringToWchar(Path); WIN32_FIND_DATA pNextInfo; hFile = FindFirstFile(lp, &pNextInfo); if (hFile == INVALID_HANDLE_VALUE){ cout << "failed" << endl; exit(-1);//搜索失败 } cout << "folder name:" << i + 1 << endl; do{ //必须加这句,不然会加载.和..的文件而加载不了图片, if (pNextInfo.cFileName[0] == '.')continue; cout << "file name" << WcharToChar(pNextInfo.cFileName) << endl; Mat srcImage = imread(getstring(i+1) + "/" + WcharToChar(pNextInfo.cFileName), CV_LOAD_IMAGE_GRAYSCALE); Mat trainImage; //if (!srcImage.empty())cout << " done \n"; //处理样本图像 resize(srcImage, trainImage, Size(image_cols, image_rows), (0, 0), (0, 0), CV_INTER_AREA); Canny(trainImage, trainImage, 150, 100, 3, false); for (int k = 0; k < image_rows * image_cols; k++){ //cout << "矩阵 k-- " << k << " j--" << j << " i--" << i << endl; trainingData[i*sample_num + j][k] = (float)trainImage.data[k]; } j++; } while (FindNextFile(hFile, &pNextInfo)); } // 训练好的矩阵 Mat DataMat(class_num*sample_num, image_rows*image_cols, CV_32FC1, trainingData); cout << "DataMat done~" << endl; // 初始化标签 // 0-石头 1-剪刀 2-布 for (int i = 0; i < class_num ; i++){ for (int j = 0; j < sample_num; j++){ for (int k = 0; k < class_num; k++){ if (k == i)labels[i*sample_num + j][k] = 1; else labels[i*sample_num + j][k] = 0; } } } // 标签矩阵 Mat labelsMat(class_num*sample_num, class_num, CV_32FC1, labels); cout << "labelsMat done~" << endl; //训练代码 CvANN_MLP bp; CvANN_MLP_TrainParams params; params.train_method = CvANN_MLP_TrainParams::BACKPROP; params.bp_dw_scale = 0.001; params.bp_moment_scale = 0.1; //cvTermCriteria 迭代终止规则 params.term_crit = cvTermCriteria(CV_TERMCRIT_ITER | CV_TERMCRIT_EPS, 10000, 0.0001); //设置网络层数 Mat layerSizes = (Mat_<int>(1, 4) << image_rows*image_cols, int(image_rows*image_cols / 2), int(image_rows*image_cols / 2), class_num); bp.create(layerSizes, CvANN_MLP::SIGMOID_SYM, 1.0, 1.0); cout << "training...." << endl; bp.train(DataMat, labelsMat, Mat(), Mat(), params); bp.save("detect_gesture.xml"); cout << "done" << endl; //测试神经网络 cout << "testing...." << endl; Mat test = imread("test.jpg"); Mat temp; resize(test, temp, Size(image_cols, image_rows), (0, 0), (0, 0), CV_INTER_AREA); Canny(temp, temp, 150, 100, 3, false); Mat_<float>sample(1, image_rows*image_cols); for (int i = 0; i<image_rows*image_cols; ++i){ sample.at<float>(0, i) = (float)temp.data[i]; } Mat result; bp.predict(sample, result); float* p = result.ptr<float>(0); float max = -1, min = 0; int index = 0; for (int i = 0; i<class_num; i++) { cout << (float)(*(p + i)) << " "; if (i == class_num - 1) cout << endl; if ((float)(*(p + i))>max) { min = max; max = (float)(*(p + i)); index = i; } else { if (min < (float)(*(p + i))) min = (float)(*(p + i)); } } cout << "Your choice :" << choice[index] << endl << "识别率:" << (((max - min) * 100) > 100 ? 100 : ((max - min) * 100)) << endl; //石头剪刀布——游戏开局~ int computer = random(3); cout << "computer's choice :" << choice[computer] << endl; if (computer == index) cout << "A Draw -_- " << endl << endl; else if ((computer < index && (index - computer == 1)) || (computer == 2 && index == 0)){ cout << "You Lose T_T " << endl << endl; } else cout << "You Win o * ̄▽ ̄* " << endl << endl; system("pause"); waitKey(100); return 0; }
运行一次后,不用每次都训练数据,直接加载第一次保存的 "detect_gesture.xml"即可
CvANN_MLP bp; CvANN_MLP_TrainParams params; bp.load("detect_gesture.xml");
PS:
//CvTermCriteria() //迭代算法的终止准则 #define CV_TERMCRIT_ITER 1 #define CV_TERMCRIT_NUMBER CV_TERMCRIT_ITER #define CV_TERMCRIT_EPS 2 typedef struct CvTermCriteria { int type; // CV_TERMCRIT_ITER 和CV_TERMCRIT_EPS二值之一,或者二者的组合 int max_iter; // 最大迭代次数 double epsilon; // 结果的精确性 } CvTermCriteria; // 构造函数 inline CvTermCriteria cvTermCriteria( int type, int max_iter, double epsilon ); // 在满足max_iter和epsilon的条件下检查终止准则并将其转换使得type=CV_TERMCRIT_ITER+CV_TERMCRIT_EPS CvTermCriteria cvCheckTermCriteria( CvTermCriteria criteria, double default_eps, int default_max_iters );