c/c++的opencv實現(xiàn)圖片膨脹
圖像膨脹 (Dilation) 是形態(tài)學(xué)圖像處理中的另一種基本操作,與腐蝕操作相對應(yīng)。它通常用于填充圖像中的小孔洞、連接斷開的物體部分、以及加粗二值圖像中的物體。本文將詳細介紹膨脹的原理,并演示如何使用 C++ 和 OpenCV 庫來實現(xiàn)圖像膨脹。
什么是圖像膨脹?
與腐蝕類似,圖像膨脹也是用一個特定的結(jié)構(gòu)元素(核)“探測”或“掃描”輸入圖像的過程。對于二值圖像,如果結(jié)構(gòu)元素下的至少一個像素為前景像素(通常為白色,值為1或255),則輸出圖像中結(jié)構(gòu)元素錨點對應(yīng)的像素就被置為前景像素。對于灰度圖像,輸出像素的值是結(jié)構(gòu)元素覆蓋區(qū)域內(nèi)所有像素的最大值。
簡單來說,膨脹操作會:
- 擴大 亮色區(qū)域(前景)。
- 縮小 暗色區(qū)域(背景)。
- 填充前景物體內(nèi)的小孔洞或斷裂。
其效果就像是用結(jié)構(gòu)元素“膨脹”或“擴張”前景物體的邊界。
結(jié)構(gòu)元素 (Kernel)
結(jié)構(gòu)元素在膨脹操作中的作用與在腐蝕操作中類似,它定義了操作的鄰域范圍和形狀。結(jié)構(gòu)元素的中心點通常被稱為“錨點”。OpenCV 提供了 cv::getStructuringElement()
函數(shù)來方便地創(chuàng)建常見的結(jié)構(gòu)元素。
常用的結(jié)構(gòu)元素形狀包括:
cv::MORPH_RECT
: 矩形cv::MORPH_ELLIPSE
: 橢圓形cv::MORPH_CROSS
: 十字形
// 創(chuàng)建一個 3x3 大小的矩形結(jié)構(gòu)元素 cv::Mat kernel_rect = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(3, 3)); // 創(chuàng)建一個 5x5 大小的橢圓形結(jié)構(gòu)元素 cv::Mat kernel_ellipse = cv::getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(5, 5)); // 創(chuàng)建一個 7x7 大小的十字形結(jié)構(gòu)元素 cv::Mat kernel_cross = cv::getStructuringElement(cv::MORPH_CROSS, cv::Size(7, 7));
結(jié)構(gòu)元素的大小和形狀對膨脹結(jié)果有顯著影響。
OpenCV 中的 cv::dilate() 函數(shù)
OpenCV 提供了 cv::dilate()
函數(shù)來實現(xiàn)圖像膨脹。
函數(shù)原型:
void cv::dilate( cv::InputArray src, // 輸入圖像 cv::OutputArray dst, // 輸出圖像 cv::InputArray kernel, // 用于膨脹的結(jié)構(gòu)元素 cv::Point anchor = cv::Point(-1,-1), // 結(jié)構(gòu)元素內(nèi)錨點的位置。默認值 (-1,-1) 表示錨點在核中心。 int iterations = 1, // 膨脹操作迭代次數(shù) int borderType = cv::BORDER_CONSTANT, // 像素外推方法 const cv::Scalar& borderValue = cv::morphologyDefaultBorderValue() //邊界不變時的邊界值 );
參數(shù)說明:
src
: 輸入圖像,可以是任意通道數(shù)的圖像,但深度應(yīng)為CV_8U
,CV_16U
,CV_16S
,CV_32F
或CV_64F
。dst
: 輸出圖像,與src
具有相同的大小和類型。kernel
: 結(jié)構(gòu)元素。如果傳入一個空的cv::Mat()
,則默認使用一個 3x3 的矩形核。anchor
: 錨點位置。默認值cv::Point(-1,-1)
表示錨點在結(jié)構(gòu)元素的中心。iterations
: 膨脹操作執(zhí)行的次數(shù)。多次迭代會使膨脹效果更明顯。borderType
: 用于推斷圖像外部像素的邊界模式。borderValue
: 當borderType
為cv::BORDER_CONSTANT
時使用的邊界值。
C++ 代碼示例
下面是一個完整的 C++ 示例,演示了如何加載圖像并對其進行膨脹操作:
#include <opencv2/opencv.hpp> #include <iostream> int main(int argc, char** argv) { // 1. 加載圖像 // 將 "your_image_path.png" 替換為你的圖像路徑 cv::Mat srcImage = cv::imread("your_image_path.png", cv::IMREAD_COLOR); // 或者 cv::IMREAD_GRAYSCALE 用于灰度圖 // 檢查圖像是否成功加載 if (srcImage.empty()) { std::cerr << "錯誤: 無法加載圖像!" << std::endl; return -1; } // 2. 創(chuàng)建膨脹后的輸出圖像 cv::Mat dilatedImage; // 3. 定義結(jié)構(gòu)元素 (核) // 嘗試不同的形狀和大小 // int dilation_size = 3; // 核大小,可以調(diào)整 // cv::Mat element = cv::getStructuringElement(cv::MORPH_RECT, // cv::Size(2 * dilation_size + 1, 2 * dilation_size + 1), // cv::Point(dilation_size, dilation_size)); // 使用一個簡單的 5x5 矩形核 cv::Mat element = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(5, 5)); // 你也可以嘗試: // cv::Mat element = cv::getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(5, 5)); // cv::Mat element = cv::getStructuringElement(cv::MORPH_CROSS, cv::Size(5, 5)); // 如果不指定核,OpenCV 會默認使用一個 3x3 的矩形核 // cv::Mat element; // 使用默認 3x3 核 // 4. 執(zhí)行膨脹操作 // 可以指定迭代次數(shù),例如 iterations = 2 int iterations = 1; cv::dilate(srcImage, dilatedImage, element, cv::Point(-1,-1), iterations); // 5. 顯示原始圖像和膨脹后的圖像 cv::imshow("原始圖像", srcImage); cv::imshow("膨脹后的圖像", dilatedImage); // 6. 等待用戶按鍵,然后關(guān)閉窗口 cv::waitKey(0); cv::destroyAllWindows(); return 0; }
編譯和運行說明 (以 g++ 為例):
g++ your_source_file.cpp -o dilate_example $(pkg-config --cflags --libs opencv4) ./dilate_example
(請確保你已安裝 OpenCV 并配置好 pkg-config,如果使用 OpenCV 3,將 opencv4
替換為 opencv
)
代碼解析
- #include <opencv2/opencv.hpp>: 包含了 OpenCV 的主要頭文件。
- cv::imread("your_image_path.png", cv::IMREAD_COLOR): 加載指定路徑的彩色圖像。你需要將 "your_image_path.png" 替換為實際的圖像文件路徑。對于二值化操作,通常先轉(zhuǎn)換為灰度圖再進行閾值化處理,然后進行膨脹。
- srcImage.empty(): 檢查圖像是否成功加載。
- cv::getStructuringElement(cv::MORPH_RECT, cv::Size(5, 5)): 創(chuàng)建一個 5x5 大小的矩形結(jié)構(gòu)元素。你可以修改形狀 (MORPH_ELLIPSE, MORPH_CROSS) 和大小 (cv::Size) 來觀察不同的效果。
- cv::dilate(srcImage, dilatedImage, element, cv::Point(-1,-1), iterations): 對 srcImage 應(yīng)用膨脹操作,使用 element 作為結(jié)構(gòu)元素,迭代 iterations 次,并將結(jié)果存儲在 dilatedImage 中。cv::Point(-1,-1) 表示錨點在核的中心。
- cv::imshow(): 顯示原始圖像和處理后的圖像。
- cv::waitKey(0): 等待用戶按下任意鍵。
- cv::destroyAllWindows(): 關(guān)閉所有 OpenCV 創(chuàng)建的窗口。
膨脹的效果和應(yīng)用場景
- 填充物體內(nèi)的小孔洞: 對于二值圖像中前景物體內(nèi)部的小黑色區(qū)域(“胡椒噪聲”中的“胡椒”點),膨脹操作可以有效填充。
- 連接斷開的物體部分: 如果物體的不同部分之間存在小的間隙,膨脹可以使它們連接起來。
- 加粗或增大物體: 使二值圖像中前景物體的尺寸變大,線條變粗。
- 平滑物體邊界: 可以使物體邊界更加平滑,填補一些小的凹陷。
- 在其他更復(fù)雜形態(tài)學(xué)操作(如閉運算、梯度計算)中作為基礎(chǔ)步驟。
可調(diào)整的參數(shù)及其影響
- 結(jié)構(gòu)元素的大小:
- 較小的結(jié)構(gòu)元素產(chǎn)生的膨脹效果較弱。
- 較大的結(jié)構(gòu)元素產(chǎn)生的膨脹效果較強,會更顯著地擴大物體或填充孔洞。
- 結(jié)構(gòu)元素的形狀:
- 不同的形狀會以不同的方式擴張物體。例如,水平線核會主要在水平方向上膨脹物體。
- 迭代次數(shù) (
iterations
):- 增加迭代次數(shù)會增強膨脹效果,多次小核迭代的效果類似于使用一個更大的結(jié)構(gòu)元素。
膨脹與腐蝕
膨脹和腐蝕是形態(tài)學(xué)操作中的一對對偶操作。
- 腐蝕會“收縮”或“細化”物體。
- 膨脹會“擴張”或“加粗”物體。
它們經(jīng)常組合使用:
- 開運算 (Opening): 先腐蝕后膨脹,可以用來去除小對象(噪聲)、平滑較大對象的輪廓以及斷開細的連接。
- 閉運算 (Closing): 先膨脹后腐蝕,可以用來填充小孔洞、連接鄰近的對象以及平滑較大對象的輪廓。
總結(jié)
圖像膨脹是形態(tài)學(xué)圖像處理中一個非常重要的工具,它通過擴展圖像中的亮區(qū)來達到填充孔洞、連接物體和加粗特征等目的。通過精心選擇結(jié)構(gòu)元素的形狀、大小以及迭代次數(shù),可以有效地控制膨脹操作的效果。OpenCV 的 cv::dilate()
函數(shù)為我們提供了一個簡單易用的接口來實現(xiàn)這一功能。希望本文能幫助你理解和應(yīng)用圖像膨脹技術(shù)。
到此這篇關(guān)于c/c++的opencv實現(xiàn)圖片膨脹的文章就介紹到這了,更多相關(guān)opencv 圖片膨脹內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C語言統(tǒng)計一篇英文短文中單詞的個數(shù)實例代碼
本文通過實例代碼給大家介紹的C語言統(tǒng)計一篇英文短文中單詞的個數(shù),代碼簡單易懂,非常不錯,具有參考借鑒價值,需要的朋友參考下吧2018-03-03c語言實現(xiàn)的貨物管理系統(tǒng)實例代碼(增加刪除 查找貨物信息等功能)
這篇文章主要介紹了c語言實現(xiàn)的貨物管理系統(tǒng),可增加刪除、查找貨物信息、顯示貨物信息、排序貨物銷量等操作,大家參考使用吧2013-11-11C++結(jié)構(gòu)體與類指針知識點總結(jié)
在本篇文章里小編給大家整理了關(guān)于C++結(jié)構(gòu)體與類指針知識點以及相關(guān)內(nèi)容,有興趣的朋友們參考學(xué)習(xí)下。2019-09-09C++中const、volatile、mutable使用方法小結(jié)
這篇文章主要介紹了C++中const、volatile、mutable使用方法小結(jié),需要的朋友可以參考下2020-01-01