形態學,即數學形態學(Mathematical Morphology),是圖像處理中應用最為廣泛的技術之一,主要用於從圖像中提取對表達和描繪區域形狀有意義的圖像分量,使后續的識別工作能夠抓住目標對象最為本質(最具區分能力 - most discriminative)的形狀特征,如邊界和連通區域等。同時像細化、像素化和修剪毛刺等技術也常應用於圖像的預處理和后處理中,成為圖像增強技術的有力補充。


clc; clear all; close all; RGB = imread('test.png'); %讀圖 [ROW,COL, DIM] = size(RGB); %得到圖像行列數 %------------------------------< Erode >----------------------------------- Erode_img = zeros(ROW,COL); for r = 2:ROW-1 for c = 2:COL-1 and1 = bitand(RGB(r-1, c-1), bitand(RGB(r-1, c), RGB(r-1, c+1))); and2 = bitand(RGB( r, c-1), bitand(RGB( r, c), RGB( r, c+1))); and3 = bitand(RGB(r+1, c-1), bitand(RGB(r+1, c), RGB(r+1, c+1))); Erode_img(r, c) = bitand(and1, bitand(and2, and3)); end end %------------------------------< Dilate >---------------------------------- Dilate_img = zeros(ROW,COL); for r = 2:ROW-1 for c = 2:COL-1 or1 = bitor(RGB(r-1, c-1), bitor(RGB(r-1, c), RGB(r-1, c+1))); or2 = bitor(RGB( r, c-1), bitor(RGB( r, c), RGB( r, c+1))); or3 = bitor(RGB(r+1, c-1), bitor(RGB(r+1, c), RGB(r+1, c+1))); Dilate_img(r, c) = bitor(or1, bitor(or2, or3)); end end %------------------------------< show >------------------------------------ figure; imshow(RGB); title('原圖'); subplot(2,1,1); imshow(Erode_img); title('腐蝕'); subplot(2,1,2); imshow(Dilate_img);title('膨脹');
這次圖片選擇的就是一張二值圖片,原圖如下所示:
點擊運行,得到如下結果:
可以看到,腐蝕后,最細的白色線條消失了,其他圖案也都變得更細了,而膨脹后所有白色線條都變粗了。
(1)形成3x3矩陣
這個在前面的博客花了3篇來解釋,就不多說了,我把3x3矩陣的代碼用一個專門的 .v 文件寫好,這里直接調用即可。輸入是 16bi 的二值數據,輸出是矩陣數據。耗費 1 個時鍾周期。
//========================================================================== //== matrix_3x3_16bit,生成3x3矩陣,輸入和使能需對齊,耗費1clk //========================================================================== //--------------------------------------------------- 矩陣順序 // {matrix_11, matrix_12, matrix_13} // {matrix_21, matrix_22, matrix_23} // {matrix_31, matrix_32, matrix_33} //--------------------------------------------------- 模塊例化 matrix_3x3_16bit #( .COL (480 ), .ROW (272 ) ) u_matrix_3x3_16bit ( .clk (clk ), .rst_n (rst_n ), .din_vld (RGB_de ), .din (RGB_data ), .matrix_11 (matrix_11 ), .matrix_12 (matrix_12 ), .matrix_13 (matrix_13 ), .matrix_21 (matrix_21 ), .matrix_22 (matrix_22 ), .matrix_23 (matrix_23 ), .matrix_31 (matrix_31 ), .matrix_32 (matrix_32 ), .matrix_33 (matrix_33 ) );
(2)腐蝕
采用流水線方式,一級一級的運算,最后得到結果,耗費 2 個時鍾周期。
//========================================================================== //== 腐蝕,耗費2clk //========================================================================== //clk1,三行各自相與 //--------------------------------------------------- always @ (posedge clk or negedge rst_n)begin if(!rst_n)begin erode_1 <= 'd0; erode_2 <= 'd0; erode_3 <= 'd0; end else begin erode_1 <= matrix_11 && matrix_12 && matrix_13; erode_2 <= matrix_21 && matrix_22 && matrix_23; erode_3 <= matrix_31 && matrix_32 && matrix_33; end end //clk2,全部相與 //--------------------------------------------------- always @(posedge clk or negedge rst_n)begin if(!rst_n)begin erode <= 'd0; end else begin erode <= erode_1 && erode_2 && erode_3; end end //========================================================================== //== 腐蝕后的數據 //========================================================================== assign erode_data = erode ? 16'hffff : 16'h0000;
(3)信號同步
共耗費 3 個時鍾周期,相關信號延遲 3 拍。
//========================================================================== //== 信號同步 //========================================================================== always @(posedge clk or negedge rst_n) begin if(!rst_n) begin RGB_de_r <= 3'b0; RGB_hsync_r <= 3'b0; RGB_vsync_r <= 3'b0; end else begin RGB_de_r <= {RGB_de_r[1:0], RGB_de}; RGB_hsync_r <= {RGB_hsync_r[1:0], RGB_hsync}; RGB_vsync_r <= {RGB_vsync_r[1:0], RGB_vsync}; end end assign erode_de = RGB_de_r[2]; assign erode_hsync = RGB_hsync_r[2]; assign erode_vsync = RGB_vsync_r[2];
(1)形成3x3矩陣
這個在前面的博客花了3篇來解釋,就不多說了,我把3x3矩陣的代碼用一個專門的 .v 文件寫好,這里直接調用即可。輸入是 16bi 的二值數據,輸出是矩陣數據。耗費 1 個時鍾周期。
//========================================================================== //== matrix_3x3_16bit,生成3x3矩陣,輸入和使能需對齊,耗費1clk //========================================================================== //--------------------------------------------------- 矩陣順序 // {matrix_11, matrix_12, matrix_13} // {matrix_21, matrix_22, matrix_23} // {matrix_31, matrix_32, matrix_33} //--------------------------------------------------- 模塊例化 matrix_3x3_16bit #( .COL (480 ), .ROW (272 ) ) u_matrix_3x3_16bit ( .clk (clk ), .rst_n (rst_n ), .din_vld (RGB_de ), .din (RGB_data ), .matrix_11 (matrix_11 ), .matrix_12 (matrix_12 ), .matrix_13 (matrix_13 ), .matrix_21 (matrix_21 ), .matrix_22 (matrix_22 ), .matrix_23 (matrix_23 ), .matrix_31 (matrix_31 ), .matrix_32 (matrix_32 ), .matrix_33 (matrix_33 ) );
(2)膨脹
采用流水線方式,一級一級的運算,最后得到結果,耗費 2 個時鍾周期。
//========================================================================== //== 膨脹,耗費2clk //========================================================================== //clk1,三行各自相或 //--------------------------------------------------- always @ (posedge clk or negedge rst_n)begin if(!rst_n)begin dilate_1 <= 'd0; dilate_2 <= 'd0; dilate_3 <= 'd0; end else begin dilate_1 <= matrix_11 || matrix_12 || matrix_13; dilate_2 <= matrix_21 || matrix_22 || matrix_23; dilate_3 <= matrix_31 || matrix_32 || matrix_33; end end //clk2,全部相或 //--------------------------------------------------- always @(posedge clk or negedge rst_n)begin if(!rst_n)begin dilate <= 'd0; end else begin dilate <= dilate_1 || dilate_2 || dilate_3; end end //========================================================================== //== 膨脹后的數據 //========================================================================== assign dilate_data = dilate ? 16'hffff : 16'h0000;
(3)信號同步
共耗費 3 個時鍾周期,相關信號延遲 3 拍。
//========================================================================== //== 信號同步 //========================================================================== always @(posedge clk or negedge rst_n) begin if(!rst_n) begin RGB_de_r <= 3'b0; RGB_hsync_r <= 3'b0; RGB_vsync_r <= 3'b0; end else begin RGB_de_r <= {RGB_de_r[1:0], RGB_de}; RGB_hsync_r <= {RGB_hsync_r[1:0], RGB_hsync}; RGB_vsync_r <= {RGB_vsync_r[1:0], RGB_vsync}; end end assign dilate_de = RGB_de_r[2]; assign dilate_hsync = RGB_hsync_r[2]; assign dilate_vsync = RGB_vsync_r[2];



[1] OpenS Lee:FPGA開源工作室(公眾號)
[2] CrazyBingo:基於VIP_Board Mini的FPGA視頻圖像算法(HDL-VIP)開發教程-V1.6
[3] NingHechuan:FPGA圖像處理教程
[4] 牟新剛、周曉、鄭曉亮.基於FPGA的數字圖像處理原理及應用[M]. 電子工業出版社,2017.
[5] 張錚, 王艷平, 薛桂香. 數字圖像處理與機器視覺[M]. 人民郵電出版社, 2010.