二、FPGA实时图像处理(灰度转换、高斯滤波、二值化和边缘检测)

1、框图①:整体框图②:图像处理模块框图

2、灰度转换模块3、高斯滤波模块4、二值化模块5、边缘检测模块6、图像处理模块7、顶层模块8、参数定义9、最终效果①:灰度转换②:二值化③:边缘检测

1、框图

①:整体框图

基于图像实时采集系统实现图像处理

②:图像处理模块框图

2、灰度转换模块

算法:采用精度为7的心理学公式:Gray = R0.299 + G0.587 + B0.114, Gray = R38 + G75 + B15 >> 7

/**************************************功能介绍***********************************

Copyright:

Date :

Author :厉长川

Version :2022.10.12 v1

Description:灰度转换模块

心理学公式:Gray = R*0.299 + G*0.587 + B*0.114, Gray = R*38 + G*75 + B*15 >> 7

*********************************************************************************/

module rgb2gray(

input clk ,//pclk

input rst_n ,//复位信号

input rgb_valid ,//rgb数据有效标志

input [15:0] rgb_din ,//rgb数据输入

output [7:0] gray_dout ,//灰度转换输出

output gray_valid //灰度转换数据有效标志

);

//中间信号定义

wire [7:0] r ;//rgb888

wire [7:0] g ;//rgb888

wire [7:0] b ;//rgb888

reg [2:0] valid_r ;//rgb数据有效标志打拍

reg [14:0] r_u ;//灰度转换运算寄存

reg [14:0] g_u ;//灰度转换运算寄存

reg [14:0] b_u ;//灰度转换运算寄存

reg [14:0] u_out ;//运算和寄存

//RGB565转RGB888:采用量化补偿的方式

assign r = {rgb_din[15:11], rgb_din[13:11]};

assign g = {rgb_din[10:5], rgb_din[6:5]};

assign b = {rgb_din[4:0], rgb_din[2:0]};

//valid_r:rgb数据有效标志打拍

always @(posedge clk or negedge rst_n)begin

if(!rst_n)begin

valid_r <= 2'b0;

end

else begin

valid_r <= {valid_r[1:0], rgb_valid};

end

end

//7位精度的灰度转换运算

always @(posedge clk or negedge rst_n)begin

if(!rst_n)begin

r_u <= 15'b0;

g_u <= 15'b0;

b_u <= 15'b0;

end

else if(valid_r[0])begin

r_u <= r*7'd38;

g_u <= g*7'd75;

b_u <= b*7'd15;

end

end

//u_out:运算和

always @(posedge clk or negedge rst_n)begin

if(!rst_n)begin

u_out <= 15'b0;

end

else if(valid_r[1])begin

u_out <= r_u + g_u + b_u;

end

end

//gray_dout:灰度转换结果

assign gray_dout = u_out[7 +:8];

//gray_valid:灰度转换完成标志

assign gray_valid = valid_r[2];

endmodule

3、高斯滤波模块

/**************************************功能介绍***********************************

Copyright:

Date :

Author :厉长川

Version :2022.10.13 v1

Description:高斯滤波模块

1 2 1

w = 1/16 * 2 4 2

1 2 1

*********************************************************************************/

module gus_filter(

input clk ,

input rst_n ,

input [7:0] gray_din ,

input gray_valid,

output reg [7:0] gus_dout ,

output gus_valid

);

//中间信号定义

wire [7:0] taps0 ;//shift输出数据

wire [7:0] taps1 ;//shift输出数据

wire [7:0] taps2 ;//shift输出数据

reg [7:0] taps0_1 ;//第一拍数据

reg [7:0] taps1_1 ;//第一拍数据

reg [7:0] taps2_1 ;//第一拍数据

reg [7:0] taps0_2 ;//第二拍数据

reg [7:0] taps1_2 ;//第二拍数据

reg [7:0] taps2_2 ;//第二拍数据

reg [10:0] sum_1 ;//第一行加权和

reg [11:0] sum_2 ;//第二行加权和

reg [10:0] sum_3 ;//第三行加权和

reg [3:0] valid_r ;//输入数据有效标志打四拍

//valid_r:输入数据有效标志打四拍

always @(posedge clk or negedge rst_n)begin

if(!rst_n)begin

valid_r <= 4'b0;

end

else begin

valid_r <= {valid_r[2:0], gray_valid};

end

end

//shift输出数据打拍

always @(posedge clk or negedge rst_n)begin

if(!rst_n)begin

taps0_1 <= 8'b0;

taps1_1 <= 8'b0;

taps2_1 <= 8'b0;

taps0_2 <= 8'b0;

taps1_2 <= 8'b0;

taps2_2 <= 8'b0;

end

else begin

taps0_1 <= taps0;

taps1_1 <= taps1;

taps2_1 <= taps2;

taps0_2 <= taps0_1;

taps1_2 <= taps1_1;

taps2_2 <= taps2_1;

end

end

//三行数据加权和计算

always @(posedge clk or negedge rst_n)begin

if(!rst_n)begin

sum_1 <= 11'b0;

sum_2 <= 12'b0;

sum_3 <= 11'b0;

end

else if(valid_r[1])begin

sum_1 <= taps0 + {taps0_1,1'b1} + taps0_2;

sum_2 <= {taps1,1'b1} + {taps1_1,2'b11} + {taps1_2,1'b1};

sum_3 <= taps2 + {taps2_1,1'b1} + taps2_2;

end

end

//最后结果输出

always @(posedge clk or negedge rst_n)begin

if(!rst_n)begin

gus_dout <= 8'b0;

end

else if(valid_r[2])begin

gus_dout <= (sum_1 + sum_2 + sum_3) >> 3'd4;

end

end

//高斯滤波数据有效标志

assign gus_valid = valid_r[3];

shift_gus shift_gus_inst (

.clken (gray_valid),

.clock (clk ),

.shiftin (gray_din ),

.shiftout ( ),

.taps0x (taps0 ),

.taps1x (taps1 ),

.taps2x (taps2 )

);

endmodule

4、二值化模块

/**************************************功能介绍***********************************

Copyright:

Date :

Author :厉长川

Version :2022.10.14 v2 简化算法

2022.10.13 v1

Description:二值化模块

*********************************************************************************/

`include "param.v"

module bin(

input clk ,//pclk

input rst_n ,//复位信号

input [7:0] gus_din ,//高斯滤波输入

input gus_valid ,//高斯滤波输入有效标志

output bin_dout ,//二值化输出

output bin_valid //二值化输出有效标志

);

//bin_dout:二值化输出

assign bin_dout = (gus_din > `BIN)?1'b1:1'b0;

//bin_valid:二值化输出有效标志

assign bin_valid = gus_valid;

endmodule

5、边缘检测模块

采用sobel算子进行边缘检测。

/**************************************功能介绍***********************************

Copyright:

Date :

Author :厉长川

Version :2022.10.13 v1

Description:边缘检测模块

-1 0 +1 +1 +2 +1

Gx = -2 0 +2 Gy = 0 0 0

-1 0 +1 -1 -2 -1

G = |Gx| + |Gy|;

*********************************************************************************/

`include "param.v"

module sobel(

input clk ,//pclk

input rst_n ,//复位信号

input bin_din ,//二值化输入

input bin_valid ,//二值化输入有效标志

output sobel_dout ,//边缘检测输出

output sobel_valid //边缘检测输出有效标志

);

//中间信号定义

wire taps0 ;//shift输出数据

wire taps1 ;//shift输出数据

wire taps2 ;//shift输出数据

reg taps0_1 ;//第一拍数据

reg taps1_1 ;//第一拍数据

reg taps2_1 ;//第一拍数据

reg taps0_2 ;//第二拍数据

reg taps1_2 ;//第二拍数据

reg taps2_2 ;//第二拍数据

reg [2:0] sumx_1 ;//x方向第一列

reg [2:0] sumx_3 ;//x方向第三列

reg [2:0] sumy_1 ;//y方向第一行

reg [2:0] sumy_3 ;//y方向第三行

reg [2:0] g_x ;//x方向梯度

reg [2:0] g_y ;//y方向梯度

reg [3:0] g ;//总梯度和

reg [4:0] valid_r ;//输入数据有效标志打四拍

//valid_r:输入数据有效标志打四拍

always @(posedge clk or negedge rst_n)begin

if(!rst_n)begin

valid_r <= 5'b0;

end

else begin

valid_r <= {valid_r[3:0], bin_valid};

end

end

//shift输出数据打拍

always @(posedge clk or negedge rst_n)begin

if(!rst_n)begin

taps0_1 <= 1'b0;

taps1_1 <= 1'b0;

taps2_1 <= 1'b0;

taps0_2 <= 1'b0;

taps1_2 <= 1'b0;

taps2_2 <= 1'b0;

end

else begin

taps0_1 <= taps0 ;

taps1_1 <= taps1 ;

taps2_1 <= taps2 ;

taps0_2 <= taps0_1;

taps1_2 <= taps1_1;

taps2_2 <= taps2_1;

end

end

//加权和

always @(posedge clk or negedge rst_n)begin

if(!rst_n)begin

sumx_1 <= 3'b0;

sumx_3 <= 3'b0;

sumy_1 <= 3'b0;

sumy_3 <= 3'b0;

end

else if(valid_r[1])begin

sumx_1 <= taps0 + {taps1 ,1'b1} + taps2;

sumx_3 <= taps0_2 + {taps1_2,1'b1} + taps2_2;

sumy_1 <= taps0 + {taps0_1,1'b1} + taps0_2;

sumy_3 <= taps2 + {taps2_1,1'b1} + taps2_2;

end

end

//x和y方向梯度

always @(posedge clk or negedge rst_n)begin

if(!rst_n)begin

g_x <= 3'b0;

g_y <= 3'b0;

end

else if(valid_r[2])begin

g_x <= (sumx_1 > sumx_3)?sumx_1 - sumx_3:sumx_3 - sumx_1;

g_y <= (sumy_1 > sumy_3)?sumy_1 - sumy_3:sumy_3 - sumy_1;

end

end

//g:总梯度和

always @(posedge clk or negedge rst_n)begin

if(!rst_n)begin

g <= 4'b0;

end

else if(valid_r[3])begin

g <= g_x + g_y;

end

end

//边缘检测结果

assign sobel_dout = (g > `SOBEL)?1'b1:1'b0;

//边缘检测数据有效标志

assign sobel_valid = valid_r[4];

shift_sobel shift_sobel_inst (

.clken ( bin_valid ),

.clock ( clk ),

.shiftin ( bin_din ),

.shiftout ( ),

.taps0x ( taps0 ),

.taps1x ( taps1 ),

.taps2x ( taps2 )

);

endmodule

6、图像处理模块

/**************************************功能介绍***********************************

Copyright:

Date :

Author :厉长川

Version :2022.10.13 v1

Description:图像数据处理模块

*********************************************************************************/

`include "param.v"

module process(

input clk ,//pclk

input rst_n ,//复位信号

input [15:0] rgb_din ,//rgb数据输入

input rgb_valid ,//rgb数据有效标志

output [15:0] pro_dout ,//处理完成输出

output pro_valid //处理完成输出有效标志

);

//中间信号定义

wire [7:0] gray_dout ;//灰度转换输出

wire gray_valid ;//灰度转换输出有效标志

wire [7:0] gus_dout ;//高斯滤波输出

wire gus_valid ;//高斯滤波输出有效标志

wire bin_dout ;//二值化输出

wire bin_valid ;//二值化输出有效标志

wire sobel_dout ;//边缘检测输出

wire sobel_valid;//边缘检测输出有效标志

//灰度转换模块

rgb2gray u_rgb2gray(

.clk (clk ),

.rst_n (rst_n ),

.rgb_valid (rgb_valid ),

.rgb_din (rgb_din ),

.gray_dout (gray_dout ),

.gray_valid (gray_valid )

);

//高斯滤波模块

gus_filter u_gus_filter(

.clk (clk ),

.rst_n (rst_n ),

.gray_din (gray_dout ),

.gray_valid (gray_valid ),

.gus_dout (gus_dout ),

.gus_valid (gus_valid )

);

//二值化模块

bin u_bin(

.clk (clk ),

.rst_n (rst_n ),

.gus_din (gus_dout ),

.gus_valid (gus_valid ),

.bin_dout (bin_dout ),

.bin_valid (bin_valid )

);

//边缘检测模块

sobel u_sobel(

.clk (clk ),

.rst_n (rst_n ),

.bin_din (bin_dout ),

.bin_valid (bin_valid ),

.sobel_dout (sobel_dout ),

.sobel_valid (sobel_valid )

);

//输出控制

`ifdef GRAY_OUT //输出灰度化图像

assign pro_dout = {gray_dout[7:3], gray_dout[7:2], gray_dout[7:3]};//灰度输出

assign pro_valid = gray_valid;//灰度输出有效标志

`endif

`ifdef GUS_OUT //输出高斯滤波图像

assign pro_dout = {gus_dout[7:3], gus_dout[7:2], gus_dout[7:3]};//高斯滤波输出

assign pro_valid = gus_valid;//高斯滤波输出有效标志

`endif

`ifdef BIN_OUT //输出二值化图像

assign pro_dout = {16{bin_dout}};//二值化输出

assign pro_valid = bin_valid;//二值化输出有效标志

`endif

`ifdef SOBEL_OUT//输出边缘检测图像

assign pro_dout = {16{sobel_dout}};//边缘检测输出

assign pro_valid = sobel_valid;//边缘检测输出有效标志

`endif

`ifdef NO_PRO //输出rgb图像

assign pro_dout = rgb_din;//rgb输出

assign pro_valid = rgb_valid;//rgb输出有效标志

`endif

endmodule

7、顶层模块

/**************************************功能介绍***********************************

Copyright:

Date :

Author :厉长川

Version :2022.10.10 v1

Description:顶层模块

*********************************************************************************/

module img_pro(

input clk ,//系统时钟50Mhz

input rst_n ,//复位信号,低电平有效

input [7:0] cmos_db ,//摄像头采集数据

input cmos_pclk ,//摄像头pclk时钟48MHz

input cmos_vsync ,//摄像头场同步信号

input cmos_href ,//摄像头行有效信号

output cmos_rst_n ,//摄像头复位信号

output cmos_xclk ,//摄像头xclk时钟24Mhz

output cmos_pwdn ,//摄像头掉电使能信号

output cmos_scl ,//摄像头配置时钟信号

inout cmos_sda ,//摄像头配置数据信号

output sdram_clk ,//sdram工作时钟

output sdram_cke ,//sdram使能

output [12:0] sdram_addr ,//sdram地址总线

output [1:0] sdram_ba ,//sdram bank地址

inout [15:0] sdram_dq ,//sdram数据总线

output [1:0] sdram_dqm ,//数据掩码

output [3:0] cmd ,//sdram操作命令

output vga_out_hs ,//vga行同步信号

output vga_out_vs ,//vga场同步信号

output [15:0] vga_dout //vga输出的RGB数据

);

//中间信号定义

wire vga_clk ;//vga时钟

wire clk_100MHz ;//100MHz工作时钟

wire done ;//摄像头配置完成标志

wire [15:0] pixel_dout ;//采集的像素数据

wire dout_valid ;//采集数据有效标志

wire [15:0] w_data ;//sdram写入数据

wire [15:0] r_data ;//sdram读出数据

wire [15:0] vga_din ;//vga输入数据

wire data_req ;//vga数据请求

wire [23:0] w_addr ;//sdram写地址

wire [23:0] r_addr ;//sdram读地址

wire sdram_rdreq ;//sdram数据接收fifo,读请求

wire sdram_wrreq ;//sdram数据发送fifo,写请求

wire r_ack ;//读响应

wire wr_ack ;//写响应

wire locked_1 ;//pll_1输出稳定标志

wire locked_2 ;//pll_2输出稳定标志

wire reset ;//sccb、data_cache、sdram和vga模块复位信号

wire init_done ;//sdram初始化结束

wire pixel_rst ;//pixel_sampling模块复位信号

wire w_done ;//写完成标志

wire r_done ;//读完成标志

wire pro_valid ;//灰度转换数据有效标志

wire [15:0] pro_dout ;//灰度转换输出

wire pclk ;//增强后的cmos_pclk

//sdram_cke:sdram使能

assign sdram_cke = 1'b1;

//sdram_dqm:数据掩码

assign sdram_dqm = 2'b00;

//reset:sccb、data_cache、sdram和vga模块复位信号

assign reset = locked_1 & locked_2 & rst_n;

//pixel_rst:pixel_sampling模块复位信号

assign pixel_rst = done & init_done & reset;

//时钟增强模块例化

iobuf iobuf_inst (

.datain ( cmos_pclk ),

.dataout ( pclk )

);

//摄像头配置模块例化

sccb u_sccb(

.clk (clk ),

.rst_n (reset ),

.done (done ),

.cmos_rst_n (cmos_rst_n ),

.cmos_pwdn (cmos_pwdn ),

.cmos_scl (cmos_scl ),

.cmos_sda (cmos_sda )

);

//摄像头数据拼接模块例化

pixel_sampling u_pixel_sampling(

.clk (pclk ),//摄像头pclk时钟48MHz

.rst_n (pixel_rst ),//pixel_sampling模块复位信号

.din (cmos_db ),//摄像头采集数据

.vsync (cmos_vsync ),//摄像头场同步信号

.href (cmos_href ),//摄像头行有效信号

.dout_valid (dout_valid ),//输出数据有效标志

.dout (pixel_dout ) //输出拼接完成的像素

);

//图像数据处理模块例化

process u_process(

.clk (pclk ),

.rst_n (pixel_rst ),

.rgb_din (pixel_dout ),

.rgb_valid (dout_valid ),

.pro_dout (pro_dout ),

.pro_valid (pro_valid )

);

//数据缓存模块例化

data_cache u_data_cache(

.clk (clk_100MHz ),

.rst_n (reset ),

.w_done (w_done ),

.r_done (r_done ),

.init_done (init_done ),

.r_data (pro_dout ),

.r_wrclk (pclk ),

.r_wrreq (pro_valid ),

.t_data (r_data ),

.t_rdclk (vga_clk ),

.t_rdreq (data_req ),

.w_ack (wr_ack ),

.r_ack (r_ack ),

.r_q (w_data ),

.w_addr (w_addr ),

.r_addr (r_addr ),

.t_q (vga_din ),

.sdram_rdreq (sdram_rdreq ),//sdram数据接收fifo,读请求

.sdram_wrreq (sdram_wrreq ) //sdram数据发送fifo,写请求

);

//sdram操作模块例化

sdram u_sdram(

.clk (clk_100MHz ),

.rst_n (reset ),

.w_req (sdram_wrreq ),

.r_req (sdram_rdreq ),

.w_addr (w_addr ),

.r_addr (r_addr ),

.w_data (w_data ),

.r_data (r_data ),

.sdram_addr (sdram_addr ),

.sdram_ba (sdram_ba ),

.sdram_dq (sdram_dq ),

.cmd (cmd ),

.init_done (init_done ),

.r_ack (r_ack ),

.wr_ack (wr_ack ),

.w_done (w_done ),//写操作完成标志

.r_done (r_done ) //读操作完成标志

);

//vga驱动模块例化

vga u_vga(

.clk (vga_clk ),

.rst_n (reset ),

.din (vga_din ),

.vga_out_hs (vga_out_hs ),

.vga_out_vs (vga_out_vs ),

.vga_dout (vga_dout ),

.data_req (data_req )

);

//时钟模块1例化

pll_1 pll_1_inst (

.areset (~rst_n ),

.inclk0 (clk ),//50MHz

.c0 (vga_clk ),//65MHz

.c1 (clk_100MHz ),//100MHz

.c2 (sdram_clk ),//100MHz,-75deg

.locked (locked_1 )

);

//时钟模块2例化

pll_2 pll_2_inst (

.areset (~rst_n ),

.inclk0 (clk ),//50MHz系统时钟

.c0 (cmos_xclk ),//24Mhz

.locked (locked_2 )

);

endmodule

8、参数定义

可以通过参数定义修改二值化和边缘检测阈值,以及控制是否进行图像处理和图像处理类型选择。

/**************************************功能介绍***********************************

Copyright:

Date :

Author :厉长川

Version :2022.10.10 v1

Description:参数定义

*********************************************************************************/

//sccb参数定义

`define CNT_1M 6'd50 //1M时钟计数

`define CNT_MS 21'd1315000 //26.3ms时间计数

`define PWDN 18'd255000 //5.1ms计时

`define RST_CMOS 19'd310000 //1.1ms复位等待时间

`define NUM_CFG 8'd248 //寄存器配置个数

//pixel_sampling参数定义

`define PIXEL 4'd10 //舍弃帧数

//vga接口参数

// 1024*768 65Mhz

`define H_ACTIVE 11'd1024 //行有效

`define H_FP 11'd24 //行前沿

`define H_SYNC 11'd136 //行同步

`define H_BP 11'd160 //行后沿

`define H_TO 11'd1344 //行周期

`define V_ACTIVE 11'd768 //场有效

`define V_FP 11'd3 //场前沿

`define V_SYNC 11'd6 //场同步

`define V_BP 11'd29 //场后沿

`define V_TO 11'd806 //场周期

//sdram模块参数

`define CMD_NOOP 4'b0111 //空指令

`define CMD_ACT 4'b0011 //行激活指令

`define CMD_RD 4'b0101 //读指令

`define CMD_WR 4'b0100 //写指令

`define CMD_BR 4'b0110 //突发终止指令

`define CMD_PRE 4'b0010 //预充电指令

`define CMD_AREF 4'b0001 //自动刷新指令

`define CMD_MOD 4'b0000 //模式寄存器配置命令

`define INIT_TIME 14'd10000 //上电等待时间,10000个时钟周期(100us)

`define AREF_TIME 10'd700 //自动刷新间隔时间,700个时钟周期(7us)

`define BURST_LEN 10'd512 //读写突发长度

`define ADDR_END `H_ACTIVE * `V_ACTIVE - `BURST_LEN //读写地址末地址

//阈值参数

`define BIN 7'd127 //二值化阈值

`define SOBEL 2'd3 //边缘检测阈值

//图像处理控制参数

// `define GRAY_OUT //输出灰度化图像

// `define GUS_OUT //输出高斯滤波图像

// `define BIN_OUT //输出二值化图像

// `define SOBEL_OUT //输出边缘检测图像

`define NO_PRO //输出rgb图像

9、最终效果

高斯滤波效果不明显不做演示。

①:灰度转换

②:二值化

③:边缘检测

推荐阅读

评论可见,请评论后查看内容,谢谢!!!评论后请刷新页面。