前兩天看了一篇碩士學位論文,但是在知網上被引用了13次,下載了700多次。是相關主題中相對最有價值的一篇論文。
論文題目:細胞圖像的分割與計數
作者:王筱(xiao)豔(四川大學)生物醫學工程專業,生物醫學圖像研究方向
論文設計了一個軟件,可以進行細胞圖像的分割、自動識別、統計分析的功能。高效準確且使用方便。
在我看完這篇論文後,我發現最重要的是她解決了鏈式粘連以及非鏈式粘連細胞的分割。
在這裏主要說她利用線長直方圖估計等效直徑這個想法十分出彩。
輪到我自己進行實踐的時候,也想到提取線長直方圖,結果發現網上所有有關opencv直方圖提取的全是灰度直方圖。。。
這就很惱火,所以我準備自己寫一個。
首先了解一下線長直方圖(以線段長度爲橫軸,以線長出現的次數爲縱軸。)
粘連越嚴重的細胞圖像,其線長直方圖最高峯越往右移,因此通過最高峯估計出來的等效直徑要根據粘連嚴重程度做一個修正,這個修正值應該憑經驗選擇。這裏就不管什麼修正了。
重點是實現:
以下爲代碼:
void my_Hist(Mat Gray_img){
//繪製直方圖圖像
int hist_height=500;
double max_val=500; //直方圖的最大值
int scale = 2; //直方圖的寬度
int hist[500] = {0};
// at方法遍歷圖片
int data=0;
int length=0;//長度計數
for(int i=0;i<Gray_img.rows;i++) //遍歷行
{
for(int j=0;j<Gray_img.cols;j++) //遍歷列
{
data = Gray_img.at<uchar>(i,j);
if(data!=0)
length++;
else
{
if(length!=0)
{
hist[length]++;
length=0;
}
}
}
length=0;
}
/*for(int p=0;p<80;p++)
cout<<hist[p]<<endl;*/
max_val=max(hist,500);
Mat hist_img = Mat::zeros(hist_height,500*scale, CV_8UC3); //創建一個直方圖圖像並初始化爲0
int bin_val=0;int intensity=0;
//在直方圖圖像中寫入直方圖數據
for(int i=0;i<500;i++)
{
bin_val = hist[i]; // 第i灰度級上的數
intensity = cvRound(bin_val*hist_height/max_val); //要繪製的高度
//填充第i灰度級的數據
rectangle(hist_img,Point(i*scale,hist_height-1),
Point((i+1)*scale - 1, hist_height - intensity),
CV_RGB(255,255,255));
}
imshow( "Histogram", hist_img );
imwrite("Histogram.bmp", hist_img);
}
我在寫這部分代碼的時候,借鑑了灰度直方圖顯示直方圖圖片的方法,用一維數組代替了原本的MatND格式的hist,成功實現了橫向線長直方圖的提取。
至於怎麼調用這段代碼只需要當作一個函數調用就好了,輸入是Mat的灰度圖
以下是原圖以及結果圖
2017.3.31加:
後來添加了縱向上線段長度的統計,也就是把上面行列順序換一下,效果好了不少。
接下來考慮了統計方法進行優化,比如每五個取均值之類的,能夠讓效果好很多。圖就懶得放了。