OpenCV(八)形态学操作3--形态学梯度实现轮廓分析(基本梯度、内部梯度、外部梯度、方向梯度X(Y))
目錄
?形態(tài)學(xué)梯度概述
一、基本梯度
1、原理?
2、代碼
3、效果
二、內(nèi)部梯度
1、原理?
2、代碼
?3、效果
三、外部梯度
1、原理?
2、代碼
3、效果
四、方向梯度
1、原理
2、二值化圖像(黑白)
?3、求X(Y)軸方向梯度
X軸:?
Y軸:
總代碼
參考資料:
?形態(tài)學(xué)梯度概述
作用:保留物體的邊緣輪廓,便于輪廓分析(突出高亮區(qū)域)
形態(tài)學(xué)梯度定義:????????G = I⊕S ? I!S
(其中G為輸出圖像,I為輸入圖像,S為卷積核函數(shù)。⊕為膨脹運(yùn)算,!為腐蝕運(yùn)算。
- 形態(tài)學(xué)梯度操作的輸出圖像像素值是在對應(yīng)結(jié)構(gòu)元素而非局部過渡區(qū)域所定義的領(lǐng)域中灰度級強(qiáng)度變化的最大值。
- 對二值圖像進(jìn)行形態(tài)學(xué)操作可以將團(tuán)塊(blob)的邊緣突出出來,可以用形態(tài)學(xué)梯度來保留物體的邊緣輪廓。
一、基本梯度
1、原理?
基本梯度 = 膨脹圖像 - 腐蝕圖像
基本梯度是用膨脹后的圖像減去腐蝕后的圖像得到差值圖像,稱為梯度圖像也是OpenCV中支持的計算形態(tài)學(xué)梯度的方法,而此方法得到梯度有被稱為基本梯度。
2、代碼
//基本梯度(膨脹-腐蝕)
void BasicGrad()
{//創(chuàng)建卷積核(結(jié)構(gòu)元)Mat kernel = getStructuringElement(MORPH_RECT, Size(15, 15), Point(-1, -1));//創(chuàng)建新圖像(膨脹、腐蝕)Mat dilate_output, erode_ouput;dilate(img, dilate_output, kernel, Point(-1, -1)); //膨脹erode(img, erode_ouput, kernel, Point(-1, -1)); //腐蝕//計算基本梯度subtract(dilate_output, erode_ouput, dst, Mat()); //膨脹-腐蝕// 膨脹 腐蝕 結(jié)果imshow("基本梯度", dst);
}
3、效果
二、內(nèi)部梯度
1、原理?
內(nèi)部梯度 = 原圖像 - 腐蝕圖像
內(nèi)部梯度是用原圖像減去腐蝕之后的圖像得到差值圖像。
2、代碼
//內(nèi)部梯度(原圖-腐蝕)
void InternalGrad()
{//創(chuàng)建卷積核(結(jié)構(gòu)元)Mat kernel = getStructuringElement(MORPH_RECT, Size(15, 15), Point(-1, -1));//創(chuàng)建新圖(腐蝕)Mat erode_ouput;erode(img, erode_ouput, kernel, Point(-1, -1)); //腐蝕//計算內(nèi)部梯度(原圖-腐蝕)subtract(img, erode_ouput, dst, Mat());imshow("內(nèi)部梯度", dst);
}
?3、效果
三、外部梯度
1、原理?
外部梯度 = 膨脹圖像 - 原圖像
外部梯度使用膨脹之后的圖像減去原來的圖像得到的差值圖像。
2、代碼
//外部梯度(膨脹-原圖)
void ExternalGrad()
{//創(chuàng)建卷積核(結(jié)構(gòu)元)Mat kernel = getStructuringElement(MORPH_RECT, Size(15, 15), Point(-1, -1));//創(chuàng)建新圖(膨脹)Mat dilate_output;dilate(img, dilate_output, kernel, Point(-1, -1)); //膨脹//計算外部梯度(膨脹-原圖)subtract(dilate_output, img, dst, Mat());imshow("外部梯度", dst);
}
3、效果
四、方向梯度
1、原理
方向梯度是使用X方向與Y方向的直線作為結(jié)構(gòu)元素之后得到圖像梯度。
用X方向直線做結(jié)構(gòu)元素分別膨脹與腐蝕之后得到圖像求差值之后稱為X方向梯度;
用Y方向直線做結(jié)構(gòu)元素分別膨脹與腐蝕之后得到圖像求差值之后稱為Y方向梯度。
2、二值化圖像(黑白)
開始計算方向梯度前,先把圖像二值化(黑白化)。
二值化步驟:
1、先把彩圖轉(zhuǎn)灰度圖
2、再把灰度圖轉(zhuǎn)黑白圖(二值化)
//圖像二值化
void ToBin()
{// 1、轉(zhuǎn)為灰度圖cvtColor(img, grayImage, COLOR_BGR2GRAY);// 2、將灰度圖二值化threshold(grayImage, binImg, 0, 255, THRESH_OTSU);
}
?3、求X(Y)軸方向梯度
X方向梯度 = X軸方向膨脹 - X軸方向腐蝕? ? ? ? (黑白圖像)
Y方向梯度 = Y軸方向膨脹 - Y軸方向腐蝕? ? ? ? (黑白圖像)
把黑白圖像分別沿X(Y)軸膨脹和腐蝕,最后求差值。
X軸:?
//X方向梯度(黑白圖:沿X軸方向膨脹 - 沿X方向腐蝕)
void XDirectGrad()
{//X方向梯度:使用X方向的直線作為結(jié)構(gòu)元素Mat X = getStructuringElement(MORPH_RECT, Size(img.cols / 32, 1)); //X向量:寬XX,高1Mat dilate_direct, erode_direct; //膨脹與腐蝕圖像Mat xDirectImg; //X方向梯度圖像// 1、圖像二值化ToBin();// 2、沿X軸方向分別膨脹和腐蝕dilate(binImg, dilate_direct, X); //沿X軸方向膨脹erode(binImg, erode_direct, X); //沿X軸方向腐蝕// 3、X 方向梯度:X軸方向膨脹 - X軸方向腐蝕subtract(dilate_direct, erode_direct, xDirectImg, Mat());imshow("X 方向梯度", xDirectImg);
}
Y軸:
//Y方向梯度(黑白圖:沿Y軸方向膨脹 - 沿Y方向腐蝕)
void YDirectGrad()
{//Y方向梯度:使用Y方向的直線作為結(jié)構(gòu)元素Mat Y = getStructuringElement(MORPH_RECT, Size(1, img.rows / 32)); //Y向量:寬1,高XXMat dilate_direct, erode_direct; //膨脹與腐蝕圖像Mat yDirectImg; //Y方向梯度圖像// 1、圖像二值化ToBin();// 2、沿Y軸方向分別膨脹和腐蝕dilate(binImg, dilate_direct, Y); //沿Y軸方向膨脹erode(binImg, erode_direct, Y); //沿Y軸方向腐蝕// 3、Y 方向梯度:Y軸方向膨脹 - Y軸方向腐蝕subtract(dilate_direct, erode_direct, yDirectImg, Mat());imshow("Y 方向梯度", yDirectImg);
}
總代碼
//形態(tài)學(xué)梯度(基本梯度、內(nèi)部梯度、外部梯度、方向梯度X(Y))
#include <iostream>
#include <opencv2/opencv.hpp>using namespace cv;
using namespace std;Mat img, dst;
Mat grayImage, binImg;//圖像初始化
void Image_Init()
{img = imread("Resource/test7.jpg");dst = Mat::zeros(img.size(), img.type());if (img.empty()){printf("圖像加載失敗");exit(0);}
}//基本梯度(膨脹-腐蝕)
void BasicGrad()
{//創(chuàng)建卷積核(結(jié)構(gòu)元)Mat kernel = getStructuringElement(MORPH_RECT, Size(15, 15), Point(-1, -1));//創(chuàng)建新圖像(膨脹、腐蝕)Mat dilate_output, erode_ouput;dilate(img, dilate_output, kernel, Point(-1, -1)); //膨脹erode(img, erode_ouput, kernel, Point(-1, -1)); //腐蝕//計算基本梯度subtract(dilate_output, erode_ouput, dst, Mat()); //膨脹-腐蝕// 膨脹 腐蝕 結(jié)果imshow("基本梯度", dst);
}//內(nèi)部梯度(原圖-腐蝕)
void InternalGrad()
{//創(chuàng)建卷積核(結(jié)構(gòu)元)Mat kernel = getStructuringElement(MORPH_RECT, Size(15, 15), Point(-1, -1));//創(chuàng)建新圖(腐蝕)Mat erode_ouput;erode(img, erode_ouput, kernel, Point(-1, -1)); //腐蝕//計算內(nèi)部梯度(原圖-腐蝕)subtract(img, erode_ouput, dst, Mat());imshow("內(nèi)部梯度", dst);
}//外部梯度(膨脹-原圖)
void ExternalGrad()
{//創(chuàng)建卷積核(結(jié)構(gòu)元)Mat kernel = getStructuringElement(MORPH_RECT, Size(15, 15), Point(-1, -1));//創(chuàng)建新圖(膨脹)Mat dilate_output;dilate(img, dilate_output, kernel, Point(-1, -1)); //膨脹//計算外部梯度(膨脹-原圖)subtract(dilate_output, img, dst, Mat());imshow("外部梯度", dst);
}//圖像二值化
void ToBin()
{// 1、轉(zhuǎn)為灰度圖cvtColor(img, grayImage, COLOR_BGR2GRAY);// 2、將灰度圖二值化threshold(grayImage, binImg, 0, 255, THRESH_OTSU);
}//X方向梯度(黑白圖:沿X軸方向膨脹 - 沿X方向腐蝕)
void XDirectGrad()
{//X方向梯度:使用X方向的直線作為結(jié)構(gòu)元素Mat X = getStructuringElement(MORPH_RECT, Size(img.cols / 32, 1)); //X向量:寬XX,高1Mat dilate_direct, erode_direct; //膨脹與腐蝕圖像Mat xDirectImg; //X方向梯度圖像// 1、圖像二值化ToBin();// 2、沿X軸方向分別膨脹和腐蝕dilate(binImg, dilate_direct, X); //沿X軸方向膨脹erode(binImg, erode_direct, X); //沿X軸方向腐蝕// 3、X 方向梯度:X軸方向膨脹 - X軸方向腐蝕subtract(dilate_direct, erode_direct, xDirectImg, Mat());imshow("X 方向梯度", xDirectImg);
}//Y方向梯度(黑白圖:沿Y軸方向膨脹 - 沿Y方向腐蝕)
void YDirectGrad()
{//Y方向梯度:使用Y方向的直線作為結(jié)構(gòu)元素Mat Y = getStructuringElement(MORPH_RECT, Size(1, img.rows / 32)); //Y向量:寬1,高XXMat dilate_direct, erode_direct; //膨脹與腐蝕圖像Mat yDirectImg; //Y方向梯度圖像// 1、圖像二值化ToBin();// 2、沿Y軸方向分別膨脹和腐蝕dilate(binImg, dilate_direct, Y); //沿Y軸方向膨脹erode(binImg, erode_direct, Y); //沿Y軸方向腐蝕// 3、Y 方向梯度:Y軸方向膨脹 - Y軸方向腐蝕subtract(dilate_direct, erode_direct, yDirectImg, Mat());imshow("Y 方向梯度", yDirectImg);
}//顯示圖像
void Show()
{imshow("原圖", img);
}int main()
{Image_Init(); //圖像初始化BasicGrad(); //基本梯度InternalGrad(); //內(nèi)部梯度ExternalGrad(); //外部梯度XDirectGrad(); //X方向梯度YDirectGrad(); //Y方向梯度Show(); //顯示原圖像waitKey(0);return 0;
}
參考資料:
https://blog.csdn.net/sinat_36264666/article/details/78629600?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522162856242416780261952100%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=162856242416780261952100&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduend~default-2-78629600.pc_search_result_control_group&utm_term=%E5%BD%A2%E6%80%81%E5%AD%A6%E6%A2%AF%E5%BA%A6&spm=1018.2226.3001.4187
https://blog.csdn.net/weixin_41695564/article/details/79935028
https://blog.csdn.net/qq_41498261/article/details/103112661?ops_request_misc=&request_id=&biz_id=102&utm_term=%E5%BD%A2%E6%80%81%E5%AD%A6%E6%A2%AF%E5%BA%A6&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-7-.nonecase&spm=1018.2226.3001.4187
總結(jié)
以上是生活随笔為你收集整理的OpenCV(八)形态学操作3--形态学梯度实现轮廓分析(基本梯度、内部梯度、外部梯度、方向梯度X(Y))的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: OpenCV(基础补充)图像二值化
- 下一篇: 数据结构与算法(8-1)顺序表查找及优化