1. PCA 降维
void DataPrepareUtil::PCA_Reduce(cv::Mat & input_train, cv::Mat & input_test, cv::Mat & output_train, cv::Mat & output_test, Mat & mean, Mat & eigenvectors)
{
cout << "start pca" << endl;
double t0 = (double)cvGetTickCount();
PCA pca(input_train, Mat(), PCA::DATA_AS_ROW, 1700);
cout << "end pca" << endl;
double t1 = (double)cvGetTickCount();
cout << "cost time is: " << ((t1 - t0) / ((double)cvGetTickFrequency() * 1000 * 1000)) << "s" << endl;
//cout << pca.eigenvalues << endl;
//cout << pca.eigenvectors << endl;
output_train = pca.project(input_train);
output_test = pca.project(input_test);
cout << " point size :" << output_train.rows << " " << output_train.cols << endl;
//把 pca.mean 和 engenvectors写入文件,给测试样本使用
//imwrite("D:\\face\\face_img_96\\img\\feature_sift\\pca\\mean.jpg", pca.mean);
//imwrite("D:\\face\\face_img_96\\img\\feature_sift\\pca\\engv.jpg", pca.eigenvectors);
mean = pca.mean;
eigenvectors = pca.eigenvectors;
}
2.libsvm的使用
svm_parameter param;
void init_param()
{
param.svm_type = C_SVC;
param.kernel_type = RBF;
param.degree = 3;
param.gamma = 0.1;
param.coef0 = 0;
param.nu = 0.5;
param.cache_size = 1000;
param.C = 20;
param.eps = 1e-6;
param.shrinking = 1;
param.probability = 0;
param.nr_weight = 0;
param.weight_label = NULL;
param.weight = NULL;
}
void DataPrepare::libSVM_Train(cv::Mat & data, cv::Mat &label, string save_path)
{
init_param();
int rows = data.rows;
int cols = data.cols;
svm_problem prob;
prob.l = rows;
svm_node *x_space = new svm_node[(cols + 1)*prob.l];//样本特征存储空间
prob.x = new svm_node *[prob.l]; //每一个X指向一个样本
cout << "size :" << sizeof(x_space) << endl;
prob.y = new double[prob.l];
//libsvm train data prepare.
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols + 1; j++)
{
if (j == cols)
{
x_space[i*(cols + 1) + j].index = -1;
prob.x[i] = &x_space[i * (cols + 1)];
prob.y[i] = label.at<uchar>(i, 0);
break;
}
x_space[i*(cols + 1) + j].index = j + 1;
x_space[i*(cols + 1) + j].value = data.at<float>(i, j);
}
}
cout << "start train svm." << endl;
svm_model *model = svm_train(&prob, ¶m);
cout << "save model" << endl;
svm_save_model(save_path.c_str(), model);
cout << "done!" << endl;
delete[] x_space;
delete[] prob.x;
delete[] prob.y;
}
void DataPrepare::libSVM_Predict(std::string mode, cv::Mat & data, cv::Mat &label)
{
svm_model* model = svm_load_model(mode.c_str());
int test_cols = data.cols;
int test_rows = data.rows;
svm_node *test_space = new svm_node[test_cols + 1];
//svm_problem prob_test;
//libsvm test data prepare.
int error = 0;
double t0 = (double)cvGetTickCount();
for (int i = 0; i < test_rows; i++)
{
for (int j = 0; j < test_cols + 1; j++)
{
if (j == test_cols)
{
test_space[j].index = -1;
break;
}
test_space[j].index = j + 1;
test_space[j].value = data.at<float>(i, j);
}
int d = svm_predict(model, test_space);
if (d != label.at<int>(i, 0))
{
cout << "predict is :" << d << " really is :" << label.at<int>(i, 0) << endl;
error++;
}
}
double t1 = (double)cvGetTickCount();
cout << "average time is: " << ((t1 - t0) / ((double)cvGetTickFrequency() * 1000 * 1000))*1000.0 / test_rows << "ms" << endl;
cout << "acurcy is :" << (float)(test_rows - error) / test_rows << endl;
delete[] test_space;
}
3.adaboost 使用
void DataPrepare::adaboostTrain(cv::Mat & data, cv::Mat &label, std::string save_path)
{
Ptr<Boost> boost = Boost::create();
int i, j, k;
Ptr<Boost> model;
int class_count = 8;
int ntrain_samples = data.rows;
int var_count = data.cols;
Mat new_data(ntrain_samples*class_count, var_count + 1, CV_32F);
Mat new_responses(ntrain_samples*class_count, 1, CV_32S);
for (i = 0; i < ntrain_samples; i++)
{
const float* data_row = data.ptr<float>(i);
for (j = 0; j < class_count; j++)
{
float* new_data_row = (float*)new_data.ptr<float>(i*class_count + j);
memcpy(new_data_row, data_row, var_count * sizeof(data_row[0]));
new_data_row[var_count] = (float)j;
new_responses.at<int>(i*class_count + j, 0) = label.at<int>(i, 0) == j;
}
}
Mat var_type(1, var_count + 2, CV_8U);
var_type.setTo(Scalar::all(VAR_ORDERED));
var_type.at<uchar>(var_count) = var_type.at<uchar>(var_count + 1) = VAR_CATEGORICAL;
Ptr<TrainData> tdata = TrainData::create(new_data, ROW_SAMPLE, new_responses,
noArray(), noArray(), noArray(), var_type);
vector<double> priors(2);
priors[0] = 1;
priors[1] = class_count;
model = Boost::create();
model->setBoostType(Boost::GENTLE);
model->setWeakCount(100);
model->setWeightTrimRate(0.95);
model->setMaxDepth(5);
model->setUseSurrogates(false);
model->setPriors(Mat(priors));
double t0 = (double)cvGetTickCount();
cout << "start train .." << endl;
model->train(tdata);
double t1 = (double)cvGetTickCount();
cout << "train end . cost time is :" << ((t1 - t0) / ((double)cvGetTickFrequency() * 1000 * 1000)) / 60.0 << " minute" << endl;
model->save(save_path);
Mat temp_sample(1, var_count + 1, CV_32F);
float* tptr = temp_sample.ptr<float>();
// compute prediction error on train and test data
double train_hr = 0, test_hr = 0;
for (i = 0; i < ntrain_samples; i++)
{
int best_class = 0;
double max_sum = -DBL_MAX;
const float* ptr = data.ptr<float>(i);
for (k = 0; k < var_count; k++)
tptr[k] = ptr[k];
for (j = 0; j < class_count; j++)
{
tptr[var_count] = (float)j;
float s = model->predict(temp_sample, noArray(), StatModel::RAW_OUTPUT);
if (max_sum < s)
{
max_sum = s;
best_class = j;
}
}
double r = std::abs(best_class - label.at<int>(i)) < FLT_EPSILON ? 1 : 0;
if (i < ntrain_samples)
train_hr += r;
else
test_hr += r;
}
test_hr /= ntrain_samples - ntrain_samples;
train_hr = ntrain_samples > 0 ? train_hr / ntrain_samples : 1.;
printf("Recognition rate: train = %.1f%%, test = %.1f%%\n",
train_hr*100., test_hr*100.);
cout << "Number of trees: " << model->getRoots().size() << endl;
}
void DataPrepare::adaboostPredict(std::string mode, cv::Mat & data, cv::Mat &label)
{
Ptr<Boost> model = Algorithm::load<Boost>(mode);
int rows = data.rows;
int cols = data.cols;
int class_count = 8;
double t0 = (double)cvGetTickCount();
Mat temp_sample(1, cols + 1, CV_32F);
int i, j, k;
float* tptr = temp_sample.ptr<float>();
// compute prediction error on train and test data
double test_hr = 0;
for (i = 0; i < rows; i++)
{
int best_class = 0;
double max_sum = -DBL_MAX;
const float* ptr = data.ptr<float>(i);
for (k = 0; k < cols; k++)
tptr[k] = ptr[k];
for (j = 0; j < class_count; j++)
{
tptr[cols] = (float)j;
float s = model->predict(temp_sample, noArray(), StatModel::RAW_OUTPUT);
if (max_sum < s)
{
max_sum = s;
best_class = j;
}
}
double r = std::abs(best_class - label.at<int>(i)) < FLT_EPSILON ? 1 : 0;
test_hr += r;
}
test_hr = test_hr / rows;
//train_hr = ntrain_samples > 0 ? train_hr / ntrain_samples : 1.;
printf("Recognition rate:test = %.1f%%\n", test_hr*100.);
double t1 = (double)cvGetTickCount();
cout << "average cost time is: " << ((t1 - t0) / ((double)cvGetTickFrequency() * 1000 * 1000)) * 1000.0 / rows << "ms" << endl;
}
4.计算图像内部一个 四边形 包围的像素均值
double get_sobel_mean_with_landmark(cv::Mat img, vector<float> landmark) {
Mat edgeVertical, edgeHorizontal;
Sobel(img, edgeHorizontal, CV_8U, 0, 1, 3, 1, 0);
Sobel(img, edgeVertical, CV_8U, 1, 0, 3, 1, 0);
Point2f left_eye = Point2f(landmark[0], landmark[1]);
Point2f right_eye = Point2f(landmark[2], landmark[3]);
Point2f nose = Point2f(landmark[4], landmark[5]);
Point2f left_mouth = Point2f(landmark[6], landmark[7]);
Point2f right_mouth = Point2f(landmark[8], landmark[9]);
Point2f mid_eye = (left_eye + right_eye) / 2;
Point2f mid_mouth = (left_mouth + right_mouth) / 2;
Point2f mid_left = (left_eye + left_mouth) / 2;
Point2f mid_right = (right_eye + right_mouth) / 2;
float mid_width = mid_right.x - mid_left.x;
mid_left.x = mid_left.x - mid_width /4.0f;
mid_right.x = mid_right.x + mid_width / 4.0f;
float k1 = (mid_eye.y - mid_left.y) / (mid_eye.x - mid_left.x);
float k2 = (mid_eye.y - mid_right.y) / (mid_eye.x - mid_right.x);
float k3 = (mid_left.y - mid_mouth.y) / (mid_left.x - mid_mouth.x);
float k4 = (mid_right.y - mid_mouth.y) / (mid_right.x - mid_mouth.x);
float b1 = mid_eye.y - k1 * mid_eye.x;
float b2 = mid_eye.y - k2 * mid_eye.x;
float b3 = mid_mouth.y - k3 * mid_mouth.x;
float b4 = mid_mouth.y - k4 * mid_mouth.x;
int rows = img.rows;
int cols = img.cols;
float sum_pix = 0;
int count = 1;
for (size_t i = 0; i < rows; i++)
{
uchar * ptr = edgeHorizontal.ptr<uchar>(i);
uchar * ptr2 = edgeVertical.ptr<uchar>(i);
for (size_t j = 0; j < cols; j++)
{
if ((k1 * j + b1 < i) && (k2 * j + b2 < i) && (k3 * j + b3 > i) && (k4 * j + b4 > i)) {
count++;
sum_pix += ptr[j];
sum_pix += ptr2[j];
ptr[j] = 0;
ptr2[j] = 0;
}
}
}
cv::imshow("img_", edgeVertical);
return sum_pix / count;
}
5.黑白图像与彩色图像区分
float caculate_residual_pixel(cv::Mat face_img) {
//threadhold 30
int channels = face_img.channels();
int rows = face_img.rows;
int cols = face_img.cols;
cv::imshow("face_imgss", face_img);
if (channels == 3) {
int ele_cols = cols*channels;
float sum = 0;
for (size_t i = 0; i < rows; i++)
{
uchar * ptr = face_img.ptr<uchar>(i);
for (size_t j = 0; j < ele_cols; j += 3)
{
sum += abs(ptr[j] - ptr[j + 1]) + abs(ptr[j] - ptr[j + 2]) + abs(ptr[j + 1] - ptr[j + 2]);
}
}
return sum / (rows*cols);
}
return -1;
}
6.gama 矫正
Mat norm_0_255(const Mat& src) {
// Create and return normalized image:
Mat dst;
switch (src.channels()) {
case 1:
cv::normalize(src, dst, 0, 255, NORM_MINMAX, CV_8UC1);
break;
case 3:
cv::normalize(src, dst, 0, 255, NORM_MINMAX, CV_8UC3);
break;
default:
src.copyTo(dst);
break;
}
return dst;
}
void use_camera() {
cv::VideoCapture cap(0);
if (!cap.isOpened())
{
std::cout << "Unable to connect to camera" << std::endl;
return;
}
std::ostringstream outtext;
//main loop
cv::Mat temp,gray, temp2, temp3;
while (true)
{
// Grab a frame
cap >> temp;
cvtColor(temp, gray, CV_BGR2GRAY);
gray.convertTo(temp2, CV_32FC1);
float gamma = 1 / 2.2;
cv::pow(temp2, gamma, temp3);
cv::imshow("temp2", gray);
cv::imshow("temp3", norm_0_255(temp3));
unsigned char key = cv::waitKey(1);
if (key == 27)
{
break;
}
}
}
7.直方图均值化 显示
int channels = 0;
cv::MatND dstHist;
int histSize[] = { 256 }; //如果写成int histSize = 256;调用计算直方图的函数的时,该变量需写成&histSize
float midRanges[] = { 0, 256 };
const float *ranges[] = { midRanges };
calcHist(&infrare_frame(box), 1, &channels, Mat(), dstHist, 1, histSize, ranges, true, false);
//绘制直方图,首先先创建一个黑底的图像,为了可以显示彩色,所以该绘制图像是一个8位的3通道图像
Mat drawImage = Mat::zeros(Size(256, 256), CV_8UC3);
//任何一个图像的某个像素的总个数有可能会很多,甚至超出所定义的图像的尺寸,
//所以需要先对个数进行范围的限制,用minMaxLoc函数来得到计算直方图后的像素的最大个数
double g_dHistMaxValue;
minMaxLoc(dstHist, 0, &g_dHistMaxValue, 0, 0);
//将像素的个数整合到图像的最大范围内
for (int i = 0; i < 256; i++)
{
int value = cvRound(dstHist.at<float>(i) * 256 * 0.9 / g_dHistMaxValue);
line(drawImage, Point(i, drawImage.rows - 1), Point(i, drawImage.rows - 1 - value), Scalar(0, 0, 255));
}
imshow("hist", drawImage);