************************************************************************************************ ************************************************************************************************ * 例程:detect_indent_fft.hdev * 1. 說明:這個程序展示了如何利用快速傅里葉變換(FFT)對塑料制品的表面進行目標(缺陷)的檢測,大致分為三步: * 2. 首先,我們用高斯濾波器構造一個合適的濾波器(將原圖通過高斯濾波器濾波); * 3. 然后,將原圖和構造的濾波器進行快速傅里葉變換; * 4. 最后,利用形態學算子將缺陷表示在濾波后的圖片上(在缺陷上畫圈)。 * 注:代碼中綠色部分為個人理解和注釋,其余為例程中原有代碼 * 算法講解:在實際的表面缺陷檢測系統中,針對的檢測表面很多是具有一定紋理的比如:布匹、皮革、塑料等, * 針對這一類表面的檢測就不能單純依靠幀差或者背景差來完成,因為背景的紋理不可能和當前圖像的 * 紋理完全相同。因此,本例程的算法通過將圖像變換到頻域進行處理,提取缺陷分量后反變換到時域, * 獲得缺陷的具體位置。 * 高斯濾波器:在本算法中,在一開始就構造了兩個高斯濾波器,高斯濾波器是一種線性平滑濾波器,適用於消除高斯噪聲。 * 濾波器的實質是對信號進行濾波,濾除不需要的部分,得到想要的部分。一個低通的濾波器可以濾除高頻信號, * 對於圖像來說,噪聲和邊緣往往集中在高頻分量,因此低通能夠降噪,但是也能造成圖像的模糊。 * 本文關鍵:本文的關鍵就是使用兩個低通濾波器,進行相減后構造了一個帶阻濾波器來提取缺陷分量。這就需要保證在實際 * 的待檢測表面中缺陷所處的頻率范圍要和背景以及噪聲有明顯的差異,並且帶阻的頻率選擇要合適。通過帶阻濾 * 波后獲得的頻率成分對背景中的紋理要有明顯的抑制,並且突出缺陷成分,進行傅里葉反變換后重構的圖像就是 * 缺陷圖像,經過簡單的分割就能很容易得到缺陷了。 *********************************************************************************************** *********************************************************************************************** ** Initialization(初始化) ********* dev_update_off(): 這一句包含如下三個算子: * dev_updata_pc(‘off’) 關閉更新程序計數器 * dev_updata_var(‘off’) 關閉更新變量窗口 * dev_updata_window(‘off’) 關閉更新圖像窗口(即通過命令來顯示想要在圖像窗口顯示的圖片) dev_update_off() ********* dev_close_window(): 關閉活動的圖像窗口 dev_close_window() * 參數說明:為讀入圖片命名(Image) * 文件名(’plastics/plastics_01’) read_image(Image,'plastics/plastics_01') * 參數說明:之前讀入或生成的圖片(Image) * 圖片的寬(Width) * 圖片的高(Height) get_image_size(Image,Width,Height) //獲取圖片的長寬; * 打開一個新的圖像窗口 * 參數說明:起始坐標(0,0) * 大小(Width,Height) * 背景顏色(’Black’) * 窗口句柄(WindowHandle) dev_open_window(0, 0, Width, Height, 'black', WindowHandle) *設置不依賴操作系統的字體 *參數說明:窗口句柄(WindowHandle) * 字體大小(14) * 字體類型(’mono’) * 是否黑體(’ture’) * 是否傾斜(’false’) set_display_font(WindowHandle, 14, 'mono', 'true', 'false') *定義區域填充模式 *參數說明:填充模式(’Margin'或者'Fill’) dev_set_draw ('margin') *設置輸出區域輪廓線的線寬 *可以修改參數來看最后缺陷區域標示的區別 dev_set_line_width(3) *設置一種或者多種輸出顏色 dev_set_color('red') *Optimize the fft speed for the specific image size(根據指定圖像大小進行fft速度最優化) *參數說明:圖片大小(Width,Height) * 優化模式(’standard’) optimize_rft_speed(Width,Height,'standard') //對指定大小的圖片的fft速度進行優化 *Construct a suitable filter by combining two Gaussian filters(結合兩個高斯濾波器構造一*個合適的濾波器) Sigma1 := 20.0 Sigma2 := 3.0 //定義兩個常量 * 如何知道缺陷的頻率范圍->選用適合的濾波器 * 1、 * 2、 * 3、 *在頻域生成兩個高斯濾波器 *參數說明: 生成的高斯濾波器(GaussFilter) * 空域中高斯在主方向上的標准差[Sigma1 >= 0] * 空域中高斯在正交於主方向的方向上的標准差[Sigma2 >= 0] * 濾波器主方向的角度[0.0] * 濾波器的規范['n', 'none' ] * 直流項在頻域的位置['dc_center', 'dc_edge', 'rft' ] * 圖片的大小(Width,Height) *高斯函數 高斯-平滑濾波器 無論在空間域還是在頻率域都是十分有效的低通濾波器 高斯函數具有五個十分重要的性質,它們是: * (1)二維高斯函數具有旋轉對稱性 ,即濾波器在各個方向上的平滑程度是相同的.一般來說,一幅圖像的邊緣方向是事先不知道的, * 因此,在濾波前是無法確定一個方向上比另一方向上需要更多的平滑.旋轉對稱性意味着高斯平滑濾波器在后續邊緣檢測 中不會偏向任一方向. * (2)高斯函數是單值函數.這表明,高斯濾波器用像素鄰域 的加權均值來代替該點的像素值,而每一鄰域像素點權值是隨該點與中心點的距離單調增減的. * 這一性質是很重要的,因為邊緣是一種圖像局部特征,如果平滑運算對離算子 中心很遠的像素點仍然有很大作用,則平滑運算會使圖像失真. * (3)高斯函數的付立葉變換頻譜 是單瓣的.正如下面所示,這一性質是高斯函數付立葉變換等於高斯函數本身這一事實的直接推論. * 圖像常被不希望的高頻信號 所污染(噪聲和細紋理 ).而所希望的圖像特征(如邊緣),既含有低頻分量,又含有高頻分量. * 高斯函數付立葉變換的單瓣意味着平滑圖像不會被不需要的高頻信號所污染,同時保留了大部分所需信號. * (4)高斯濾波器寬度(決定着平滑程度)是由參數σ表征的,而且σ和平滑程度的關系是非常簡單的.σ越大,高斯濾波器的頻帶 就越寬, * 平滑程度就越好.通過調節平滑程度參數σ,可在圖像特征過分模糊(過平滑)與平滑圖像中由於噪聲和細紋理所引起的過多的不希望突變量(欠平滑)之間取得折衷. * (5)由於高斯函數的可分離性,大高斯濾波器可以得以有效地實現.二維高斯函數卷積 可以分兩步來進行, * 首先將圖像與一維 高斯函數進行卷積,然后將卷積結果與方向垂直的相同一維高斯函數卷積.因此,二維高斯濾波的計算量隨濾波模板寬度成線性 增長而不是成平方增長. * 調節Sigma1和Sigma2,其中: * 1、調節Sigma1: * 2、調節Sigma1: * 3、調節Sigma1與調節Sigma2關系: gen_gauss_filter(GaussFilter1,Sigma1,Sigma1,0.0,'none','rft',Width,Height) gen_gauss_filter(GaussFilter2,Sigma2,Sigma2,0.0,'none','rft',Width,Height) *兩圖片相減(灰度) *sub_image(ImageMinuend, ImageSubtrahend : ImageSub : Mult, Add : ) *g' := (g1 - g2) * Mult + Add *以上為函數原型以及運算公式 sub_image(GaussFilter1,GaussFilter2,Filter,1,0) *Process the images iteratively(對圖像進行迭代運算) NumImages := 11 for Index := 1 to NumImages by 1 *Read an image and convert it to gray values read_image(Image,'plastics/plastics_'+Index$'02') *將原圖轉化為灰度圖,第一個參數為原圖 rgb1_to_gray(Image,Image) *Perform the convolution in the frequency domain *對計算一幅圖片實部進行快速傅里葉變換 *參數說明:輸入的圖片(Image) * 傅里葉變換后輸出的圖片(ImageFFT) * 變換方向(’to_freq'或'from_freq’) * 變換因子的規范(’none’) * 輸出圖片的數據類型(’complex’) * 圖片的寬(Width) rft_generic(Image,ImageFFT,'to_freq','none','complex',Width) *參數說明:輸入的圖片(ImageFFT) * 頻域濾波器(Filter) * 運算后輸出的結果 *對圖片用一個濾波器在頻域進行卷積運算 convol_fft(ImageFFT,Filter,ImageConvol) *對濾波后的圖片進行傅里葉反變換 rft_generic(ImageConvol,ImageFiltered,'from_freq','n','real',Width) *Process the filtered image *參數說明:輸入的圖片(ImageFiltered) * 輸出的灰度范圍圖(ImageResult) * 矩形掩膜大小(10,10) gray_range_rect(ImageFiltered,ImageResult,10,10)//用一個矩形掩膜計算像素點的灰度范圍 *判斷區域內灰度值的最大和最小值 * ???? min_max_gray *參數說明: * 待分析圖片區域(ImageResult) * 圖片(ImageResult) * 被去除的直方圖兩邊像素點所 * 占總像素數的百分比(0) * 得到的最小值最大值及灰度值范圍(Min,Max,Range) min_max_gray(ImageResult,ImageResult,0,Min,Max,Range) *利用全局閾值對圖像進行分割 *參數說明:輸入的圖片(ImageResult) * 分割后得到的區域(RegionDynThresh) * 閾值(max([5.55,Max*0.8]),255) * 公式:MinGray <= g <= MaxGray threshold(ImageResult,RegionDynThresh,max([5.55,Max*0.8]),255) *計算區域內的連通部分 *參數說明:輸入的圖片(RegionDynThresh) * 得到的連通區域(ConnectedRegions) connection(RegionDynThresh,ConnectedRegions) *根據指定的形態特征選擇區域 *參數說明:輸入的圖片(ConnectedRegions) * 滿足條件的區域(SelectedRegions) * 將要計算的形態特征(’area’) * 獨立特征間的連接關系(’and’) * 特征的最小限制(4) * 特征的最大限制(99999) select_shape(ConnectedRegions,SelectedRegions,'area','and',4,99999) *返回包含所有區域的集合 *參數說明:包含所有區域的待計算區域的圖片(tedRegions) * 所有輸入區域合(RegionUnion) union1(SelectedRegions,RegionUnion) *用一個圓圈來封閉一個區域 *參數說明:將要被封閉的區域(RegionUnion) * 被封閉的區域(RegionClosing) * 圓圈的半徑(10) closing_circle(RegionUnion,RegionClosing,10) connection(RegionClosing,ConnectedRegions1) select_shape(ConnectedRegions1,SelectedRegions1,'area','and',10,99999) * 計算區域的面積以及中心位置 *參數說明:待計算的區域(SelectedRegions1) * 區域的面積(Area) * 區域中心的行(Row) * 區域中心的列(Column) area_center(SelectedRegions1,Area,Row,Column) *Display the results dev_display(Image) //顯示原圖 Number := |Area| //將區域面積賦給Number用於后面檢查是否存在缺陷 if(Number) *構造一個與設定的圓弧或圓相一致的邊界 *參數說明:生成的邊界(ContCircle) * 圓弧或圓的中心坐標(Row,Cloumn) * 圓弧或圓的半徑(gen_tuple_const(Number,30)) * 圓弧或圓的起始角度(gen_tuple_const(Number,0)) * 圓弧或圓的結束角度(gen_tuple_const(Number,rad(360))) * 不明白是什么意思 * 相鄰兩點間的距離(1) gen_circle_contour_xld(ContCircle,Row,Column,gen_tuple_const(Number,30),gen_tuple_const(Number,0), gen_tuple_const(Number,rad(360)),'positive',1) ResultMessage := ['Not OK',Number + 'defect(s) found'] Color := ['red','black'] dev_display(ContCircle) else ResultMessage := 'OK' Color := 'forest green' endif disp_message(WindowHandle,ResultMessage,'window',12,12,Color,'true') if(Index#NumImages) disp_continue_message(WindowHandle,'black','true') stop() endif endfor
- ************************************************************************************************
- ************************************************************************************************
- * 例程:detect_indent_fft.hdev
- * 1. 說明:這個程序展示了如何利用快速傅里葉變換(FFT)對塑料制品的表面進行目標(缺陷)的檢測,大致分為三步:
- * 2. 首先,我們用高斯濾波器構造一個合適的濾波器(將原圖通過高斯濾波器濾波);
- * 3. 然后,將原圖和構造的濾波器進行快速傅里葉變換;
- * 4. 最后,利用形態學算子將缺陷表示在濾波后的圖片上(在缺陷上畫圈)。
- * 注:代碼中綠色部分為個人理解和注釋,其余為例程中原有代碼
- * 算法講解:在實際的表面缺陷檢測系統中,針對的檢測表面很多是具有一定紋理的比如:布匹、皮革、塑料等,
- * 針對這一類表面的檢測就不能單純依靠幀差或者背景差來完成,因為背景的紋理不可能和當前圖像的
- * 紋理完全相同。因此,本例程的算法通過將圖像變換到頻域進行處理,提取缺陷分量后反變換到時域,
- * 獲得缺陷的具體位置。
- * 高斯濾波器:在本算法中,在一開始就構造了兩個高斯濾波器,高斯濾波器是一種線性平滑濾波器,適用於消除高斯噪聲。
- * 濾波器的實質是對信號進行濾波,濾除不需要的部分,得到想要的部分。一個低通的濾波器可以濾除高頻信號,
- * 對於圖像來說,噪聲和邊緣往往集中在高頻分量,因此低通能夠降噪,但是也能造成圖像的模糊。
- * 本文關鍵:本文的關鍵就是使用兩個低通濾波器,進行相減后構造了一個帶阻濾波器來提取缺陷分量。這就需要保證在實際
- * 的待檢測表面中缺陷所處的頻率范圍要和背景以及噪聲有明顯的差異,並且帶阻的頻率選擇要合適。通過帶阻濾
- * 波后獲得的頻率成分對背景中的紋理要有明顯的抑制,並且突出缺陷成分,進行傅里葉反變換后重構的圖像就是
- * 缺陷圖像,經過簡單的分割就能很容易得到缺陷了。
- ***********************************************************************************************
- ***********************************************************************************************
- ** Initialization(初始化)
- ********* dev_update_off(): 這一句包含如下三個算子:
- * dev_updata_pc(‘off’) 關閉更新程序計數器
- * dev_updata_var(‘off’) 關閉更新變量窗口
- * dev_updata_window(‘off’) 關閉更新圖像窗口(即通過命令來顯示想要在圖像窗口顯示的圖片)
- dev_update_off()
- ********* dev_close_window(): 關閉活動的圖像窗口
- dev_close_window()
- * 參數說明:為讀入圖片命名(Image)
- * 文件名(’plastics/plastics_01’)
- read_image(Image,'plastics/plastics_01')
- * 參數說明:之前讀入或生成的圖片(Image)
- * 圖片的寬(Width)
- * 圖片的高(Height)
- get_image_size(Image,Width,Height) //獲取圖片的長寬;
- * 打開一個新的圖像窗口
- * 參數說明:起始坐標(0,0)
- * 大小(Width,Height)
- * 背景顏色(’Black’)
- * 窗口句柄(WindowHandle)
- dev_open_window(0, 0, Width, Height, 'black', WindowHandle)
- *設置不依賴操作系統的字體
- *參數說明:窗口句柄(WindowHandle)
- * 字體大小(14)
- * 字體類型(’mono’)
- * 是否黑體(’ture’)
- * 是否傾斜(’false’)
- set_display_font(WindowHandle, 14, 'mono', 'true', 'false')
- *定義區域填充模式
- *參數說明:填充模式(’Margin'或者'Fill’)
- dev_set_draw ('margin')
- *設置輸出區域輪廓線的線寬
- *可以修改參數來看最后缺陷區域標示的區別
- dev_set_line_width(3)
- *設置一種或者多種輸出顏色
- dev_set_color('red')
- *Optimize the fft speed for the specific image size(根據指定圖像大小進行fft速度最優化)
- *參數說明:圖片大小(Width,Height)
- * 優化模式(’standard’)
- optimize_rft_speed(Width,Height,'standard') //對指定大小的圖片的fft速度進行優化
- *Construct a suitable filter by combining two Gaussian filters(結合兩個高斯濾波器構造一*個合適的濾波器)
- Sigma1 := 20.0
- Sigma2 := 3.0 //定義兩個常量
- * 如何知道缺陷的頻率范圍->選用適合的濾波器
- * 1、
- * 2、
- * 3、
- *在頻域生成兩個高斯濾波器
- *參數說明: 生成的高斯濾波器(GaussFilter)
- * 空域中高斯在主方向上的標准差[Sigma1 >= 0]
- * 空域中高斯在正交於主方向的方向上的標准差[Sigma2 >= 0]
- * 濾波器主方向的角度[0.0]
- * 濾波器的規范['n', 'none' ]
- * 直流項在頻域的位置['dc_center', 'dc_edge', 'rft' ]
- * 圖片的大小(Width,Height)
- *高斯函數 高斯-平滑濾波器 無論在空間域還是在頻率域都是十分有效的低通濾波器 高斯函數具有五個十分重要的性質,它們是:
- * (1)二維高斯函數具有旋轉對稱性 ,即濾波器在各個方向上的平滑程度是相同的.一般來說,一幅圖像的邊緣方向是事先不知道的,
- * 因此,在濾波前是無法確定一個方向上比另一方向上需要更多的平滑.旋轉對稱性意味着高斯平滑濾波器在后續邊緣檢測 中不會偏向任一方向.
- * (2)高斯函數是單值函數.這表明,高斯濾波器用像素鄰域 的加權均值來代替該點的像素值,而每一鄰域像素點權值是隨該點與中心點的距離單調增減的.
- * 這一性質是很重要的,因為邊緣是一種圖像局部特征,如果平滑運算對離算子 中心很遠的像素點仍然有很大作用,則平滑運算會使圖像失真.
- * (3)高斯函數的付立葉變換頻譜 是單瓣的.正如下面所示,這一性質是高斯函數付立葉變換等於高斯函數本身這一事實的直接推論.
- * 圖像常被不希望的高頻信號 所污染(噪聲和細紋理 ).而所希望的圖像特征(如邊緣),既含有低頻分量,又含有高頻分量.
- * 高斯函數付立葉變換的單瓣意味着平滑圖像不會被不需要的高頻信號所污染,同時保留了大部分所需信號.
- * (4)高斯濾波器寬度(決定着平滑程度)是由參數σ表征的,而且σ和平滑程度的關系是非常簡單的.σ越大,高斯濾波器的頻帶 就越寬,
- * 平滑程度就越好.通過調節平滑程度參數σ,可在圖像特征過分模糊(過平滑)與平滑圖像中由於噪聲和細紋理所引起的過多的不希望突變量(欠平滑)之間取得折衷.
- * (5)由於高斯函數的可分離性,大高斯濾波器可以得以有效地實現.二維高斯函數卷積 可以分兩步來進行,
- * 首先將圖像與一維 高斯函數進行卷積,然后將卷積結果與方向垂直的相同一維高斯函數卷積.因此,二維高斯濾波的計算量隨濾波模板寬度成線性 增長而不是成平方增長.
- * 調節Sigma1和Sigma2,其中:
- * 1、調節Sigma1:
- * 2、調節Sigma1:
- * 3、調節Sigma1與調節Sigma2關系:
- gen_gauss_filter(GaussFilter1,Sigma1,Sigma1,0.0,'none','rft',Width,Height)
- gen_gauss_filter(GaussFilter2,Sigma2,Sigma2,0.0,'none','rft',Width,Height)
- *兩圖片相減(灰度)
- *sub_image(ImageMinuend, ImageSubtrahend : ImageSub : Mult, Add : )
- *g' := (g1 - g2) * Mult + Add
- *以上為函數原型以及運算公式
- sub_image(GaussFilter1,GaussFilter2,Filter,1,0)
- *Process the images iteratively(對圖像進行迭代運算)
- NumImages := 11
- for Index := 1 to NumImages by 1
- *Read an image and convert it to gray values
- read_image(Image,'plastics/plastics_'+Index$'02')
- *將原圖轉化為灰度圖,第一個參數為原圖
- rgb1_to_gray(Image,Image)
- *Perform the convolution in the frequency domain
- *對計算一幅圖片實部進行快速傅里葉變換
- *參數說明:輸入的圖片(Image)
- * 傅里葉變換后輸出的圖片(ImageFFT)
- * 變換方向(’to_freq'或'from_freq’)
- * 變換因子的規范(’none’)
- * 輸出圖片的數據類型(’complex’)
- * 圖片的寬(Width)
- rft_generic(Image,ImageFFT,'to_freq','none','complex',Width)
- *參數說明:輸入的圖片(ImageFFT)
- * 頻域濾波器(Filter)
- * 運算后輸出的結果
- *對圖片用一個濾波器在頻域進行卷積運算
- convol_fft(ImageFFT,Filter,ImageConvol)
- *對濾波后的圖片進行傅里葉反變換
- rft_generic(ImageConvol,ImageFiltered,'from_freq','n','real',Width)
- *Process the filtered image
- *參數說明:輸入的圖片(ImageFiltered)
- * 輸出的灰度范圍圖(ImageResult)
- * 矩形掩膜大小(10,10)
- gray_range_rect(ImageFiltered,ImageResult,10,10)//用一個矩形掩膜計算像素點的灰度范圍
- *判斷區域內灰度值的最大和最小值
- * ???? min_max_gray
- *參數說明:
- * 待分析圖片區域(ImageResult)
- * 圖片(ImageResult)
- * 被去除的直方圖兩邊像素點所
- * 占總像素數的百分比(0)
- * 得到的最小值最大值及灰度值范圍(Min,Max,Range)
- min_max_gray(ImageResult,ImageResult,0,Min,Max,Range)
- *利用全局閾值對圖像進行分割
- *參數說明:輸入的圖片(ImageResult)
- * 分割后得到的區域(RegionDynThresh)
- * 閾值(max([5.55,Max*0.8]),255)
- * 公式:MinGray <= g <= MaxGray
- threshold(ImageResult,RegionDynThresh,max([5.55,Max*0.8]),255)
- *計算區域內的連通部分
- *參數說明:輸入的圖片(RegionDynThresh)
- * 得到的連通區域(ConnectedRegions)
- connection(RegionDynThresh,ConnectedRegions)
- *根據指定的形態特征選擇區域
- *參數說明:輸入的圖片(ConnectedRegions)
- * 滿足條件的區域(SelectedRegions)
- * 將要計算的形態特征(’area’)
- * 獨立特征間的連接關系(’and’)
- * 特征的最小限制(4)
- * 特征的最大限制(99999)
- select_shape(ConnectedRegions,SelectedRegions,'area','and',4,99999)
- *返回包含所有區域的集合
- *參數說明:包含所有區域的待計算區域的圖片(tedRegions)
- * 所有輸入區域合(RegionUnion)
- union1(SelectedRegions,RegionUnion)
- *用一個圓圈來封閉一個區域
- *參數說明:將要被封閉的區域(RegionUnion)
- * 被封閉的區域(RegionClosing)
- * 圓圈的半徑(10)
- closing_circle(RegionUnion,RegionClosing,10)
- connection(RegionClosing,ConnectedRegions1)
- select_shape(ConnectedRegions1,SelectedRegions1,'area','and',10,99999)
- * 計算區域的面積以及中心位置
- *參數說明:待計算的區域(SelectedRegions1)
- * 區域的面積(Area)
- * 區域中心的行(Row)
- * 區域中心的列(Column)
- area_center(SelectedRegions1,Area,Row,Column)
- *Display the results
- dev_display(Image) //顯示原圖
- Number := |Area| //將區域面積賦給Number用於后面檢查是否存在缺陷
- if(Number)
- *構造一個與設定的圓弧或圓相一致的邊界
- *參數說明:生成的邊界(ContCircle)
- * 圓弧或圓的中心坐標(Row,Cloumn)
- * 圓弧或圓的半徑(gen_tuple_const(Number,30))
- * 圓弧或圓的起始角度(gen_tuple_const(Number,0))
- * 圓弧或圓的結束角度(gen_tuple_const(Number,rad(360)))
- * 不明白是什么意思
- * 相鄰兩點間的距離(1)
- gen_circle_contour_xld(ContCircle,Row,Column,gen_tuple_const(Number,30),gen_tuple_const(Number,0), gen_tuple_const(Number,rad(360)),'positive',1)
- ResultMessage := ['Not OK',Number + 'defect(s) found']
- Color := ['red','black']
- dev_display(ContCircle)
- else
- ResultMessage := 'OK'
- Color := 'forest green'
- endif
- disp_message(WindowHandle,ResultMessage,'window',12,12,Color,'true')
- if(Index#NumImages)
- disp_continue_message(WindowHandle,'black','true')
- stop()
- endif
- endfor