当前位置:   article > 正文

基于FPGA的双目视觉教程_2.RGB转灰度图_正点原子 zynq7020 双面摄像头

正点原子 zynq7020 双面摄像头

项目框架

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

在这里插入图片描述

RGB转灰度

vivado实现RGB转灰度还是很简单的,简单来说就是RGB通道的加权和

Gray = 0.2989*R+0.5870*G+0.1140*B
  • 1

但是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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

然后取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

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

双目视觉处理

由于正点原子的例程是双目视频数据拼接到同一画面显示的,我使用的视频分辨率为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拍之后输出左图
);
  • 1
  • 2
  • 3
  • 4
  • 5

在实现完左图打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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

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 ;//输出左图
  • 1
  • 2

下面附上完整代码

`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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家自动化/article/detail/592032
推荐阅读
相关标签
  

闽ICP备14008679号