使用OpenCV的kmeans實現影象分割
阿新 • • 發佈:2022-04-10
一、概述
案例:使用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; intdims = 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);
三、示例圖片