赞
踩
本项目使用的开发板为zynq7020,框架为正点原子提供的hdim显示双目摄像头例程,
并在此基础上进行双目视觉处理,最终生成视差图和深度图;
所有双目视觉处理部分均在pl端采用Verilog实现
vivado实现RGB转灰度还是很简单的,简单来说就是RGB通道的加权和
Gray = 0.2989*R+0.5870*G+0.1140*B
但是FPGA不擅长浮点数,所以要进行浮点转定点,虽然会丢失精度,但是会节省很多硬件资源,下面是浮点转定点后的代码`
always @(posedge clk or negedge rst_n) begin : proc_RGB if(~rst_n) begin R <= 15'b0; G <= 15'b0; B <= 15'b0; end else begin R<= data_in[23:16]*8'd77; //打一拍 G<= data_in[15:8]*8'd150; B<= data_in[7:0]*8'd29; end end always @(posedge clk or negedge rst_n) begin : proc_gray if(~rst_n) begin gray <= 15'b0; end else begin gray <= R+G+B;//打2拍 end end
然后取gray的高八位即为输出的灰度数据
由于彩色数据转灰度数据需要两个时钟周期,故输出要不输入往后打两拍
always @(posedge clk or negedge rst_n) begin : proc_data_out_vaild if(~rst_n) begin data_out_vaild <= 1'b0; data_out_vsync <= 1'b0; data_out_hsync <= 1'b0; data_out_vaild_d0 <= 1'b0; data_out_vsync_d0 <= 1'b0; data_out_clken_d0 <= 1'b0; end else begin data_out_vsync_d0 <= data_in_vsync;//打一拍 data_out_clken_d0 <= data_in_hsync;//打一拍 data_out_vaild_d0 <= data_in_valid;//打一拍 data_out_vsync <= data_out_vsync_d0;//打2拍 data_out_hsync <= data_out_clken_d0;//打2拍 data_out_vaild <= data_out_vaild_d0;//打2拍 end end
由于正点原子的例程是双目视频数据拼接到同一画面显示的,我使用的视频分辨率为800480,即每个摄像头的分辨率为400480,要进行后续双目视觉处理时需要左右目的数据同步输入,故需要对左目数据进行打拍处理,为实现左右目视频数据对齐左目需要打400拍,这里明显用寄存器打拍不现实,可以采用FIFO或者shitf_RAM进行打拍,我采用的是shift_RAM.下图为我的shift_RAM配置界面
shift_ram代码实现
c_shift_ram_0 your_instance_name (
.D(data_out_L_d), // input wire [7 : 0] D
.CLK(clk), // input wire CLK
.Q(data_out_L) // 400拍之后输出左图
);
在实现完左图打400拍后还需要一个计数器来计数从而实现左右目的同步输出
always @(posedge clk or negedge rst_n) begin : proc_x_pos
if(~rst_n)
begin
x_pos<= 11'd0;
end
else if(data_out_vaild&&(x_pos<IMG_HDISP-1'b1))
x_pos<= x_pos+1'b1;
else
x_pos<= 11'd0;
end
x_pos已输出有效信号拉高开始计数,在x_pos<400时输出左图,否则输出右图,由于左图使用shift_RAM打了400拍,故左右图实现了同步输出
assign data_out_R = x_pos<400 ? 8'd0 :gray[15:8];//输出右图
assign data_out_L_d = (x_pos<400&&data_out_vaild) ? gray[15:8]:8'd0 ;//输出左图
下面附上完整代码
`timescale 1ns/1ps module rgb2gray #( parameter [9:0] IMG_HDISP = 10'd800, //400*480 parameter [9:0] IMG_VDISP = 10'd480 ) ( //时序 逻辑 input clk, // Clock input rst_n , // Asynchronous reset active low input [23:0] data_in, input data_in_vsync , input data_in_hsync , input data_in_valid,//输入信号有效信号 output [7:0] data_out_R, output [7:0] data_out_L, output reg data_out_vsync , output reg data_out_hsync , output reg data_out_vaild//输出信号有效信号 ); reg [15:0] gray; reg [9:0] x_pos; wire [7:0] data_out_L_d; wire [7:0] gray_8; assign gray_8 = gray[15:8]; assign data_out_R = x_pos<400 ? 8'd0 :gray[15:8];//输出右图 assign data_out_L_d = (x_pos<400&&data_out_vaild) ? gray[15:8]:8'd0 ;//输出左图 c_shift_ram_0 your_instance_name ( .D(data_out_L_d), // input wire [7 : 0] D .CLK(clk), // input wire CLK .Q(data_out_L) // 400拍之后输出左图 ); //assign data_out = {gray[15:8],gray[15:8],gray[15:8]}; reg [15:0] R; reg [15:0] G; reg [15:0] B; reg data_out_vaild_d0; reg data_out_vsync_d0 ; reg data_out_clken_d0 ; always @(posedge clk or negedge rst_n) begin : proc_RGB if(~rst_n) begin R <= 15'b0; G <= 15'b0; B <= 15'b0; end else begin R<= data_in[23:16]*8'd77; //打一拍 G<= data_in[15:8]*8'd150; B<= data_in[7:0]*8'd29; end end always @(posedge clk or negedge rst_n) begin : proc_gray if(~rst_n) begin gray <= 15'b0; end else begin gray <= R+G+B;//打2拍 end end always @(posedge clk or negedge rst_n) begin : proc_data_out_vaild if(~rst_n) begin data_out_vaild <= 1'b0; data_out_vsync <= 1'b0; data_out_hsync <= 1'b0; data_out_vaild_d0 <= 1'b0; data_out_vsync_d0 <= 1'b0; data_out_clken_d0 <= 1'b0; end else begin data_out_vsync_d0 <= data_in_vsync;//打一拍 data_out_clken_d0 <= data_in_hsync;//打一拍 data_out_vaild_d0 <= data_in_valid;//打一拍 data_out_vsync <= data_out_vsync_d0;//打2拍 data_out_hsync <= data_out_clken_d0;//打2拍 data_out_vaild <= data_out_vaild_d0;//打2拍 end end always @(posedge clk or negedge rst_n) begin : proc_x_pos if(~rst_n) begin x_pos<= 10'd0; end else if(data_out_vaild&&(x_pos<IMG_HDISP-1'b1)) x_pos<= x_pos+1'b1; else x_pos<= 10'd0; end endmodule
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。