Bootstrap

基于FPGA的双目视觉教程_2.RGB转灰度图

项目框架

本项目使用的开发板为zynq7020,框架为正点原子提供的hdim显示双目摄像头例程,
并在此基础上进行双目视觉处理,最终生成视差图和深度图;
所有双目视觉处理部分均在pl端采用Verilog实现

在这里插入图片描述

RGB转灰度图

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
;