double cv::kmeans(
InputArray data
int k
InputOutputArray bestLabels //输出的所有样本的标签数组
TermCriteria criteria
int attempts //采样不同初始化标签的尝试次数
int flag // 中心点初始化方法,支持KMEANS_RANDOM_CENTERS//KMEANS_PP_CENTERS//KMEANS_USE_INITIAL_LABELS
OutputArray centers=noArray()
)
kmeans实现图像语义分割示例代码:
void MLoperatorsDemo::kmeans_segmentation_demo(Mat &image) {
Scalar colorTab[] = {
Scalar(0, 0, 255),
Scalar(0, 255, 0),
Scalar(255, 0, 0),
Scalar(0, 255, 255),
Scalar(255, 0, 255)
};
int width = image.cols;
int height = image.rows;
int dims = image.channels();
// 初始化定义
int sampleCount = width*height;
int clusterCount = 5;
Mat labels;
Mat centers;
// RGB 数据转换到样本数据
Mat sample_data = image.reshape(3, sampleCount);
Mat data;
sample_data.convertTo(data, CV_32F);
// 运行K-Means
TermCriteria criteria = TermCriteria(TermCriteria::EPS + TermCriteria::COUNT, 10, 0.1);
kmeans(data, clusterCount, labels, criteria, clusterCount, KMEANS_PP_CENTERS, centers);
// 显示图像分割结果
int index = 0;
Mat result = Mat::zeros(image.size(), image.type());
for (int row = 0; row < height; row++) {
for (int col = 0; col < width; col++) {
index = row*width + col;
int label = labels.at(index, 0);
result.at(row, col)[0] = colorTab[label][0];
result.at(row, col)[1] = colorTab[label][1];
result.at(row, col)[2] = colorTab[label][2];
}
}
imshow("KMeans图像分割", result);
}
KNN实现手写数字识别:
void MLoperatorsDemo::knn_digit_train(Mat &image) {
Mat gray;
cvtColor(image, gray, COLOR_BGR2GRAY);
// 分割为5000个cells
Mat images = Mat::zeros(5000, 400, CV_8UC1);
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;
for (int col = 0; col < 100; col++) {
int offsetx = col * 20;
Mat digit = Mat::zeros(Size(20, 20), CV_8UC1);
for (int sr = 0; sr < 20; sr++) {
for (int sc = 0; sc < 20; sc++) {
digit.at(sr, sc) = gray.at(sr + offsety, sc + offsetx);
}
}
Mat one_row = digit.reshape(1, 1);
roi.y = index;
one_row.copyTo(images(roi));
labels.at(index, 0) = label;
index++;
}
}
printf("load sample hand-writing data...\n");
// 转换为浮点数
images.convertTo(images, CV_32FC1);
labels.convertTo(labels, CV_32SC1);
printf("load sample hand-writing data...\n");
// 开始KNN训练
printf("Start to knn train...\n");
Ptr knn = ml::KNearest::create();
knn->setDefaultK(5);
knn->setIsClassifier(true);
Ptr tdata = ml::TrainData::create(images, ml::ROW_SAMPLE, labels);
knn->train(tdata);
knn->save("D:/vcworkspaces/knn_knowledge.yml");
printf("Finished KNN...\n");
}
void MLoperatorsDemo::knn_digit_test() {
// real test it
Mat t1 = imread(rootdir + "knn_01.png", IMREAD_GRAYSCALE);
Mat t2 = imread(rootdir + "knn_02.png", IMREAD_GRAYSCALE);
namedWindow("t1", WINDOW_FREERATIO);
namedWindow("t2", WINDOW_FREERATIO);
imshow("t1", t1);
imshow("t2", t2);
Mat m1, m2;
resize(t1, m1, Size(20, 20));
resize(t2, m2, Size(20, 20));
Mat testdata = Mat::zeros(2, 400, CV_8UC1);
Mat testlabels = Mat::zeros(2, 1, CV_32SC1);
Rect rect;
rect.x = 0;
rect.y = 0;
rect.height = 1;
rect.width = 400;
Mat one = m1.reshape(1, 1);
Mat two = m2.reshape(1, 1);
one.copyTo(testdata(rect));
rect.y = 1;
two.copyTo(testdata(rect));
testlabels.at(0, 0) = 1;
testlabels.at(1, 0) = 2;
testdata.convertTo(testdata, CV_32F);
// 加载KNN分类器
Ptr knn = Algorithm::load("D:/vcworkspaces/knn_knowledge.yml");
Mat result;
knn->findNearest(testdata, 5, result);
for (int i = 0; i< result.rows; i++) {
int predict = result.at(i, 0);
printf("knn t%d predict : %d, actual label :%d \n", (i + 1), predict, testlabels.at(i, 0));
}
}
void MLoperatorsDemo::get_hog_descriptor(Mat &image, vector &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))); //宽设置为64且图像的宽高比不变
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)); //图像resize之后对缺失部分进行灰度填充,所以hog.compute不能直接用gray(宽高比不对)
hog.compute(result, desc, Size(8, 8), Size(0, 0));
}
void MLoperatorsDemo::train_ele_watch(std::string positive_dir, std::string negative_dir) {
// 创建变量
Mat trainData = Mat::zeros(Size(3780, 26), CV_32FC1);
Mat labels = Mat::zeros(Size(1, 26), CV_32SC1);
vector images;
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 fv;
get_hog_descriptor(image, fv);
printf("image path : %s, feature data length: %d \n", images[i].c_str(), fv.size());
for (int j = 0; j < fv.size(); j++) {
trainData.at(i, j) = fv[j];
}
labels.at(i, 0) = 1;
}
images.clear();
glob(negative_dir, images);
for (int i = 0; i < images.size(); i++) {
Mat image = imread(images[i].c_str());
vector fv;
get_hog_descriptor(image, fv);
printf("image path : %s, feature data length: %d \n", images[i].c_str(), fv.size());
for (int j = 0; j < fv.size(); j++) {
trainData.at(i + pos_num, j) = fv[j];
}
labels.at(i + pos_num, 0) = -1;
}
// 训练SVM仪表分类器
printf("\n start SVM training... \n");
Ptr< ml::SVM > svm = ml::SVM::create();
svm->setKernel(ml::SVM::LINEAR);
svm->setC(2.0);
svm->setType(ml::SVM::C_SVC);
svm->train(trainData, ml::ROW_SAMPLE, labels);
clog << "...[done]" << endl;
// save xml
svm->save("D:/vcworkspaces/svm_hog_elec.yml");
}
void MLoperatorsDemo::hog_svm_detector_demo(Mat &image) {
// 创建HOG与加载SVM训练数据
HOGDescriptor hog;
Ptr svm = ml::SVM::load("D:/vcworkspaces/svm_hog_elec.yml");
Mat sv = svm->getSupportVectors();
Mat alpha, svidx;
double rho = svm->getDecisionFunction(0, alpha, svidx);
// 构建detector
vector svmDetector;
svmDetector.clear();
svmDetector.resize(sv.cols + 1);
for (int j = 0; j < sv.cols; j++) {//sv.cols=3780=fv.size
svmDetector[j] = -sv.at(0, j);
}
svmDetector[sv.cols] = (float)rho;
hog.setSVMDetector(svmDetector);
vector objects;
hog.detectMultiScale(image, objects, 0.1, Size(8, 8), Size(32, 32), 1.25);
for (int i = 0; i < objects.size(); i++) {
rectangle(image, objects[i], Scalar(0, 0, 255), 2, 8, 0);
}
namedWindow("SVM+HOG对象检测演示", WINDOW_FREERATIO);
imshow("SVM+HOG对象检测演示", image);
}