1. 程式人生 > >學習OpenCV範例(十一)——影象的腐蝕與膨脹

學習OpenCV範例(十一)——影象的腐蝕與膨脹

這次範例相對比較簡單,是涉及到形態學操作的問題,原理也是比較簡單,學習起來比較輕鬆,大家看完這次的範例分析就可以明白到底影象的腐蝕和膨脹是怎麼回事了。

1、原理

簡單來講,形態學操作就是基於形狀的一系列影象處理操作。通過將 結構元素 作用於輸入影象來產生輸出影象。
最基本的形態學操作有二:腐蝕與膨脹(Erosion 與 Dilation)。 他們的運用廣泛:
消除噪聲
分割(isolate)獨立的影象元素,以及連線(join)相鄰的元素。
尋找影象中的明顯的極大值區域或極小值區域。
通過以下影象,我們簡要來討論一下膨脹與腐蝕操作,膨脹是取畫素值高的點,腐蝕相反,是取畫素值低的點。


                      圖1、原圖

①、膨脹

此操作將影象 A 與任意形狀的核心 (B),通常為正方形或圓形,進行卷積。
核心 B 有一個可定義的 錨點, 通常定義為核心中心點。
進行膨脹操作時,將核心 B 劃過影象,將核心 B 覆蓋區域的最大相素值提取,並代替錨點位置的相素。顯然,這一最大化操作將會導致影象中的亮區開始”擴充套件” (因此有了術語膨脹 dilation )。對上圖採用膨脹操作我們得到:

                圖2、膨脹圖片

與上面原圖比較,可以明顯的看到影象字母變粗了,膨脹了。

②、腐蝕

腐蝕在形態學操作家族裡是膨脹操作的孿生姐妹。它提取的是核心覆蓋下的相素最小值。
進行腐蝕操作時,將核心 B 劃過影象,將核心 B 覆蓋區域的最小相素值提取,並代替錨點位置的相素。
以與膨脹相同的影象作為樣本,我們使用腐蝕操作。如下圖:


                圖3、腐蝕圖片

與上面原圖比較,可以明顯的看到影象字母變細了,腐蝕了。

現在,我們編寫一些程式碼,在視窗中再加上trackbar控制元件對影象進行操作,這樣可以更直觀的看到影象的變化。

2、程式碼實現

#include "stdafx.h"

#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <stdlib.h>
#include <stdio.h>

using namespace cv;

/// 全域性變數
Mat src, erosion_dst, dilation_dst;

int erosion_elem = 0;
int erosion_size = 0;
int dilation_elem = 0;
int dilation_size = 0;
int const max_elem = 2;
int const max_kernel_size = 21;

/** Function Headers */
void Erosion( int, void* );
void Dilation( int, void* );

/** @function main */
int main( int argc, char** argv )
{
	/// Load 影象
	src = imread( "LinuxLogo.jpg" );

	if( !src.data )
	{ return -1; }

	/// 建立顯示視窗
	namedWindow( "Erosion Demo", CV_WINDOW_AUTOSIZE );
	namedWindow( "Dilation Demo", CV_WINDOW_AUTOSIZE );
	cvMoveWindow( "Dilation Demo", src.cols, 0 );

	/// 建立腐蝕 Trackbar
	createTrackbar( "Element:\n 0: Rect \n 1: Cross \n 2: Ellipse", "Erosion Demo",
		&erosion_elem, max_elem,
		Erosion );

	createTrackbar( "Kernel size:\n 2n +1", "Erosion Demo",
		&erosion_size, max_kernel_size,
		Erosion );

	/// 建立膨脹 Trackbar
	createTrackbar( "Element:\n 0: Rect \n 1: Cross \n 2: Ellipse", "Dilation Demo",
		&dilation_elem, max_elem,
		Dilation );

	createTrackbar( "Kernel size:\n 2n +1", "Dilation Demo",
		&dilation_size, max_kernel_size,
		Dilation );

	/// Default start
	Erosion( 0, 0 );
	Dilation( 0, 0 );

	waitKey(0);
	return 0;
}

/**  @function Erosion  */
void Erosion( int, void* )
{
	int erosion_type;
	if( erosion_elem == 0 ){ erosion_type = MORPH_RECT; }
	else if( erosion_elem == 1 ){ erosion_type = MORPH_CROSS; }
	else if( erosion_elem == 2) { erosion_type = MORPH_ELLIPSE; }

	Mat element = getStructuringElement( erosion_type,
		Size( 2*erosion_size + 1, 2*erosion_size+1 ),
		Point( erosion_size, erosion_size ) );

	/// 腐蝕操作
	erode( src, erosion_dst, element );
	imshow( "Erosion Demo", erosion_dst );
}

/** @function Dilation */
void Dilation( int, void* )
{
	int dilation_type;
	if( dilation_elem == 0 ){ dilation_type = MORPH_RECT; }
	else if( dilation_elem == 1 ){ dilation_type = MORPH_CROSS; }
	else if( dilation_elem == 2) { dilation_type = MORPH_ELLIPSE; }

	Mat element = getStructuringElement( dilation_type,
		Size( 2*dilation_size + 1, 2*dilation_size+1 ),
		Point( dilation_size, dilation_size ) );
	///膨脹操作
	dilate( src, dilation_dst, element );
	imshow( "Dilation Demo", dilation_dst );
}

3、執行結果


          圖4、原圖


         圖5、膨脹圖片


         圖6、腐蝕圖片

4、用到的類和函式

getStructuringElement:

功能:返回一個指定大小和形態的結構元素

結構:

Mat getStructuringElement(int shape, Size ksize, Point anchor=Point(-1,-1))
shape :核的型別
        MORPH_RECT:矩形,核的定義為:
        E_{ij}=1
      MORPH_ELLIPSE:橢圓
      MORPH_CROSS:交叉型,核的定義為:

      E_{ij} =  \fork{1}{if i=\texttt{anchor.y} or j=\texttt{anchor.x}}{0}{otherwise}
      CV_SHAPE_CUSTOM :自定義型別
ksize :核的大小
anchor :錨點 位置。不指定錨點位置,則預設錨點在核心中心位置。

dilate:

功能:影象膨脹

結構:

void dilate(InputArray src, OutputArray dst, InputArray element, Point anchor=Point(-1,-1), int iterations=1, int borderType=BORDER_CONSTANT, const Scalar& borderValue=morphologyDefaultBorderValue() )
src :源影象
dst :目標影象,和源影象有同樣的size和type
element :結構元素,可通過getStructuringElement,如果element=Mat(),那麼預設核為3*3的矩形結構
anchor: 錨點 位置。不指定錨點位置,則預設錨點在核心中心位置。
iterations :迭代次數
borderType :邊緣點插值型別
實現原理:

\texttt{dst} (x,y) =  \max _{(x',y'):  \, \texttt{element} (x',y') \ne0 } \texttt{src} (x+x',y+y')

函式支援(in-place)模式。膨脹可以重複進行 (iterations) 次. 對彩色影象,每個彩色通道單獨處理。

erode:

功能:腐蝕影象

結構:

void erode(InputArray src, OutputArray dst, InputArray element, Point anchor=Point(-1,-1), int iterations=1, int borderType=BORDER_CONSTANT, const Scalar& borderValue=morphologyDefaultBorderValue() )
src :源影象
dst :目標影象,和源影象有同樣的size和type
element :結構元素,可通過getStructuringElement,如果element=Mat(),那麼預設核為3*3的矩形結構
anchor: 錨點 位置。不指定錨點位置,則預設錨點在核心中心位置。
iterations :迭代次數
borderType :邊緣點插值型別
實現原理:

\texttt{dst} (x,y) =  \min _{(x',y'):  \, \texttt{element} (x',y') \ne0 } \texttt{src} (x+x',y+y')

函式支援(in-place)模式。膨脹可以重複進行 (iterations) 次. 對彩色影象,每個彩色通道單獨處理。

createTrackbar:

功能:建立trackbar並將它新增到指定的視窗

結構:

int createTrackbar(const string& trackbarname, const string& winname, int* value, int count, TrackbarCallback onChange=0, void* userdata=0)
trackbarname :被建立的trackbar名字
winname :視窗名字,這個視窗將為被建立trackbar的父物件
value :整數指標,它的值將反映滑塊的位置。這個變數指定建立時的滑塊位置
count :滑塊位置的最大值。最小值一直是0
onChange :每次滑塊位置被改變的時候,被呼叫函式的指標。這個函式應該被宣告為void Foo(int,void*);第一個引數是trackbar的位置,第二個引數是userdata,如果沒有回撥函式,這個值可以設為NULL。
userdata :回撥函式返回的資料,在沒有使用全域性變數的時候,可以通過它來處理trackbar事件
補充:

getTrackbarPos:

功能:獲取trackbar的位置,也即是value的位置

結構:

 int getTrackbarPos(const string& trackbarname, const string& winname)
trackbarname :trackbar的名字
winname :trackbar父視窗的名字

setTrackbarPos:

功能:設定trackbar位置,也即是value的位置

結構:

void setTrackbarPos(const string& trackbarname, const string& winname, int pos)
trackbarname :trackbar的名字
winname :trackbar父視窗的名字
pos :新的位置

相關推薦

學習OpenCV範例——影象腐蝕膨脹

這次範例相對比較簡單,是涉及到形態學操作的問題,原理也是比較簡單,學習起來比較輕鬆,大家看完這次的範例分析就可以明白到底影象的腐蝕和膨脹是怎麼回事了。 1、原理 簡單來講,形態學操作就是基於形狀的一系列影象處理操作。通過將 結構元素 作用於輸入影象來產生輸出影象。 最基本的

學習OpenCV範例——直方圖計算和均衡化

本次案例將為大家介紹直方圖計算和直方圖均衡化,直方圖的計算非常有用,在很多場合下都可以用上,不僅僅是在影象的灰度值上,還可能是在影象的其他特徵上;影象的均衡化在影象預處理時經常被用到,它可以增強對比度,使得畫素強度分佈範圍更廣。 1、原理 直方圖計算: 直方圖均衡化:

學習OpenCV範例——輪廓提取和形狀描述符

本範例主要介紹瞭如何提取輪廓和用一些形狀描述符對輪廓進行表述,輪廓提取函式涉及到的引數很多,沒有經常用到它的話,對引數的瞭解就不會太深刻,這裡也按照本人搜尋出來的一些資料進行總結,希望對大家有用。 1、程式碼實現 本程式碼實現了多個功能 建立了三個滑動條: 第一個滑動條表示

學習OpenCV範例——反向投影

本次要講的範例是反向投影,反向投影如果是按照字面上的理解,還有書本上的理解可能會比較困難,但是如果是舉一些具體的簡單的例子,那可能就比較容易接受了,應用的話,可以檢測出膚色區域,例如,你有一個膚色直方圖 ( Hue-Saturation 直方圖 ),你可以用它來尋找影象中的

學習OpenCV範例——sobel,laplace,canny的運用

本次範例將要學習關於邊緣提取,影象銳化的三個基本函式,風別是Sobel(),Laplacian(),Canny(),會從原理講起,再到程式碼實現,最後會貼出執行結果,進行三種結果的對比。 1、原理及計算 Sobel: 原理: 由上圖,你可以看到在 邊緣 ,相素值顯著的 改

學習OpenCV範例——霍夫變換

本次範例通過霍夫變換檢測直線和圓,講解霍夫線變換和霍夫圓變換的原理,程式碼實現,和演示結果,使用霍夫線變換之前, 首先要對影象進行邊緣檢測的處理,也即霍夫線變換的直接輸入只能是邊緣二值影象。而霍夫圓變換則只要輸入灰度影象即可,因為在霍夫圓變換的過程中已經用到了canny邊緣

深度學習基礎系列| Keras中影象增強技術詳解

  在深度學習中,資料短缺是我們經常面臨的一個問題,雖然現在有不少公開資料集,但跟大公司掌握的海量資料集相比,數量上仍然偏少,而某些特定領域的資料採集更是非常困難。根據之前的學習可知,資料量少帶來的最直接影響就是過擬合。那有沒有辦法在現有少量資料基礎上,降低或解決過擬合問題呢?    

學習OpenCV範例二十三—GMM前景檢測

前一篇部落格中有談論到混合高斯模型GMM,但是隻是在上面的一個小應用,可能沒有很徹底的分析,大部分讀者看起來有點吃力,那麼在這篇微博中就給大家分析一下GMM在前景檢測的原理以及在OpenCV中的運用,當然長篇大論的原理我還是不全部寫出來的,依舊會貼出其他高手的部落格,他們寫

Spark學習之路 SparkCore的調優之Spark內存模型

精準 規模 memory 此外 結構定義 申請 管理方式 存儲 內部 摘抄自:https://www.ibm.com/developerworks/cn/analytics/library/ba-cn-apache-spark-memory-management/index

Kubernetes學習之路之資源清單定義

map latest dem kubectl 服務發現 bject 均衡 ima limit 一、Kubernetes常用資源 以下列舉的內容都是 kubernetes 中的 Object,這些對象都可以在 yaml 文件中作為一種 API 類型來配置。 類別 名稱

Python學習之旅

Python基礎知識(10):函式(Ⅱ) 一、全域性變數和區域性變數 區域性變數:在函式內定義的變數,在函式內使用 全域性變數:在函式外定義的變數,在程式任何地方都可以使用 1、全域性變數與區域性變數同名 這時函式內部只調用區域性變數,如果要呼叫全域性變數需要在函式內加一句“global 同名變數”

影象處理影象分割(3)泛函能量LevelSet、snake分割

一、level set相關理論 基於水平集的影象分割演算法是一種進化版的Snake演算法,也是需要給定初始的輪廓曲線,然後根據泛函能量最小化,進行曲線演化。水平集的方法,用的是一種隱式函式的方法,這個演算法比較難理解,我一年前開始搞這個演算法的時候,雖然知道程式碼怎麼寫,但是它的原理推

Python3+OpenCV3影象處理—— 影象金字塔

簡介:影象金字塔是影象中多尺度表達的一種,最主要用於影象的分割,是一種以多解析度來解釋影象的有效但概念簡單的結構。簡單來說,影象金字塔就是用來進行影象縮放的。 進行影象縮放可以用影象金字塔,也可以使用resize函式進行縮放,後者效果更好。這裡只是對影象金字塔做一些簡單瞭解

【GANs學習筆記】DCGAN、ImprovedDCGAN

在這一部分我們開始探討generator與discriminator內部網路的結構,之前我們一直在探討二者在外部的連線方式和如何使用divergence能讓結果更好,而涉及到generator與discriminator本身時一直粗略地描述成神經網路,但其實,

Linux 學習之路:壓縮歸檔以及RAID

壓縮、解壓縮命令 壓縮格式:gz,bz2,xz,zip,Z 壓縮演算法不同,壓縮比(壓縮後的大小-壓縮前的大小/壓縮前的大小)可能也會不同。 compress:FILENAME.Z uncompress 只能壓縮檔案,預設會刪除原檔案保留壓縮後文件: gzip

Linux 學習之路:RAID和LVM

傳輸速度 Mb/8=MB 硬碟的介面: IDE(ATA):133Mbps 並行匯流排 SATA:300Mbps,600Mbps,6Gbps 序列匯流排 USB:USB3.0:480Mbps 序列匯流排 SCSI:Small Computer System Int

PHP學習練手

給指令碼傳值 1、方法一:利用HTML的隱藏輸入框型別 <input type="hidden" name="do" value="this" /> 在提交form表單時,$_POST[‘do’]將具有this這個值(假定表單使用POS

從零開始學習PYTHON3講義計算器升級啦

(內容需要,本講中再次使用了大量線上公式,如果因為轉帖網站不支援公式無法顯示的情況,歡迎訪問原始部落格。) 《從零開始PYTHON3》第十一講 第二講的時候,我們通過Python的互動模式來入門Python基本知識。當時把Python當成了一個計算器使用。隨後從第三講開始,一直到第十講,我們進入了程式

unity官方demo學習之Stealth角色移動

十一,角色移動 為char_ethan新增指令碼DonePlayerMovement using UnityEngine; using System.Collections; public class DonePlayerMovement : MonoBehaviour

Salesforce學習之路Aura元件屬性<aura:attribute />

 1. <aura:attribute />語法 Aura元件屬性類似與Apex中類的成員變數(或者說Java中類的成員變數)。他們是元件在特定的例項上設定的型別化欄位,可以使用表示式語法從元件的標記內引用他們。 語法:<aura:attribute name="**" type=