摘要:
SLIC:simple linear iterative clustering,簡(jiǎn)單的線性迭代聚類,它使用k-means聚類來(lái)生成超像素,實(shí)現(xiàn)起來(lái)簡(jiǎn)單悼粮,運(yùn)行效率還比較高掀淘,超像素對(duì)邊界的保持效果也比較好,具體的與其他方法的對(duì)比結(jié)果在下方論文中有詳細(xì)記錄耘纱。
論文地址:https://infoscience.epfl.ch/record/177415/files/Superpixel_PAMI2011-2.pdf
1.原理
SLIC本質(zhì)上說(shuō)只需要一個(gè)聚類數(shù)k敬肚,這個(gè)聚類數(shù)k也就是超像素的個(gè)數(shù),希望把圖片分割成多少個(gè)超像素就設(shè)多少個(gè)聚類中心束析,在初始化時(shí)把聚類中心等間隔的放到圖像上艳馒,設(shè)圖像像素?cái)?shù)為N,則在每個(gè)邊長(zhǎng)為的方格內(nèi)放置一個(gè)初始聚類中心员寇, 為了避免把噪聲像素和邊緣當(dāng)作聚類中心弄慰,會(huì)把該中心移動(dòng)到周圍3*3鄰域內(nèi)梯度最小的地方。
在用k-means做聚類時(shí)蝶锋,采用的特征是Lab顏色空間的三個(gè)值加上坐標(biāo)x陆爽,y,一共5個(gè)維度扳缕,,另外與常規(guī)的k均值不同的地方是慌闭,這里計(jì)算距離時(shí)只考慮聚類中心周圍
的鄰域别威,因此計(jì)算量和一般的k均值聚類相比要小很多。搜索空間對(duì)比如下圖驴剔,
聚類后計(jì)算每一類的平均特征省古,并把聚類中心的特征更新為平均特征。如果迭代超過(guò)10次或者前后兩次聚類的差小于閾值則結(jié)束仔拟,否則繼續(xù)聚類衫樊,更新聚類中心........。算法流程如下:
2. 實(shí)現(xiàn)
2.1 初始化聚類中心
原文中按聚類數(shù)k來(lái)等間隔地初始化聚類中心利花,假設(shè)樣本總數(shù)為N科侈,聚類數(shù)為k,則每隔個(gè)樣本放置一個(gè)聚類中心炒事。在圖片上等間隔地放置k個(gè)初始聚類中心臀栈,也就是把圖片等分成邊長(zhǎng)為
的格子,在格子的固定位置放置初始聚類中心挠乳。另外為了避免初始的聚類中心落在物體邊緣上权薯,還要對(duì)每一個(gè)聚類中心都進(jìn)行一下微調(diào),具體就是計(jì)算初始聚類中心點(diǎn)周圍鄰域的梯度睡扬,把中心點(diǎn)移到梯度最小的點(diǎn)上盟蚣。
這里實(shí)現(xiàn)的時(shí)候以初始超像素的邊長(zhǎng)len作為參數(shù)會(huì)比較直觀,可以很簡(jiǎn)單的控制生成的超像素的大小卖怜,k和len的關(guān)系是屎开。
注:圖片坐標(biāo)系以左上角為原點(diǎn),水平向右為x軸正方向马靠,水平向下為y軸正方向(與opencv一致)奄抽,在訪問(wèn)圖片數(shù)據(jù)矩陣時(shí),一般用行和列的方式來(lái)描述甩鳄,也就是row對(duì)應(yīng)y逞度,colum對(duì)應(yīng)x。
- 等間隔放置聚類中心,
int initilizeCenters(cv::Mat &imageLAB, std::vector<center> ¢ers, int len)
{
if (imageLAB.empty())
{
std::cout << "In itilizeCenters: image is empty!\n";
return -1;
}
uchar *ptr = NULL;
center cent;
int num = 0;
for (int i = 0; i < imageLAB.rows; i += len)
{
cent.y = i + len / 2;
if (cent.y >= imageLAB.rows) continue;
ptr = imageLAB.ptr<uchar>(cent.y);
for (int j = 0; j < imageLAB.cols; j += len)
{
cent.x = j + len / 2;
if ((cent.x >= imageLAB.cols)) continue;
cent.L = *(ptr + cent.x * 3);
cent.A = *(ptr + cent.x * 3 + 1);
cent.B = *(ptr + cent.x * 3 + 2);
cent.label = ++num;
centers.push_back(cent);
}
}
return 0;
}
- 把聚類中心移到到周圍8鄰域里梯度最小的地方,梯度用Sobel計(jì)算(不希望聚類中心落在邊緣上所以才調(diào)整的)
int fituneCenter(cv::Mat &imageLAB, cv::Mat &sobelGradient, std::vector<center> ¢ers)
{
if (sobelGradient.empty()) return -1;
center cent;
double *sobPtr = sobelGradient.ptr<double>(0);
uchar *imgPtr = imageLAB.ptr<uchar>(0);
int w = sobelGradient.cols;
for (int ck = 0; ck < centers.size(); ck++)
{
cent = centers[ck];
if (cent.x - 1 < 0 || cent.x + 1 >= sobelGradient.cols || cent.y - 1 < 0 || cent.y + 1 >= sobelGradient.rows)
{
continue;
}//end if
double minGradient = 9999999;
int tempx = 0, tempy = 0;
for (int m = -1; m < 2; m++)
{
sobPtr = sobelGradient.ptr<double>(cent.y + m);
for (int n = -1; n < 2; n++)
{
double gradient = pow(*(sobPtr + (cent.x + n) * 3), 2)
+ pow(*(sobPtr + (cent.x + n) * 3 + 1), 2)
+ pow(*(sobPtr + (cent.x + n) * 3 + 2), 2);
if (gradient < minGradient)
{
minGradient = gradient;
tempy = m;//row
tempx = n;//column
}//end if
}
}
cent.x += tempx;
cent.y += tempy;
imgPtr = imageLAB.ptr<uchar>(cent.y);
centers[ck].x = cent.x;
centers[ck].y = cent.y;
centers[ck].L = *(imgPtr + cent.x * 3);
centers[ck].A = *(imgPtr + cent.x * 3 + 1);
centers[ck].B = *(imgPtr + cent.x * 3 + 2);
}//end for
return 0;
}
2.2 聚類
對(duì)每一個(gè)聚類中心center_k妙啃,計(jì)算它到周圍2len*2len區(qū)域的所有點(diǎn)的距離档泽,如果新計(jì)算的距離比原來(lái)的距離更小,則把該點(diǎn)歸入center_k這一類揖赴。
注意聚類的本質(zhì)就是“物以類聚”茁瘦,判斷樣本點(diǎn)和聚類中心的“近似”程度,可以從兩個(gè)方面來(lái)考察储笑,一種是距離測(cè)度:距離越近越相似甜熔,另一種是相似性測(cè)度,例如角度相似系數(shù)突倍,相關(guān)系數(shù)腔稀,指數(shù)相似系數(shù)等盆昙。
距離的計(jì)算方式有很多種,比如:
- 歐拉距離
- 城區(qū)距離
- 切比雪夫距離
- 馬氏距離(Mahalanobis):
诵闭,它有一點(diǎn)比較好的性質(zhì)就是與量綱無(wú)關(guān)(另外它還對(duì)坐標(biāo)尺度炼团、旋轉(zhuǎn)、平移保持不變疏尿,從統(tǒng)計(jì)意義上去除了分量間的相關(guān)性)瘟芝,在這里分割超像素時(shí),Lab顏色空間的距離往往會(huì)比空間距離大很多褥琐,用歐式距離時(shí)需要加一個(gè)權(quán)重參數(shù)來(lái)調(diào)節(jié)顏色距離和空間距離的比例锌俱。
要是以后有時(shí)間的話可以考慮一下都試一下這些距離聚類的效果。這里采用的是歐式距離敌呈,而且因?yàn)長(zhǎng)ab顏色空間和圖像xy坐標(biāo)空間量綱不同贸宏,需要調(diào)整顏色空間距離和xy坐標(biāo)距離的權(quán)重,論文中用下面的方式來(lái)計(jì)算距離
但是實(shí)際上在做超像素分割時(shí)我們更關(guān)心超像素的大小磕洪,而不是有多少個(gè)吭练,雖然尺寸S和聚類數(shù)k有明確的對(duì)應(yīng)關(guān)系,但是把k當(dāng)輸入?yún)?shù)不如直接用尺寸S來(lái)得直接析显,另外實(shí)際用起來(lái)有點(diǎn)麻煩鲫咽,因?yàn)閱为?dú)修改m或者s都會(huì)被另外一個(gè)參數(shù)調(diào)制,所以D的計(jì)算我改成了下面這樣
int clustering(const cv::Mat &imageLAB, cv::Mat &DisMask, cv::Mat &labelMask,
std::vector<center> ¢ers, int len, int m)
{
if (imageLAB.empty())
{
std::cout << "clustering :the input image is empty!\n";
return -1;
}
double *disPtr = NULL;//disMask type: 64FC1
double *labelPtr = NULL;//labelMask type: 64FC1
const uchar *imgPtr = NULL;//imageLAB type: 8UC3
//disc = std::sqrt(pow(L - cL, 2)+pow(A - cA, 2)+pow(B - cB,2))
//diss = std::sqrt(pow(x-cx,2) + pow(y-cy,2));
//dis = sqrt(disc^2 + (diss/len)^2 * m^2)
double dis = 0, disc = 0, diss = 0;
//cluster center's cx, cy,cL,cA,cB;
int cx, cy, cL, cA, cB, clabel;
//imageLAB's x, y, L,A,B
int x, y, L, A, B;
//注:這里的圖像坐標(biāo)以左上角為原點(diǎn)叫榕,水平向右為x正方向,水平向下為y正方向浑侥,與opencv保持一致
// 從矩陣行列角度看姊舵,i表示行晰绎,j表示列,即(i,j) = (y,x)
for (int ck = 0; ck < centers.size(); ++ck)
{
cx = centers[ck].x;
cy = centers[ck].y;
cL = centers[ck].L;
cA = centers[ck].A;
cB = centers[ck].B;
clabel = centers[ck].label;
for (int i = cy - len; i < cy + len; i++)
{
if (i < 0 | i >= imageLAB.rows) continue;
//pointer point to the ith row
imgPtr = imageLAB.ptr<uchar>(i);
disPtr = DisMask.ptr<double>(i);
labelPtr = labelMask.ptr<double>(i);
for (int j = cx - len; j < cx + len; j++)
{
if (j < 0 | j >= imageLAB.cols) continue;
L = *(imgPtr + j * 3);
A = *(imgPtr + j * 3 + 1);
B = *(imgPtr + j * 3 + 2);
disc = std::sqrt(pow(L - cL, 2) + pow(A - cA, 2) + pow(B - cB, 2));
diss = std::sqrt(pow(j - cx, 2) + pow(i - cy, 2));
dis = sqrt(pow(disc, 2) + m * pow(diss, 2));
if (dis < *(disPtr + j))
{
*(disPtr + j) = dis;
*(labelPtr + j) = clabel;
}//end if
}//end for
}
}//end for (int ck = 0; ck < centers.size(); ++ck)
return 0;
}
2.3 更新聚類中心
對(duì)每一個(gè)聚類中心center_k括丁,把所有屬于這一類的點(diǎn)的特征加起來(lái)求平均荞下,把這個(gè)平均特征賦給center_k。
int updateCenter(cv::Mat &imageLAB, cv::Mat &labelMask, std::vector<center> ¢ers, int len)
{
double *labelPtr = NULL;//labelMask type: 64FC1
const uchar *imgPtr = NULL;//imageLAB type: 8UC3
int cx, cy;
for (int ck = 0; ck < centers.size(); ++ck)
{
double sumx = 0, sumy = 0, sumL = 0, sumA = 0, sumB = 0, sumNum = 0;
cx = centers[ck].x;
cy = centers[ck].y;
for (int i = cy - len; i < cy + len; i++)
{
if (i < 0 | i >= imageLAB.rows) continue;
//pointer point to the ith row
imgPtr = imageLAB.ptr<uchar>(i);
labelPtr = labelMask.ptr<double>(i);
for (int j = cx - len; j < cx + len; j++)
{
if (j < 0 | j >= imageLAB.cols) continue;
if (*(labelPtr + j) == centers[ck].label)
{
sumL += *(imgPtr + j * 3);
sumA += *(imgPtr + j * 3 + 1);
sumB += *(imgPtr + j * 3 + 2);
sumx += j;
sumy += i;
sumNum += 1;
}//end if
}
}
//update center
if (sumNum == 0) sumNum = 0.000000001;
centers[ck].x = sumx / sumNum;
centers[ck].y = sumy / sumNum;
centers[ck].L = sumL / sumNum;
centers[ck].A = sumA / sumNum;
centers[ck].B = sumB / sumNum;
}//end for
return 0;
}
2.4 顯示超像素分割結(jié)果
方式一:把屬于同一類的點(diǎn)的特征都替換成平均特征;
方式二:畫出聚類邊界;
3. 實(shí)測(cè)效果
-
左側(cè)為原圖史飞,中間為在原圖上畫出超像素邊界效果圖尖昏,右側(cè)為超像素圖像效果
bassball.png
4. 完整源碼
//
//created by Mr. Peng. 2021\08\31
//
#include "opencv.hpp"
struct center
{
int x;//column
int y;//row
int L;
int A;
int B;
int label;
};
/////////////////////////////////////////////////////
//input parameters:
//imageLAB: the source image in Lab color space
//DisMask: it save the shortest distance to the nearest center
//labelMask: it save every pixel's label
//centers: clustering center
//len: the super pixls will be initialize to len*len
//m: a parameter witch adjust the weights of the spacial and color space distance
//
//output:
////////////////////////////////////////////////////
int clustering(const cv::Mat &imageLAB, cv::Mat &DisMask, cv::Mat &labelMask,
std::vector<center> ¢ers, int len, int m)
{
if (imageLAB.empty())
{
std::cout << "clustering :the input image is empty!\n";
return -1;
}
double *disPtr = NULL;//disMask type: 64FC1
double *labelPtr = NULL;//labelMask type: 64FC1
const uchar *imgPtr = NULL;//imageLAB type: 8UC3
//disc = std::sqrt(pow(L - cL, 2)+pow(A - cA, 2)+pow(B - cB,2))
//diss = std::sqrt(pow(x-cx,2) + pow(y-cy,2));
//dis = sqrt(disc^2 + (diss/len)^2 * m^2)
double dis = 0, disc = 0, diss = 0;
//cluster center's cx, cy,cL,cA,cB;
int cx, cy, cL, cA, cB, clabel;
//imageLAB's x, y, L,A,B
int x, y, L, A, B;
//注:這里的圖像坐標(biāo)以左上角為原點(diǎn),水平向右為x正方向,水平向下為y正方向构资,與opencv保持一致
// 從矩陣行列角度看抽诉,i表示行,j表示列吐绵,即(i,j) = (y,x)
for (int ck = 0; ck < centers.size(); ++ck)
{
cx = centers[ck].x;
cy = centers[ck].y;
cL = centers[ck].L;
cA = centers[ck].A;
cB = centers[ck].B;
clabel = centers[ck].label;
for (int i = cy - len; i < cy + len; i++)
{
if (i < 0 | i >= imageLAB.rows) continue;
//pointer point to the ith row
imgPtr = imageLAB.ptr<uchar>(i);
disPtr = DisMask.ptr<double>(i);
labelPtr = labelMask.ptr<double>(i);
for (int j = cx - len; j < cx + len; j++)
{
if (j < 0 | j >= imageLAB.cols) continue;
L = *(imgPtr + j * 3);
A = *(imgPtr + j * 3 + 1);
B = *(imgPtr + j * 3 + 2);
disc = std::sqrt(pow(L - cL, 2) + pow(A - cA, 2) + pow(B - cB, 2));
diss = std::sqrt(pow(j - cx, 2) + pow(i - cy, 2));
dis = sqrt(pow(disc, 2) + m * pow(diss, 2));
if (dis < *(disPtr + j))
{
*(disPtr + j) = dis;
*(labelPtr + j) = clabel;
}//end if
}//end for
}
}//end for (int ck = 0; ck < centers.size(); ++ck)
return 0;
}
/////////////////////////////////////////////////////
//input parameters:
//imageLAB: the source image in Lab color space
//labelMask: it save every pixel's label
//centers: clustering center
//len: the super pixls will be initialize to len*len
//
//output:
////////////////////////////////////////////////////
int updateCenter(cv::Mat &imageLAB, cv::Mat &labelMask, std::vector<center> ¢ers, int len)
{
double *labelPtr = NULL;//labelMask type: 64FC1
const uchar *imgPtr = NULL;//imageLAB type: 8UC3
int cx, cy;
for (int ck = 0; ck < centers.size(); ++ck)
{
double sumx = 0, sumy = 0, sumL = 0, sumA = 0, sumB = 0, sumNum = 0;
cx = centers[ck].x;
cy = centers[ck].y;
for (int i = cy - len; i < cy + len; i++)
{
if (i < 0 | i >= imageLAB.rows) continue;
//pointer point to the ith row
imgPtr = imageLAB.ptr<uchar>(i);
labelPtr = labelMask.ptr<double>(i);
for (int j = cx - len; j < cx + len; j++)
{
if (j < 0 | j >= imageLAB.cols) continue;
if (*(labelPtr + j) == centers[ck].label)
{
sumL += *(imgPtr + j * 3);
sumA += *(imgPtr + j * 3 + 1);
sumB += *(imgPtr + j * 3 + 2);
sumx += j;
sumy += i;
sumNum += 1;
}//end if
}
}
//update center
if (sumNum == 0) sumNum = 0.000000001;
centers[ck].x = sumx / sumNum;
centers[ck].y = sumy / sumNum;
centers[ck].L = sumL / sumNum;
centers[ck].A = sumA / sumNum;
centers[ck].B = sumB / sumNum;
}//end for
return 0;
}
int showSLICResult(const cv::Mat &image, cv::Mat &labelMask, std::vector<center> ¢ers, int len)
{
cv::Mat dst = image.clone();
cv::cvtColor(dst, dst, cv::COLOR_BGR2Lab);
double *labelPtr = NULL;//labelMask type: 32FC1
uchar *imgPtr = NULL;//image type: 8UC3
int cx, cy;
double sumx = 0, sumy = 0, sumL = 0, sumA = 0, sumB = 0, sumNum = 0.00000001;
for (int ck = 0; ck < centers.size(); ++ck)
{
cx = centers[ck].x;
cy = centers[ck].y;
for (int i = cy - len; i < cy + len; i++)
{
if (i < 0 | i >= image.rows) continue;
//pointer point to the ith row
imgPtr = dst.ptr<uchar>(i);
labelPtr = labelMask.ptr<double>(i);
for (int j = cx - len; j < cx + len; j++)
{
if (j < 0 | j >= image.cols) continue;
if (*(labelPtr + j) == centers[ck].label)
{
*(imgPtr + j * 3) = centers[ck].L;
*(imgPtr + j * 3 + 1) = centers[ck].A;
*(imgPtr + j * 3 + 2) = centers[ck].B;
}//end if
}
}
}//end for
cv::cvtColor(dst, dst, cv::COLOR_Lab2BGR);
cv::namedWindow("showSLIC", 0);
cv::imshow("showSLIC", dst);
cv::waitKey(1);
return 0;
}
int showSLICResult2(const cv::Mat &image, cv::Mat &labelMask, std::vector<center> ¢ers, int len)
{
cv::Mat dst = image.clone();
//cv::cvtColor(dst, dst, cv::COLOR_Lab2BGR);
double *labelPtr = NULL;//labelMask type: 32FC1
double *labelPtr_nextRow = NULL;//labelMask type: 32FC1
uchar *imgPtr = NULL;//image type: 8UC3
for (int i = 0; i < labelMask.rows - 1; i++)
{
labelPtr = labelMask.ptr<double>(i);
imgPtr = dst.ptr<uchar>(i);
for (int j = 0; j < labelMask.cols - 1; j++)
{
//if left pixel's label is different from the right's
if (*(labelPtr + j) != *(labelPtr + j + 1))
{
*(imgPtr + 3 * j) = 0;
*(imgPtr + 3 * j + 1) = 0;
*(imgPtr + 3 * j + 2) = 0;
}
//if the upper pixel's label is different from the bottom's
labelPtr_nextRow = labelMask.ptr<double>(i + 1);
if (*(labelPtr_nextRow + j) != *(labelPtr + j))
{
*(imgPtr + 3 * j) = 0;
*(imgPtr + 3 * j + 1) = 0;
*(imgPtr + 3 * j + 2) = 0;
}
}
}
//show center
for (int ck = 0; ck < centers.size(); ck++)
{
imgPtr = dst.ptr<uchar>(centers[ck].y);
*(imgPtr + centers[ck].x * 3) = 100;
*(imgPtr + centers[ck].x * 3 + 1) = 100;
*(imgPtr + centers[ck].x * 3 + 1) = 10;
}
cv::namedWindow("showSLIC2", 0);
cv::imshow("showSLIC2", dst);
cv::waitKey(1);
return 0;
}
int initilizeCenters(cv::Mat &imageLAB, std::vector<center> ¢ers, int len)
{
if (imageLAB.empty())
{
std::cout << "In itilizeCenters: image is empty!\n";
return -1;
}
uchar *ptr = NULL;
center cent;
int num = 0;
for (int i = 0; i < imageLAB.rows; i += len)
{
cent.y = i + len / 2;
if (cent.y >= imageLAB.rows) continue;
ptr = imageLAB.ptr<uchar>(cent.y);
for (int j = 0; j < imageLAB.cols; j += len)
{
cent.x = j + len / 2;
if ((cent.x >= imageLAB.cols)) continue;
cent.L = *(ptr + cent.x * 3);
cent.A = *(ptr + cent.x * 3 + 1);
cent.B = *(ptr + cent.x * 3 + 2);
cent.label = ++num;
centers.push_back(cent);
}
}
return 0;
}
//if the center locates in the edges, fitune it's location.
int fituneCenter(cv::Mat &imageLAB, cv::Mat &sobelGradient, std::vector<center> ¢ers)
{
if (sobelGradient.empty()) return -1;
center cent;
double *sobPtr = sobelGradient.ptr<double>(0);
uchar *imgPtr = imageLAB.ptr<uchar>(0);
int w = sobelGradient.cols;
for (int ck = 0; ck < centers.size(); ck++)
{
cent = centers[ck];
if (cent.x - 1 < 0 || cent.x + 1 >= sobelGradient.cols || cent.y - 1 < 0 || cent.y + 1 >= sobelGradient.rows)
{
continue;
}//end if
double minGradient = 9999999;
int tempx = 0, tempy = 0;
for (int m = -1; m < 2; m++)
{
sobPtr = sobelGradient.ptr<double>(cent.y + m);
for (int n = -1; n < 2; n++)
{
double gradient = pow(*(sobPtr + (cent.x + n) * 3), 2)
+ pow(*(sobPtr + (cent.x + n) * 3 + 1), 2)
+ pow(*(sobPtr + (cent.x + n) * 3 + 2), 2);
if (gradient < minGradient)
{
minGradient = gradient;
tempy = m;//row
tempx = n;//column
}//end if
}
}
cent.x += tempx;
cent.y += tempy;
imgPtr = imageLAB.ptr<uchar>(cent.y);
centers[ck].x = cent.x;
centers[ck].y = cent.y;
centers[ck].L = *(imgPtr + cent.x * 3);
centers[ck].A = *(imgPtr + cent.x * 3 + 1);
centers[ck].B = *(imgPtr + cent.x * 3 + 2);
}//end for
return 0;
}
/////////////////////////////////////////////////////
//input parameters:
//image: the source image in RGB color space
//resultLabel: it save every pixel's label
//len: the super pixls will be initialize to len*len
//m: a parameter witch adjust the weights of diss
//output:
////////////////////////////////////////////////////
int SLIC(cv::Mat &image, cv::Mat &resultLabel, std::vector<center> ¢ers, int len, int m)
{
if (image.empty())
{
std::cout << "in SLIC the input image is empty!\n";
return -1;
}
int MAXDIS = 999999;
int height, width;
height = image.rows;
width = image.cols;
//convert color
cv::Mat imageLAB;
cv::cvtColor(image, imageLAB, cv::COLOR_BGR2Lab);
//get sobel gradient map
cv::Mat sobelImagex, sobelImagey, sobelGradient;
cv::Sobel(imageLAB, sobelImagex, CV_64F, 0, 1, 3);
cv::Sobel(imageLAB, sobelImagey, CV_64F, 1, 0, 3);
cv::addWeighted(sobelImagex, 0.5, sobelImagey, 0.5, 0, sobelGradient);//sobel output image type is CV_64F
//initiate
//std::vector<center> centers;
//disMask save the distance of the pixels to center;
cv::Mat disMask ;
//labelMask save the label of the pixels
cv::Mat labelMask = cv::Mat::zeros(cv::Size(width, height), CV_64FC1);
//initialize centers, get centers
initilizeCenters(imageLAB, centers, len);
//if the center locates in the edges, fitune it's location
fituneCenter(imageLAB, sobelGradient, centers);
//update cluster 10 times
for (int time = 0; time < 10; time++)
{
//clustering
disMask = cv::Mat(height, width, CV_64FC1, cv::Scalar(MAXDIS));
clustering(imageLAB, disMask, labelMask, centers, len, m);
//update
updateCenter(imageLAB, labelMask, centers, len);
//fituneCenter(imageLAB, sobelGradient, centers);
}
resultLabel = labelMask;
return 0;
}
int SLIC_Demo()
{
std::string imagePath = "K:\\deepImage\\plane.jpg";
cv::Mat image = cv::imread(imagePath);
cv::Mat labelMask;//save every pixel's label
cv::Mat dst;//save the shortest distance to the nearest centers
std::vector<center> centers;//clustering centers
int len = 25;//the scale of the superpixel ,len*len
int m = 10;//a parameter witch adjust the weights of spacial distance and the color space distance
SLIC(image, labelMask, centers, len, m);
cv::namedWindow("image", 1);
cv::imshow("image", image);
showSLICResult(image, labelMask, centers, len);
showSLICResult2(image, labelMask, centers, len);
cv::waitKey(0);
return 0;
}
int main()
{
SLIC_Demo();
return 0;
}