1. 程式人生 > 其它 >使用OpenCV的kmeans實現影象分割

使用OpenCV的kmeans實現影象分割

一、概述

  案例:使用kmeans演算法實現影象分割

 
kmeans演算法引數介紹:
 kmeans( InputArray data, int K, InputOutputArray bestLabels,
                            TermCriteria criteria, int attempts,
                            int flags, OutputArray centers = noArray() )

data:輸入資料,此輸入資料必須是CV_32F型別的
k:要分成幾個類別
bestLabels:分類的標籤(分成k類,那麼就有k種類型的標籤)
criteria:表示kmeans分割的停止條件
attempts:判斷某個樣本屬於某個類別的最少聚類次數。例如:3代表此列別如果聚類了3此就說明它屬於這個類別
flags:中心初始化方法
    有三個值可選:
        1.KMEANS_RANDOM_CENTERS 表示隨機初始化簇心
        2.KMEANS_PP_CENTERS 表示用kmeans++演算法來初始化簇心 
        3.KMEANS_USE_INITIAL_LABELS 表示第一次聚類時用使用者給定的值初始化聚類,後面幾次的聚類,則自動確定簇心。
centers:表示最終分割後每個聚類的中心點位置

  

  使用kmeans實現影象畫素分割的步驟:

    1.載入輸入影象

    2.得到影象的寬、高、通道數

    3.建立一個CV_32F的的Mat用於存放樣本資料(由於kmeans方法的輸入資料必須是CV_32F型別的,而直接載入的影象資料是CV_8U型別的所以要經過一層轉換)

    4.將輸入影象的RGB資料轉換為 CV_32F的資料

    5.使用kmeans演算法開始給樣本數量分類

    6.顯示影象分割後的結果

  

二、程式碼樣例

//輸入影象
    Mat src = imread(filePath);
    if(src.empty()){
        qDebug()
<<"圖片為空"; return; } imshow("src",src); //定義隨機顏色 Scalar colorTab[] = { Scalar(0,0,255), Scalar(0,255,0), Scalar(255,0,0), Scalar(0,255,255), Scalar(255,0,255) }; //獲取原圖屬性,寬高及維度 int width = src.cols; int height = src.rows; int
dims = src.channels();//通道數 //初始化取樣數量 int sampleCount= width*height; int clusterCount = 4;//四分類 Mat points(sampleCount,dims,CV_32F,Scalar(10)); Mat labels; Mat centers(clusterCount,1,points.type()); //將RGB圖片資料轉換為樣本資料,因為kmeans要求輸入的樣本資料為CV_32F型別的 int index = 0; for(int row = 0;row<height;row++){ for(int col = 0;col<width;col++){ index = row*width+col; Vec3b bgr = src.at<Vec3b>(row,col); points.at<float>(index,0) = static_cast<int>(bgr[0]); points.at<float>(index,1) = static_cast<int>(bgr[1]); points.at<float>(index,2) = static_cast<int>(bgr[2]); } } //使用KMeans分類 TermCriteria criteria = TermCriteria(TermCriteria::EPS+TermCriteria::COUNT,10,0.1); kmeans(points,clusterCount,labels,criteria,3,KMEANS_PP_CENTERS,centers); //顯示影象分割後的結果 Mat result = Mat::zeros(src.size(),src.type()); for(int row=0;row<height;row++){ for(int col=0;col<width;col++){ index = row*width+col; int label = labels.at<int>(index,0); result.at<Vec3b>(row,col)[0] = colorTab[label][0]; result.at<Vec3b>(row,col)[1] = colorTab[label][1]; result.at<Vec3b>(row,col)[2] = colorTab[label][2]; } } imshow("result",result);

 

三、示例圖片