赞
踩
基于图像实时采集系统实现图像处理
算法:采用精度为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
/**************************************功能介绍*********************************** 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
/**************************************功能介绍*********************************** 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
采用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
/**************************************功能介绍*********************************** 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
/**************************************功能介绍*********************************** 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
可以通过参数定义修改二值化和边缘检测阈值,以及控制是否进行图像处理和图像处理类型选择。
/**************************************功能介绍*********************************** 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图像
高斯滤波效果不明显不做演示。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。