cpp
复制代码
#define _CRT_SECURE_NO_WARNINGS 1
#include<opencv2/opencv.hpp>
#include<iostream>
using namespace std;
using namespace cv;
void get_hog_descriptor(Mat& image, vector<float>& desc) {
HOGDescriptor hog;
int h = image.rows;
int w = image.cols;
float rate = 64.0 / w;
Mat img, gray;
resize(image, img, Size(64, int(rate * h)));
cvtColor(img, gray, COLOR_BGR2GRAY);
Mat result = Mat::zeros(Size(64, 128), CV_8UC1);
result = Scalar(127);
Rect roi;
roi.x = 0;
roi.width = 64;
roi.y = (128 - gray.rows) / 2;
roi.height = gray.rows;
gray.copyTo(result(roi));
hog.compute(result, desc, Size(8, 8), Size(0, 0));
// printf("desc len : %d \n", desc.size());
}
void svm_train(Mat& trainData, Mat& labels) {
using namespace cv::ml;
printf("\n start SVM training... \n");
Ptr<ml::SVM> svm =ml:: SVM::create();
svm->setC(2.67);//对离群点的容忍度,C越大,边界可能越小
svm->setType(SVM::C_SVC);
svm->setKernel(SVM::LINEAR);
svm->setGamma(5.383);//高斯核的大小,只对svm->setKernel() SVM::POLY,SVM::RBF,SVM::SIGMOID有效
svm->train(trainData, ROW_SAMPLE, labels);
clog << "....[Done]" << endl;
printf("end train...\n");
// save xml
svm->save("D:/images/train_data/elec_watch/hog_elec.xml");
}
int main(int argc, char** argv)
{
Mat img = imread("xxx.jpg");
//kmean
int dims = img.channels();
Mat sample_data = img.reshape(dims, img.cols * img.rows);//变形的通道数,行数
sample_data.convertTo(sample_data, CV_32F);
Mat labels, centerpoints;
int clustercount = 5;//分类数量
TermCriteria criteria = TermCriteria(TermCriteria::EPS + TermCriteria::COUNT, 10, 0.1);
kmeans(sample_data, clustercount, labels, criteria, clustercount, KMEANS_PP_CENTERS, centerpoints);
//显示结果
int index = 0;
Mat result = Mat::zeros(img.size(), img.type());
for (int row = 0; row < img.rows; row++)
{
for (int col = 0; col < img.cols; col++)
{
index = labels.at<int>(row * img.cols + col, 0);
result.at<Vec3b>(row, col) = Vec3b(index*40, 1, 1);
}
}
//KNN 图像分类,opencv有一个digits.png,有0-9手写数字共5000个,图像大小1000*2000,每个样本20*20
Mat gray;
cvtColor(img, gray, COLOR_BGR2GRAY);
//准备数据集
Mat datas = Mat::zeros(5000, 20 * 20, CV_8SC1);
Mat labels = Mat::zeros(5000, 1, CV_8UC1);
int index = 0;
Rect roi;
roi.x = 0;
roi.height = 1;
roi.width = 400;
for (int row = 0; row < 50; row++)
{
int label = row / 5;
int offsety = row * 20;
Mat digital = Mat::zeros(20, 20, CV_8SC1);
for (int col = 0; col < 100; col++)
{
int offsetx = col * 20;
digital = (gray.clone())(Rect(offsetx,offsety,20,20));
Mat one_row = digital.reshape(1, 1);
roi.y = index;
one_row.copyTo(datas(roi));
index++;
labels.at<int>(index, 0) = label;
}
}
datas.convertTo(datas, CV_32F);
labels.convertTo(labels, CV_32F);
//开始训练
Ptr<ml::KNearest>knn = ml::KNearest::create();
knn->setDefaultK(5);
knn->setIsClassifier(true);
Ptr<ml::TrainData>traindata = ml::TrainData::create(datas, ml::ROW_SAMPLE, labels);
knn->train(traindata);
knn->save("D://num.yml");
//加载KNN
Ptr<ml::KNearest>knn_test = Algorithm::load<ml::KNearest>("D://num.yml");
Mat test;
Mat result;
resize(test, test, Size(20, 20));
test.reshape(1, 1);
knn_test->findNearest(test, 5, result);
cout << "pridect:" << result.at<float>(0, 0);
//SVM
Mat trainData = Mat::zeros(Size(3780, 26), CV_32FC1);
Mat labels = Mat::zeros(Size(1, 26), CV_32SC1);
vector<string> images;
string positive_dir;//路径
glob(positive_dir, images);
int pos_num = images.size();
for (int i = 0; i < images.size(); i++) {
Mat image = imread(images[i].c_str());
vector<float> fv;
get_hog_descriptor(image, fv);
for (int j = 0; j < fv.size(); j++) {
trainData.at<float>(i, j) = fv[j];
}
labels.at<int>(i, 0) = 1;
}
images.clear();
string negative_dir;//路径
glob(negative_dir, images);
for (int i = 0; i < images.size(); i++) {
Mat image = imread(images[i].c_str());
vector<float> fv;
get_hog_descriptor(image, fv);
for (int j = 0; j < fv.size(); j++) {
trainData.at<float>(i + pos_num, j) = fv[j];
}
labels.at<int>(i + pos_num, 0) = -1;
}
// SVM train, and save model
svm_train(trainData, labels);
//加载模型
Ptr<ml::SVM> svm = ml::SVM::load("D:/images/train_data/elec_watch/hog_elec.xml");
// detect custom object
Mat test = imread("D:/images/train_data/elec_watch/test/scene_02.jpg");
resize(test, test, Size(0, 0), 0.2, 0.2);
imshow("input", test);
Rect winRect;
winRect.width = 64;
winRect.height = 128;
int sum_x = 0;
int sum_y = 0;
int count = 0;
// 开窗检测....
for (int row = 64; row < test.rows - 64; row += 4) {
for (int col = 32; col < test.cols - 32; col += 4) {
winRect.x = col - 32;
winRect.y = row - 64;
vector<float> fv;
Mat testwindows = (test.clone())(winRect);
get_hog_descriptor(testwindows, fv);
Mat one_row = Mat::zeros(Size(fv.size(), 1), CV_32FC1);
for (int i = 0; i < fv.size(); i++) {
one_row.at<float>(0, i) = fv[i];
}
float result = svm->predict(one_row);
if (result > 0) {
// rectangle(test, winRect, Scalar(0, 0, 255), 1, 8, 0);
count += 1;
sum_x += winRect.x;
sum_y += winRect.y;
}
}
}
// 显示box
winRect.x = sum_x / count;
winRect.y = sum_y / count;
rectangle(test, winRect, Scalar(255, 0, 0), 2, 8, 0);
imshow("object detection result", test);
imwrite("D:/case02.png", test);
waitKey(0);
return 0;
}