圖像分割-基本邊緣檢測roberts,prewitt,sobel,canny,laplace

執行邊緣檢測的三個基本步驟:
1、爲降噪對圖像進行平滑處理。(導數對噪聲具有敏感性。圖像的正負分量檢測困難)
2、邊緣點的檢測。(提取邊緣點的潛在候選者)
3、邊緣定位。(從候選者中選出真是邊緣點成員)
步驟
基本算子:梯度算子(表徵某點邊緣強度和方向,又稱邊緣檢測子)
梯度
梯度幅值

較爲簡單的邊緣檢測算子模板:
水平和豎直分量
45度和135度分量
sobel模板能較好地抑制噪聲。
常用絕對值來近似梯度幅值,保持灰度級的相對變化,代價是導致濾波器不再是各向同性的。
近似梯度幅值

sobel計算過程


Opencv庫函數調用方法:

void Sobel (
InputArray src,
OutputArray dst,
int ddepth,
int dx, x方向上的差分階數
int dy, y方向上的差分階數
int ksize=3, 核的大小,爲奇數
double scale=1, 計算導數時的縮放因子
double delta=0, 將結果存入目標圖像前可選的值
int borderType=BORDER_DEFAULT ) ;
在這裏插入圖片描述

int main()
{
	// Read image 讀取圖像
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_GREEN);		//字體爲綠色
	//載入原圖
	Mat srcImage = imread("D:\\opencv_picture_test\\形態學操作\\coin_inv.png",0);	//讀取灰度圖
	//判斷圖像是否加載成功
	if (srcImage.empty())
	{
		cout << "圖像加載失敗!" << endl;
		return -1;
	}
	else
		cout << "圖像加載成功!" << endl << endl;
	Mat gradx, grady;
	Mat abs_gradx, abs_grady;
	Mat dstImage;
	//求x方向的梯度
	Sobel(srcImage,gradx,CV_16S,1,0,3,1,1,BORDER_DEFAULT);//	x方向1階差分 y方向0 核大小3
	convertScaleAbs(gradx, abs_gradx);		//絕對值
	//求y方向的梯度
	Sobel(srcImage, grady, CV_16S, 0, 1, 3, 1, 1, BORDER_DEFAULT);//	x方向1階差分 y方向0 核大小3
	convertScaleAbs(grady, abs_grady);		//絕對值
	addWeighted(abs_gradx,0.5, abs_grady,0.5,0,dstImage);

	imshow("srcImage", srcImage);
	imshow("x方向", abs_gradx);
	imshow("y方向", abs_grady);
	imshow("整體", dstImage);
	waitKey(0);
	return 0;
}

效果
總覽
經過ImageWatch放大發現,提取出的邊緣比較粗。
放大
減少精密細節的兩種方法:
1、對圖像進行平滑處理(例如用均值濾波,得到主要邊緣)
2、對梯度圖像進行閾值處理(梯度幅值大於等於閾值爲黑白,小於閾值爲黑),不過這一方法容易斷線。
當爲了突出主要邊緣並儘可能維護連續性時,平滑處理和閾值處理兩者都要使用。
roberts、prewitt,sobel算子都是以一個或多個模板進行濾波,而未對圖像特性和噪聲內容採取防護措施。

接下來介紹一種最優的邊緣檢測方法:canny算子

●低錯誤率:標識出儘可能多的實際邊緣,同時儘可能地減少噪聲產生的誤報。
●高定位性:標識出的邊緣要與圖像中的實際邊緣儘可能接近。
●最小響應:圖像中的邊緣只能標識-一次,並且可能存在的圖像噪聲不應標
識爲邊緣。

canny算子計算過程

描述
Opencv庫函數調用方法:

void Canny (InputArray image , OutputArray edges, double threshold1,
double threshold2 , 兩個閾值較小的用於邊緣連接,較大的用於控制強邊緣的初始端,一般比例控制在3:1或者2:1
int apertureSize=3, sobel核大小
bool L2gradient=false )

int main()
{
	// Read image 讀取圖像
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_GREEN);		//字體爲綠色
	//載入原圖
	Mat srcImage = imread("D:\\opencv_picture_test\\形態學操作\\coin_inv.png",0);	//讀取灰度圖
	//判斷圖像是否加載成功
	if (srcImage.empty())
	{
		cout << "圖像加載失敗!" << endl;
		return -1;
	}
	else
		cout << "圖像加載成功!" << endl << endl;
	Mat dstImage;
	Canny(srcImage,dstImage,100,33,3,false);

	imshow("srcImage", srcImage);

	imshow("整體", dstImage);
	waitKey(0);
	return 0;
}

效果:
效果
經過ImageWatch放大,可以發現,邊緣只有一格
放大
總的看來,canny算子確實具有優越性。

laplace計算過程

1
3*3孔徑的模板:
模板
opencv庫函數調用:
參數


int main()
{
	// Read image 讀取圖像
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_GREEN);		//字體爲綠色
	//載入原圖
	Mat srcImage = imread("D:\\opencv_picture_test\\形態學操作\\coin_inv.png", 0);	//讀取灰度圖
	//判斷圖像是否加載成功
	if (srcImage.empty())
	{
		cout << "圖像加載失敗!" << endl;
		return -1;
	}
	else
		cout << "圖像加載成功!" << endl << endl;
	Mat dstImage,abs_dst;
	GaussianBlur(srcImage,srcImage,Size(3,3),0);	//高斯模糊
	Laplacian(srcImage,dstImage,CV_16S,3,1,0);
	convertScaleAbs(dstImage, abs_dst);
	imshow("srcImage", srcImage);

	imshow("整體", dstImage);
	waitKey(0);
	return 0;
}

在這裏插入圖片描述

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