利用opencv3中的kmeans實現摳圖功能

kmeans算法主要用來實現自動聚類,是一種非監督的機器學習算法,使用非常廣泛。在opencv3.0中提供了這樣一個函數,直接調用就能實現自動聚類,非常方便。

函數原型:

C++: double kmeans(InputArray data, int K, InputOutputArray bestLabels, TermCriteria criteria, int attempts, int flags, OutputArray centers=noArray() )

有7個參數,分別表示:

data:  需要自動聚類的數據,一般是一個Mat。浮點型的矩陣,每行爲一個樣本。

k: 取成幾類,比較關鍵的一個參數。

bestLabels:  返回的類別標記,整型數字。

criteria: 算法結束的標準,獲取期望精度的迭代最大次數

attempts:  判斷某個樣本爲某個類的最少聚類次數,比如值爲3時,則某個樣本聚類3次都爲同一個類,則確定下來。

flags:  確定簇心的計算方式。有三個值可選:KMEANS_RANDOM_CENTERS 表示隨機初始化簇心。KMEANS_PP_CENTERS 表示用kmeans++算法來初始化簇心(沒用過),KMEANS_USE_INITIAL_LABELS 表示第一次聚類時用用戶給定的值初始化聚類,後面幾次的聚類,則自動確定簇心。

centers: 用來初始化簇心的。與前一個flags參數的選擇有關。如果選擇KMEANS_RANDOM_CENTERS隨機初始化簇心,則這個參數可省略。

示例圖片:

學過ps描圖的都知道,頭髮絲在摳圖中,是非常難的。這裏我們就用kmeans自動聚類來進行自動摳圖。

思路就是將圖片的每個像素點的三通道值作爲一個特徵,因此會得到一個n行3列的特徵矩陣data,然後用這個特徵矩陣進行kmeans

代碼:

複製代碼
#include "stdafx.h"
#include "opencv2\opencv.hpp"
#include <iostream>
using namespace std;
using namespace cv;
int main()
{
    const int MAX_CLUSTERS = 5;
    Vec3b colorTab[] =
    {
        Vec3b(0, 0, 255),
        Vec3b(0, 255, 0),
        Vec3b(255, 100, 100),
        Vec3b(255, 0, 255),
        Vec3b(0, 255, 255)
    };
    Mat data,labels;
    Mat pic = imread("d:/woman.png");
    for (int i = 0; i < pic.rows;i++)
    for (int j = 0; j < pic.cols; j++)
    {
        Vec3b point = pic.at<Vec3b>(i, j);
        Mat tmp = (Mat_<float>(1, 3) << point[0], point[1], point[2]);
        data.push_back(tmp);
    }

    //根據瀏覽圖片,確定k=3
    kmeans(data, 3, labels, TermCriteria(TermCriteria::EPS + TermCriteria::COUNT, 10, 1.0),
        3, KMEANS_RANDOM_CENTERS);

    int n = 0;
    //顯示聚類結果,不同的類別用不同的顏色顯示
    for (int i = 0; i < pic.rows; i++)
    for (int j = 0; j < pic.cols; j++)
    {
        int clusterIdx = labels.at<int>(n);
        pic.at<Vec3b>(i, j) = colorTab[clusterIdx];
        n++;
    }
    imshow("pic", pic);
    waitKey(0);
    
    return 0;
}
複製代碼

結果:

效果不是十分理想,畢竟是全自動的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章