1. 程式人生 > >【OpenCV入門指南】第四篇 影象的二值化

【OpenCV入門指南】第四篇 影象的二值化

【OpenCV入門指南】第四篇 影象的二值化

   在上一篇《【OpenCV入門指南】第三篇Canny邊緣檢測》中介紹了使用Canny運算元對影象進行邊緣檢測。與邊緣檢測相比,輪廓檢測有時能更好的反映影象的內容。而要對影象進行輪廓檢測,則必須要先對影象進行二值化,影象的二值化就是將影象上的畫素點的灰度值設定為0255,這樣將使整個影象呈現出明顯的黑白效果。在數字影象處理中,二值影象佔有非常重要的地位,影象的二值化使影象中資料量大為減少,從而能凸顯出目標的輪廓。

《OpenCV入門指南》系列文章地址:http://blog.csdn.net/morewindows/article/category/1291764

一. 關鍵函式介紹

下面就介紹OpenCV中對影象進行二值化的關鍵函式——cvThreshold()

函式功能:採用Canny方法對影象進行邊緣檢測

函式原型:

void cvThreshold(

  const CvArr* src,

  CvArr* dst,

  double threshold,

  double max_value,

  int threshold_type

);

函式說明:

第一個引數表示輸入影象,必須為單通道灰度圖。

第二個引數表示輸出的邊緣影象,為單通道黑白圖。

第三個引數表示閾值

第四個引數表示最大值。

第五個引數表示運算方法。

OpenCVimgproc\types_c.h中可以找到運算方法的定義。

/* Threshold types */

enum

{

    CV_THRESH_BINARY      =0,  /* value = value > threshold ? max_value : 0       */

    CV_THRESH_BINARY_INV

  =1,  /* value = value > threshold ? 0 : max_value       */

    CV_THRESH_TRUNC       =2,  /* value = value > threshold ? threshold : value   */

    CV_THRESH_TOZERO      =3,  /* value = value > threshold ? value : 0           */

    CV_THRESH_TOZERO_INV  =4,  /* value = value > threshold ? 0 : value           */

    CV_THRESH_MASK        =7,

    CV_THRESH_OTSU        =8  /* use Otsu algorithm to choose the optimal threshold value; combine the flag with one of the above CV_THRESH_* values */

};

註釋已經寫的很清楚了,因此不再用中文來表達了。

 

二. 示例程式程式碼

下面給出對影象進行二值化的完整的原始碼:

//影象的二值化
//By MoreWindows (http://blog.csdn.net/MoreWindows)
#include <opencv2/opencv.hpp>
using namespace std;

#pragma comment(linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"")

IplImage *g_pGrayImage = NULL;
IplImage *g_pBinaryImage = NULL;
const char *pstrWindowsBinaryTitle = "二值圖(http://blog.csdn.net/MoreWindows)";

void on_trackbar(int pos)
{
	// 轉為二值圖
	cvThreshold(g_pGrayImage, g_pBinaryImage, pos, 255, CV_THRESH_BINARY);
	// 顯示二值圖
	cvShowImage(pstrWindowsBinaryTitle, g_pBinaryImage);
}

int main( int argc, char** argv )
{	
	const char *pstrWindowsSrcTitle = "原圖(http://blog.csdn.net/MoreWindows)";
	const char *pstrWindowsToolBarName = "二值圖閾值";

	// 從檔案中載入原圖
	IplImage *pSrcImage = cvLoadImage("002.jpg", CV_LOAD_IMAGE_UNCHANGED);

	// 轉為灰度圖
	g_pGrayImage =  cvCreateImage(cvGetSize(pSrcImage), IPL_DEPTH_8U, 1);
	cvCvtColor(pSrcImage, g_pGrayImage, CV_BGR2GRAY);

	// 建立二值圖
	g_pBinaryImage = cvCreateImage(cvGetSize(g_pGrayImage), IPL_DEPTH_8U, 1);

	// 顯示原圖
	cvNamedWindow(pstrWindowsSrcTitle, CV_WINDOW_AUTOSIZE);
	cvShowImage(pstrWindowsSrcTitle, pSrcImage);
	// 建立二值圖視窗
	cvNamedWindow(pstrWindowsBinaryTitle, CV_WINDOW_AUTOSIZE);

	// 滑動條	
	int nThreshold = 0;
	cvCreateTrackbar(pstrWindowsToolBarName, pstrWindowsBinaryTitle, &nThreshold, 254, on_trackbar);

	on_trackbar(1);

	cvWaitKey(0);

	cvDestroyWindow(pstrWindowsSrcTitle);
	cvDestroyWindow(pstrWindowsBinaryTitle);
	cvReleaseImage(&pSrcImage);
	cvReleaseImage(&g_pGrayImage);
	cvReleaseImage(&g_pBinaryImage);
	return 0;
}

執行結果如下所示,讀者可以到下載原始檔和程式(Release版本,不用安裝OpenCV也能使用),自己動手除錯下閾值大小,看看生成的二值圖有什麼變化。

 

OpenCV還有個cvAdaptiveThreshold()函式,這個函式會使用Otsu演算法(大律法或最大類間方差法)(注1)來計算出一個全域性閾值,然後根據這個閾值進行二值化。當然直接使用上一篇《OpenCV入門指南】第三篇Canny邊緣檢測》中的cvCanny()函式也可以對影象進行二值化(想到怎麼傳引數了嗎?)。

 

好了,影象的二值化就介紹到這裡了,歡迎繼續瀏覽下面二篇《OpenCV入門指南】第五篇輪廓檢測上》和《OpenCV入門指南】第六篇輪廓檢測下》,謝謝。

 

  

 

1.呼叫cvThreshold()時傳入引數CV_THRESH_OTSU也是使用Otsu演算法來自動生成一個閾值。


 

轉載請標明出處,原文地址:http://blog.csdn.net/morewindows/article/details/8239678

《OpenCV入門指南》系列文章地址:http://blog.csdn.net/morewindows/article/category/1291764

 

再分享一下我老師大神的人工智慧教程吧。零基礎!通俗易懂!風趣幽默!希望你也加入到我們人工智慧的隊伍中來!http://www.captainbed.net