日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

《OpenCV3编程入门》学习笔记7 图像变换(一)基于OpenCV的边缘检测

發布時間:2023/11/27 生活经验 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 《OpenCV3编程入门》学习笔记7 图像变换(一)基于OpenCV的边缘检测 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

第7章 圖像變換

7.1 基于OpenCV的邊緣檢測

7.1.1 邊緣檢測的一般步驟

1.濾波:邊緣檢測算法主要基于圖像強度的一階和二階導數,導數對噪聲敏感,所以要濾波
2.增強:確定圖像各點鄰域強度的變化值,將有顯著變化的點凸顯,可通過計算梯度幅值確定
3.檢測:某些特定應用中梯度值較大點不為邊緣點,通過閾值化方法檢測進行取舍

7.1.2 canny算子

1.主要評價標準:
(1)低錯誤率:減少噪聲誤報
(2)高定位性:接近實際邊緣
(3)最小響應:邊緣只標識一次
2.步驟:
(1)消除噪聲:高斯濾波
(2)計算梯度幅值和方向
??1)運用一對卷積陣列分別作用于x和y方向
????????
??2)計算梯度幅值和方向(按照Sobel濾波器步驟進行)
?????????????
(3)非極大值抑制:排除非邊緣像素,僅保留一些細線條
(4)滯后閾值:高閾值和低閾值(推薦高低閾值比2:1到3:1)
??1)像素幅值超過高閾值,保留為邊緣像素
??2)像素幅值小于低閾值,排除
??3)像素幅值在高低之間,該像素連接到一個高于高閾值的像素時被保留
3.函數:Canny()函數
4.函數原型:

void Canny(InputArray image, OutputArray edges, double threshold1, double threshold2, int apertureSize=3, bool L2gradient=false)

5.參數說明:
(1)輸入圖像
(2)輸出的邊緣圖
(3)第一個滯后性閾值,較小值用于邊緣連接
(4)第二個滯后性閾值,較大值用于控制強邊緣初始段
(5)應用Sobel算子的孔徑大小,默認值3
(6)計算圖像梯度幅值的標識,默認false
6.調用示例:

//將原圖轉成灰度圖,降噪,用canny,將邊緣圖作為掩??截惖叫Ч麍D上,得到彩色邊緣圖
#include<opencv2/opencv.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
using namespace cv;
int main()
{//載入原圖Mat srcImage = imread("love.jpg");imshow("【原始圖】", srcImage);Mat edgeImage, grayImage,dstImage;//【1】創建與src同類型和大小矩陣dstImage.create(srcImage.size(), srcImage.type());//【2】將原圖轉為灰度圖cvtColor(srcImage, grayImage, COLOR_BGR2GRAY);//【3】使用3*3內核降噪blur(grayImage, edgeImage, Size(3, 3));//【4】運行canny算子Canny(edgeImage, edgeImage, 3, 9, 3);//【5】將dstImage中所有元素設為0dstImage = Scalar::all(0);//【6】使用Canny算子輸出的邊緣圖作為掩碼將原圖拷到目標圖srcImage.copyTo(dstImage, edgeImage);//【7】顯示效果圖imshow("【效果圖】Canny邊緣檢測", dstImage);waitKey(0);return 0;
}

運行效果:

7.1.3 sobel算子

1.主要用于邊緣檢測的離散微分算子(discrete differentiation operator),結合高斯平滑和微分求導,計算圖像灰度函數的近似梯度
2.計算過程:
(1)分別在x和y兩個方向求導
水平:圖像I與奇數大小的內核進行卷積,如內核大小為3:
????????????????
垂直:圖像I與奇數大小的內核進行卷積,如內核大小為3:
????????????????
(2)在圖像每一點,結合以上兩個結果求出近似梯度
??????????????或
3.函數:Sobel()函數
4.函數原型:

void Sobel(InputArray src, OutputArray dst, int ddepth, int dx, int dy, int ksize=3, double scale=1, double delta=0, int borderType=BORDER_DEFAULT)

5.參數說明:
(1)輸入圖像
(2)目標圖像
(3)輸出圖像深度,支持src.depth()和ddepth的組合:
????
(4)x方向的差分階數
(5)y方向的差分階數
(6)Sobel核大小,取值:1、3(默認)、5、7,取值為1時一般使用3*1或1*3內核
???內核大小為3時,Sobel內核可能有明顯誤差,Scharr函數更精確,內核為:
????????????
(7)計算導數時可選的縮放因子,默認1(無縮放)
(8)在結果存入目標圖之前可選的delta值,默認0
(9)邊界模式,默認BORDER_DEFAULT

使用sobel()函數時,取【xorder=1,yorder=0,ksize=3】計算圖像X方向導數,取【xorder=0,yorder=1,ksize=3】計算圖像Y方向導數

6.調用示例:

#include<opencv2/opencv.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
using namespace cv;
int main()
{//【0】創建grad_x和grad_y矩陣Mat grad_x, grad_y;Mat abs_grad_x, abs_grad_y, dstImage;//【1】載入原圖Mat srcImage = imread("love.jpg");//【2】顯示原圖imshow("【原始圖】sobel邊緣檢測", srcImage);//【3】求X方向梯度Sobel(srcImage, grad_x, CV_16S, 1, 0, 3, 1, 1, BORDER_DEFAULT);convertScaleAbs(grad_x, abs_grad_x);imshow("【效果圖】x方向Sobel", abs_grad_x);//【4】求Y方向梯度Sobel(srcImage, grad_y, CV_16S, 0, 1, 3, 1, 1, BORDER_DEFAULT);convertScaleAbs(grad_y, abs_grad_y);imshow("【效果圖】y方向Sobel", abs_grad_y);//【5】合并梯度(近似)addWeighted(abs_grad_x, 0.5, abs_grad_y, 0.5, 0, dstImage, -1);//【6】顯示效果圖imshow("【效果圖】整體方向Sobel", dstImage);waitKey(0);return 0;
}

運行效果:

7.1.4 Laplacian算子

1.二階導數可以用來檢測邊緣, Laplacian算子是n維歐幾里得空間中的一個二階微分算子,定義為梯度grad的散度div,一幅圖像減去它的Laplacian算子可以增強對比度
2.如果f是二階可微的實函數,則f的拉普拉斯算子定義為笛卡爾坐標系xi中的所有非混合二階偏導數求和:
????????????????
3.函數:Laplacian()函數
4.函數原型:

void Laplacian(InputArray src, OutputArray dst, int ddepth, int ksize=1 , double scale=1, double delta=0, int borderType=BORDER_DEFAULT)

5.參數說明:
(1)輸入圖像
(2)輸出的邊緣圖
(3)輸出圖像深度
(4)計算二階導數的濾波器的孔徑尺寸,大小必須為正奇數,默認1
(5)計算拉普拉斯值得時候可選的比例因子,默認1
(6)在結果存入目標圖之前可選的delta值,默認0
(7)邊界模式,默認BORDER_DEFAULT
6.函數主要利用sobel算子的運算,通過加上sobel算子運算的圖像x方向和y方向上的導數,來得到載入圖像的拉普拉斯變換,sobel算子如下:
????????????????
ksize=1時,Laplacian()函數采用3*3孔徑:
??????????????????
7.調用示例:

#include<opencv2/opencv.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
using namespace cv;
int main()
{//【0】變量定義Mat srcImage, grayImage, dstImage, abs_dstImage;//【1】載入原圖srcImage = imread("love.jpg");//【2】顯示原圖imshow("【原始圖】圖像Laplace變換", srcImage);//【3】使用高斯濾波消除噪聲GaussianBlur(srcImage, srcImage, Size(3, 3), 0, 0, BORDER_DEFAULT);//【4】轉換為灰度圖cvtColor(srcImage, grayImage, COLOR_BGR2GRAY);//【5】使用Laplace函數Laplacian(grayImage, dstImage, CV_16S, 3, 1, 0, BORDER_DEFAULT);//【6】計算絕對值,將結果轉換成8位convertScaleAbs(dstImage, abs_dstImage);//【7】顯示效果圖imshow("【效果圖】圖像Laplacian變換", abs_dstImage);waitKey(0);return 0;
}

運行效果:

7.1.5 scharr濾波器

1.計算圖像差分:Scharr()函數,與Sobel基本一樣,沒有ksize核大小:

Scharr(src,dst,ddepth,dx,dy,scale,delta,broderType)

=
Sobel(src,dst,ddepth,dx,dy,CV_SCHARR,scale,delta,borderType)

2.調用示例:

#include<opencv2/opencv.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
using namespace cv;
int main()
{//創建grad_x和grad_y矩陣Mat grad_x, grad_y;Mat abs_grad_x, abs_grad_y, dstImage;//載入原圖Mat srcImage = imread("love.jpg");//顯示原圖imshow("【原始圖】Scharr濾波器", srcImage);//求x方向梯度Scharr(srcImage, grad_x, CV_16S, 1, 0, 1, 0, BORDER_DEFAULT);convertScaleAbs(grad_x, abs_grad_x);imshow("【效果圖】X方向Scharr", abs_grad_x);//求y方向梯度Scharr(srcImage, grad_y, CV_16S, 0, 1, 1, 0, BORDER_DEFAULT);convertScaleAbs(grad_y, abs_grad_y);imshow("【效果圖】Y方向Scharr", abs_grad_y);//合并梯度(近似)addWeighted(abs_grad_x, 0.5, abs_grad_y, 0.5, 0, dstImage);//顯示效果圖imshow("【效果圖】合并梯度后Scharr", dstImage);waitKey(0);return 0;
}

運行結果:

7.1.6 綜合示例

/*
效果:實現canny邊緣檢測,滑動條控制閾值實現Sobel邊緣檢測,滑動條控制內核大小實現Scharr濾波器
*/
#include<opencv2/opencv.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
using namespace cv;
//全局變量
Mat g_srcImage, g_grayImage, g_dstImage;
//Canny邊緣檢測相關變量
Mat g_cannyDetectedEdges;
int g_cannyLowThreshold = 1;//Trackbar位置參數
//Sobel邊緣檢測相關變量
Mat g_sobelGradient_X, g_sobelGradient_Y;
Mat g_sobelAbsGradient_X, g_sobelAbsGradient_Y;
int g_sobelKernelSize = 1;//Trackbar位置參數
//Scharr濾波器相關變量
Mat g_scharrGradient_X, g_scharrGradient_Y;
Mat g_scharrAbsGradient_X, g_scharrAbsGradient_Y;
//全局函數
static void on_Canny(int, void*);//canny邊緣檢測窗口滾動條回調函數
static void on_Sobel(int, void*);//Sobel邊緣檢測窗口滾動條回調函數
void Scharr();//封裝了Scharr邊緣檢測相關代碼的函數
int main()
{//改變console字體顏色system("color 2F");//載入原圖g_srcImage = imread("girl.jpg");if (!g_srcImage.data){printf("載入原圖失敗~!\n");return false;}//顯示原圖namedWindow("【原始圖】");imshow("【原始圖】", g_srcImage);//創建與src同類型和大小的矩陣g_dstImage.create(g_srcImage.size(), g_srcImage.type());//將原圖轉換為灰度圖cvtColor(g_srcImage, g_grayImage, COLOR_BGR2GRAY);//創建顯示窗口namedWindow("【效果圖】Canny邊緣檢測", WINDOW_AUTOSIZE);namedWindow("【效果圖】Sobel邊緣檢測", WINDOW_AUTOSIZE);namedWindow("【效果圖】Scharr濾波器", WINDOW_AUTOSIZE);//創建滑動條createTrackbar("參數值", "【效果圖】Canny邊緣檢測", &g_cannyLowThreshold, 120, on_Canny);createTrackbar("參數值", "【效果圖】Sobel邊緣檢測", &g_sobelKernelSize, 3, on_Sobel);//調用回調函數on_Canny(g_cannyLowThreshold, 0);on_Sobel(g_sobelKernelSize, 0);//調用封裝了Scharr邊緣檢測代碼的函數Scharr();while ((char)waitKey(1) != 27) {}return 0;
}
//canny邊緣檢測窗口滾動條回調函數
static void on_Canny(int, void*)
{//3*3內核降噪blur(g_grayImage, g_cannyDetectedEdges, Size(3, 3));//運行Canny算子Canny(g_cannyDetectedEdges, g_cannyDetectedEdges, g_cannyLowThreshold, g_cannyLowThreshold * 3, 3);//將g_dstImage內所有元素設為0g_dstImage = Scalar::all(0);//使用Canny算子輸出的邊緣圖g_cannyDetectedEdges作為掩模,將原圖拷貝到目標圖g_srcImage.copyTo(g_dstImage, g_cannyDetectedEdges);//顯示效果圖imshow("【效果圖】Canny邊緣檢測", g_dstImage);
}
static void on_Sobel(int, void*)
{//求X方向梯度Sobel(g_srcImage, g_sobelGradient_X, CV_16S, 1, 0, 2*g_sobelKernelSize+1, 1, 1, BORDER_DEFAULT);convertScaleAbs(g_sobelGradient_X, g_sobelAbsGradient_X);//求Y方向梯度Sobel(g_srcImage, g_sobelGradient_Y, CV_16S, 0, 1, 2*g_sobelKernelSize+1, 1, 1, BORDER_DEFAULT);convertScaleAbs(g_sobelGradient_Y, g_sobelAbsGradient_Y);//合并梯度addWeighted(g_sobelAbsGradient_X, 0.5, g_sobelAbsGradient_Y, 0.5, 0, g_dstImage);//顯示效果圖imshow("【效果圖】Sobel邊緣檢測", g_dstImage);
}
void Scharr()
{//求X方向梯度Scharr(g_srcImage, g_scharrGradient_X, CV_16S, 1, 0, 1, 0, BORDER_DEFAULT);convertScaleAbs(g_scharrGradient_X, g_scharrAbsGradient_X);//求Y方向梯度Scharr(g_srcImage, g_scharrGradient_Y, CV_16S, 0, 1, 1, 0, BORDER_DEFAULT);convertScaleAbs(g_scharrGradient_Y, g_scharrAbsGradient_Y);//合并梯度addWeighted(g_scharrAbsGradient_X, 0.5, g_scharrAbsGradient_Y, 0.5, 0, g_dstImage);//顯示效果圖imshow("【效果圖】Scharr濾波器", g_dstImage);
}

運行效果:



總結

以上是生活随笔為你收集整理的《OpenCV3编程入门》学习笔记7 图像变换(一)基于OpenCV的边缘检测的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。