關於二值化的問題

以上是在將位圖加載到內存中,直接在加載的內存中操作像素的結果,很美!

但是!以下這段代碼,新開闢了一段內存,出現的結果竟然是原圖???????,不得解,已經解決了,問題的根源就是出現在CDib::Draw函數的內部的lpData,        // 指向DIB數據的指針,之前錯誤的時候用的是CDib::m_lpData,自然不對。

void CRightView::clearmem()
{
    CSpliter2Doc * pDoc = (CSpliter2Doc*)GetDocument();
	ASSERT_VALID(pDoc);
	pDoc->statedoc = 0;
    state2 = 1;
	m_imagex = pDoc->Cdib.GetWidth();
	m_imagey = pDoc->Cdib.GetHeight();
	long int size = m_imagex * m_imagey;
	if(pDoc->Cdib.GetBitCount() > 8)  // 真彩圖
		AfxMessageBox("No");
	else{}
	image_in = new BYTE[size];
	image_out = new BYTE[size];
	memcpy(image_in,pDoc->Cdib.m_lpData,size);   // 複製原圖像數據到處理區
}

void CRightView::OnShowtwo() 
{
	CSpliter2Doc * pDoc = (CSpliter2Doc*)GetDocument();
	ASSERT_VALID(pDoc);
	// TODO: Add your command handler code here
	clearmem();
	for(int i = 0; i < m_imagey; i++)
	{
		for(int j = 0; j < m_imagex; j++)
		{
			//if(*(image_in + i*m_imagex + j) > 128)
             // *(image_out + i*m_imagex + j) = 255;
			//else
			  *(image_out + i*m_imagex + j) = 0;
		}
	}

 

接下來,以Lina圖爲例,分析一下各種二值化方法:

一:灰度平局值值法:

    即使用整幅圖像的灰度平均值作爲二值化的閾值,一般該方法可作爲其他方法的初始猜想值。

二、百分比閾值(P-Tile法) 

Doyle於1962年提出的P-Tile (即P分位數法)可以說是最古老的一種閾值選取方法。該方法根據先驗概率來設定閾值,使得二值化後的目標或背景像素比例等於先驗概率,該方法簡單高效,但是對於先驗概率難於估計的圖像卻無能爲力。因爲本圖不好估計先驗概率,故沒有試驗。

三、基於谷底最小值的閾值

這個方法適用於通過有限的迭代次數,平滑後能得到雙峯的圖像,讓雙峯的谷底成爲閾值.但出現了一個錯誤CXX0030: Error: expression cannot be evaluated,當執行完基於谷底最小值的閾值操作的時候,我改變了直方圖信息,使之成爲處理過後的直方圖信息,這時候顯示Doc裏的數據沒有問題,可是在直方圖類裏畫圖的時候卻出現了這個錯誤。問題解決了,出現的原因是在不恰當的地方獲取了數據。。。(菜單‘直方圖’的響應函數中獲取原圖直方圖數據,第二次響應的時候又獲取了一遍),以下是正確的效果,左圖爲原圖直方圖,右圖爲平滑後雙峯圖,左鋒爲30,峯谷爲46,右峯爲104.

 

 四、基於雙峯平均值的閾值 

該算法和基於谷底最小值的閾值方法類似,只是最後一步不是取得雙峯之間的谷底值,而是取雙峯的平均值作爲閾值。

五、迭代最佳閾值

該算法先假定一個閾值,然後計算在該閾值下的前景和背景的中心值,當前景和背景中心值(平均灰度值)的平均值和假定的閾值相同時,則迭代中止,並以此值爲閾值進行二值化 。

void CRightView::OnShow6() 
{
   /**********************************************************************************************
    * 迭代法求最佳閾值:
	*   思想:使所求的閾值劃分出來的前景和背景的平均灰度之和的一半等於該閾值
    *   描述:該算法先假定一個閾值,然後計算在該閾值下的前景和背景的中心值,
	*         當前景和背景中心值得平均值和假定的閾值相同時,則迭代中止,並以此值爲閾值進行二值化
	**********************************************************************************************/

	clearmem();
    CSpliter2Doc* pDoc = (CSpliter2Doc*)GetDocument();
    ASSERT_VALID(pDoc);

	// 1,求出圖像最大灰度值和最小灰度值,初始化閾值T
	int nT = 0, nY;                                               // 零時閾值
	double dHistGramC [256];                                      // 記錄直方圖信息
	int nMax,nMin;                                                // 記錄最大和最小灰度值
	bool b = true;                                                // 一個零時開關
	for(nY = 0; nY < 256; nY++)
	{
		dHistGramC[nY]  = pDoc->m_dHist[nY];                      // 獲取直方圖信息
		if(b == true && dHistGramC[nY] > 0)
		{
			nMin = nY;
			b = false;                                            // 得到最小灰度值,關閉開關
		}
		else{}
		if(dHistGramC[nY] > 0)
			nMax = nY;                                            // 更新最大灰度值
		else{}
	}

	// 2,以上程序求得最大灰度和最小灰度分別爲nMax,nMin,下面迭代
	nT = (nMax + nMin) / 2;                                       // 首次的閾值
	int nCount = 0;                                               // 記錄像素
	int nSum = 0;                                                 // 記錄總灰度,平均灰度值:nSum / nCount
	int nQianjing = 0, nBeijing = 0;                              // 分別記錄前景和背景的平均灰度值
	
	while(true)
	{
		// 2.1,算前景和後景的平均灰度值
        for(nY = 0; nY < nT; nY++)
		{
			nCount += (int)dHistGramC[nY];
			nSum += nY * (int)dHistGramC[nY];
		}
		nQianjing = nSum / nCount;                                // 得到前景的平均灰度值

		nCount = nSum = 0;                                        // 歸零,準備計算背景
		for(nY = nT; nY < 256; nY++)
		{
			nCount += (int)dHistGramC[nY];
			nSum += nY * (int)dHistGramC[nY];
		}
		nBeijing = nSum / nCount;                                 // 得到背景的平均灰度值

		// 2.2,判斷是否滿足結束迭代條件
		if(nT == (nQianjing + nBeijing) / 2)
			break;
		else
			nT = (nQianjing + nBeijing) / 2;
		nCount = nSum = 0;                                        // 歸零,準備下一次迭代
	}

	// 3,經過以上迭代,求得了閾值nT
    m_nYuzhi = nT;
    Invalidate();
}

六、OSTU大津法

該算法是1979年由日本大津提出的,主要是思想是取某個閾值,使得前景和背景兩類的類間方差最大 

大津法選取出來的閾值比較理想,對各種情況的表現都較爲良好。雖然它在很多情況下都不是最佳的分割,但分割質量通常都有一定的保障,是較穩定的分割,算是一種較爲通用的分割算法。對於具有明顯雙峯直方圖的圖像效果明顯,但對於低對比度和光照不均勻的圖像效果不佳,大津法致命的缺陷是當目標物與背景灰度差不明顯時,會出現無法忍受的大塊黑色區域,甚至會丟失整幅圖像的信息。

/**************************************************************************
	 * OSTU大津法:
	 *     主要是思想是取某個閾值,使得前景和背景兩類的類間方差最大
	 * 說明:
	 *     背景和目標之間的類間方差越大,說明構成圖像的2部分的差別越大,
     *     當部分目標錯分爲背景或部分背景錯分爲目標都會導致2部
     *     分差別變小。因此,使類間方差最大的分割意味着錯分概率最小。
	 * 參數:
	 *     T:前景(即目標)和背景的分割閾值
	 *     W0: 前景的像素點數佔整幅圖像的比例
	 *     U0: 前景的平均灰度
	 *     W1: 背景的像素點數佔整幅圖像的比例
	 *     U1: 背景的平均灰度
	 *     U:  圖像總的平均灰度
	 *     g:  類間方差
	 **************************************************************************/

類間方差:dW0 * (dU0 - dU)*(dU0 - dU) + dW1 * (dU1 - dU)*(dU1 - dU) 

、一維最大熵

使用過程中計算熵的時候出現了數據越界,-1.#IND000000000000因爲是太小了,就加了個判斷。

/****************************************************************************************************
	  * 最大熵法:
	  *     該算法把信息論中熵的概念引入到圖像中,通過計算閾值分割後兩部分熵的和來判斷閾值是否爲最佳閾值。
	  *     所謂熵值最大,就是圖像所包含的信息量是最大的。
	  * 參數:
	  *     Q:閾值
	  *     P0:前景像素累計概率
	  *     P1:背景像素累積概率
	  *     H0:前景熵
	  *     H1:背景熵
	  *     H:整幅圖像的熵
	  *****************************************************************************************************/

 

八、局部閾值之Bernsen法

Q1:第一行的像素和最後一行的設置?

/******************************************************************************************
	 * Bernsen法:
	 *    屬於局部閾值法,在光照不均勻的條件下有較好的處理效果
	 * 思想:
	 *    先人爲設定兩個值S與TT(Bemsen最初設S爲15,TT設爲128),計算以圖像中任意像素屍爲
	 *    中心的大小爲k×k(本程序K = 3)窗口內的所有像素的最大值M與最小值N,兩者的均值T,如果朋M-N大於S,
	 *    則當前P的閾值爲T;若小於S,則表示該窗口所在區域灰度級灰度級差別較小,那麼窗口在
	 *    目標區或在背景區,再判斷T與TT的關係,若T>TT則當前點灰度值爲255,否則當前點灰度值爲0。
	 ******************************************************************************************/

 

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