Vivado图像仿真平台的搭建--附源码

        我们在做FPGA图像处理中,有些时候写算法的时候,需要查看图像算法处理之后的效果如何,来验证自己算法的正确性,可能身边没有板子,我们可以通过Vivado仿真结果,来验证算法的正确性。

       本文在Vivado中搭建一个基本的图像算法处理仿真平台。将一个车牌bmp图像文件读取进来,然后按照摄像头的时序输出来,通过RGB888转YCbCr提取Cb分量,然后在经过二值化算法,提取车牌信息。 

开发环境:Vivado

工程架构:

仿真时间14ms,Vivado图像仿真结果如下:

 为了验证自己的算法是否正确,我们需要通过matlab也做图像算法处理,然后对比matlab和Vivado两者的输出图像差别。

matlab代码如下,matlab代码按照Vivado图像算法写的,也会输出图像处理结果。

clc;
clear all;
close all;

FID = fopen('G:\picture_deal\image_prj\erzhihua\chepai.bmp','r');%图像读入
FID_output = fopen('G:\picture_deal\image_prj\erzhihua\matlab_output.bmp','w');%图像算法处理后输出结果
bmp_all_data=fread(FID,'uint8');
bmp_all_data_output=bmp_all_data;


bmp_frame_header_data = bmp_all_data(1:54);

%从帧头读取图像的宽度和高度
width_temp=dec2hex(bmp_frame_header_data(19:22),2);
height_temp=dec2hex(bmp_frame_header_data(23:26),2);
for i=1:4
    width_str(9-2*i:9-2*i+1)=width_temp(i,:);
    height_str(9-2*i:9-2*i+1)=height_temp(i,:);
end
width=hex2dec(width_str);
height=hex2dec(height_str);

%截取RGB数据
bmp_rgb_image_data = bmp_all_data(55:end);
bmp_rgb_image_data1 = reshape(bmp_rgb_image_data,3,width*height);
R_data = reshape(bmp_rgb_image_data1(3,:),width,height)';
G_data = reshape(bmp_rgb_image_data1(2,:),width,height)';
B_data = reshape(bmp_rgb_image_data1(1,:),width,height)';

%Y = 0.299R + 0.587G + 0.114B
%Cb = -0.172R - 0.339G + 0.511B + 128;
%Cr = 0.511R - 0.428G - 0.083B + 128;

% 我们现在处理全部按照FPGA中处理,扩大 256 倍,转换如下
%Y = (77R + 150G + 29B)/256
%Cb = (-44R - 87G + 130B)/256 + 128;
%Cr = (128R - 107G - 21B)/256 + 128;
for r = 1:height
    for c = 1:width
        Y_data(r, c) = uint8((77*R_data(r, c) + 150*G_data(r, c) + 29*B_data(r, c))/256);
        Cb_data(r, c) = uint8((-43*R_data(r, c) - 85*G_data(r, c) + 128*B_data(r, c))/256 + 128);
        Cr_data(r, c) = uint8((128*R_data(r, c) - 107*G_data(r, c) - 21*B_data(r, c))/256 + 128);
    end
end

figure(1);
I=flipdim(Cb_data,1);%原图像的水平镜像
imshow(I);
title('Cb分量图像');

%二值化算法
erzhihua_data = zeros(height,width);
for r = 1:height
    for c = 1:width
        if(Cb_data(r, c) < 150) %白的还是白的  %215
            erzhihua_data(r,c) = 255; %白
        else
            erzhihua_data(r,c) = 0;%黑
    end
    end
end

figure(2);
I=flipdim(erzhihua_data,1);%二值化图像
imshow(I);
title('二值化图像');

R_data1 =  reshape(erzhihua_data',1,height*width);
G_data1  = reshape(erzhihua_data',1,height*width);
B_data1  = reshape(erzhihua_data',1,height*width);

bmp_rgb_image_data_output = zeros(3,height*width);
bmp_rgb_image_data_output(1,:) = B_data1;
bmp_rgb_image_data_output(2,:) = G_data1;
bmp_rgb_image_data_output(3,:) = R_data1;

bmp_all_data_output(55:end) = reshape(bmp_rgb_image_data_output,1,width*height*3);

fwrite(FID_output,bmp_all_data_output);%图像算法处理后输出结果

fclose(FID);
fclose(FID_output);

matlab图像处理结果如下:

 

我们需要对比这两个图像的区别,看看像素点图像的结果相差是否在一定范围,下面这段代码就是比较两个图像的像素误差

clc;
clear all;
close all;

%matlab算法处理的图像
FID_matlab = fopen('G:\picture_deal\image_prj\erzhihua\matlab_output.bmp','r');
%FPGA处理的图像
FID_fpga = fopen('G:\picture_deal\image_prj\erzhihua\fpga_output.bmp','r');

bmp_all_data_matlab =fread(FID_matlab,'uint8');
bmp_all_data_fpga = fread(FID_fpga,'uint8');

bmp_frame_header_data = bmp_all_data_matlab(1:54);
%从帧头读取图像的宽度和高度
width_temp=dec2hex(bmp_frame_header_data(19:22),2);
height_temp=dec2hex(bmp_frame_header_data(23:26),2);

for i=1:4
    width_str(9-2*i:9-2*i+1)=width_temp(i,:);
    height_str(9-2*i:9-2*i+1)=height_temp(i,:);
end
width=hex2dec(width_str);
height=hex2dec(height_str);

%截取RGB数据
bmp_rgb_data_matlab = bmp_all_data_matlab(55:end);
bmp_rgb_data_fpga = bmp_all_data_fpga(55:end);

bmp_rgb_data_temp_matlab = reshape(bmp_rgb_data_matlab,3,width*height);
bmp_rgb_data_temp_fpga  = reshape(bmp_rgb_data_fpga,3,width*height);

R_data_matlab = reshape(bmp_rgb_data_temp_matlab(3,:),width,height)';
G_data_matlab = reshape(bmp_rgb_data_temp_matlab(2,:),width,height)';
B_data_matlab = reshape(bmp_rgb_data_temp_matlab(1,:),width,height)';

R_data_fpga = reshape(bmp_rgb_data_temp_fpga(3,:),width,height)';
G_data_fpga = reshape(bmp_rgb_data_temp_fpga(2,:),width,height)';
B_data_fpga = reshape(bmp_rgb_data_temp_fpga(1,:),width,height)';

R_error = R_data_matlab - R_data_fpga;

fclose(FID_matlab);
fclose(FID_fpga);

通过查看R_error这个变量,我们可以看到误差为0,验证了Vivado仿真图像算法的正确性。

 bmp_sim_VIP_tb代码:

`timescale 1ns / 1ns


module bmp_sim_VIP_tb();

integer  iBmpFileId ;      //输入BMP图片
integer  oBmpFileId_1;     //输出BMP图片
integer  oTxtFiled   ;    //输入文本

integer  iIndex = 0;      //输入BMP数据索引
integer  pixel_index = 0; //输入像素数据索引

integer  iCode;

integer  iBmpWidth;        //输入BMP宽度
integer  iBmpHight;        //输入BMP高度
integer  iBmpSize;         //输入BMP字节数
integer  iDataStartIndex;  //输入BMP像素数据偏移量
reg  [7:0] rBmpData [0:2000000] ;       //用于寄存输入BMP图片中的字节数据(包括54字节的文件头)

reg  [7:0] Vip_BmpData_1 [0:2000000] ;  //用于寄存图像处理输出BMP图片
reg  [7:0] rBmpWord ;                  //输出BMP图片时用于寄存数据(以word为单位,即4Byte)
reg  [7:0] pixel_data ;                 //输出视频流时的像素数据

reg  clk;
reg rst_n;

reg [7:0] vip_pixel_data_1[0:921600];  //680*480*3  

initial begin

    //打开输入BMP图片
	iBmpFileId = $fopen("G:\\picture_deal\\image_prj\\erzhihua\\chepai.bmp","rb");
	
	//将输入图片加载到数组中
	iCode = $fread(rBmpData,iBmpFileId);
	
	//根据BMP图片文件头的格式,分别计算出图片的宽度/高度/像素数据偏移量/图片字节数
	iBmpWidth       = {rBmpData[21],rBmpData[20],rBmpData[19],rBmpData[18]};
	iBmpHight       = {rBmpData[25],rBmpData[24],rBmpData[23],rBmpData[22]};
	iBmpSize        = {rBmpData[5],rBmpData[4],rBmpData[3],rBmpData[2]};
	iDataStartIndex = {rBmpData[13],rBmpData[12],rBmpData[11],rBmpData[10]};
	
	//关闭输入图片
	$fclose(iBmpFileId);
	
	//打开输出BMP图片
	oBmpFileId_1 = $fopen("G:\\picture_deal\\image_prj\\erzhihua\\fpga_output.bmp","wb+");
	
	//延迟13ms,等待第一帧图像处理结束
	#13000000
	
    
    //加载图像处理后,BMP图片的文件头和像素数据
    //输出第一张
    for (iIndex = 0; iIndex < iBmpSize; iIndex = iIndex + 1) begin
		if(iIndex < 54) begin
			Vip_BmpData_1[iIndex] = rBmpData[iIndex];
			//$display("data %h",rBmpData[iIndex]);
		end
	    else begin
			Vip_BmpData_1[iIndex] = vip_pixel_data_1[iIndex-54];
		end
	end
	
	//将数组中的数据写到输出的BMP图片中
	 for (iIndex = 0; iIndex < iBmpSize; iIndex = iIndex + 1) begin
		rBmpWord = Vip_BmpData_1[iIndex];
		$fwrite(oBmpFileId_1,"%c",rBmpWord);
    end	
	
	//关闭输出BMP图片
	$fclose(oBmpFileId_1);
end  
 
 
//初始化时钟和复位信号
initial begin
	clk = 1;
	rst_n = 0;
	#110
	rst_n = 1;

end

always #10 clk = ~clk;

//在时钟驱动下,从数组中读取像素数据,用于在仿真中查看BMP数据
always@(posedge clk or negedge rst_n) begin
	if(!rst_n) begin
		pixel_data <= 8'd0;
		pixel_index <= 0;
	end
	else begin
		pixel_data <= rBmpData[pixel_index];
		pixel_index <= pixel_index +1;
	end

end

//产生摄像头时序
wire  cmos_vsync ;
reg   cmos_href;
wire  cmos_clken;
reg [23:0] cmos_data;

reg  cmos_clken_r;
reg  [31:0] cmos_index;

parameter [10:0] IMG_HDISP = 11'd640;
parameter [10:0] IMG_VDISP = 11'd480;

localparam H_SYNC  = 11'd5;
localparam H_BACK  = 11'd5;
localparam H_DISP  = IMG_HDISP;
localparam H_FRONT = 11'd5;
localparam H_TOTAL = H_SYNC + H_BACK + H_DISP + H_FRONT;

localparam V_SYNC  = 11'd1;
localparam V_BACK  = 11'd0;
localparam V_DISP  = IMG_VDISP;
localparam V_FRONT = 11'd1;
localparam V_TOTAL = V_SYNC + V_BACK + V_DISP + V_FRONT;


//模拟OV7725/OV5640 驱动模块输出的时钟使能
always@(posedge clk or negedge rst_n) begin
	if(!rst_n)
		cmos_clken_r <= 0;
	else 
		cmos_clken_r <= ~cmos_clken_r;		
end


//水平寄存器
reg [10:0] hcnt;
always@(posedge clk or negedge rst_n) begin
	if(!rst_n) 
		hcnt <= 11'd0;
	else if(cmos_clken_r)
		hcnt <= (hcnt < H_TOTAL - 1'b1)? hcnt + 1'b1 : 11'd0;		
end


//竖直寄存器
reg [10:0] vcnt;
always@(posedge clk or negedge rst_n) begin
	if(!rst_n) 
		vcnt <= 11'd0;
	else if(cmos_clken_r) begin
		if(hcnt == H_TOTAL - 1'b1)
			vcnt <= (vcnt < V_TOTAL - 1'b1)? vcnt + 1'b1 : 11'd0;	
		else
			vcnt <= vcnt;	
	end		
end

//场同步
reg cmos_vsync_r;

always@(posedge clk or negedge rst_n) begin
	if(!rst_n) 
		cmos_vsync_r <= 1'b0;
	else begin
		if(vcnt <= V_SYNC - 1'b1)
			cmos_vsync_r <= 1'b0;
		else
			cmos_vsync_r <= 1'b1;
	end	
end

assign cmos_vsync = cmos_vsync_r;


//行有效
wire  frame_valid_ahead = (vcnt >= V_SYNC + V_BACK && vcnt < V_SYNC + V_BACK + V_DISP
						   && hcnt >= H_SYNC + H_BACK && hcnt < H_SYNC + H_BACK + H_DISP) 
						   ? 1'b1 : 1'b0;

reg  cmos_href_r;

always@(posedge clk or negedge rst_n) begin
	if(!rst_n) 
		cmos_href_r <= 1'b0;
	else begin
		if(frame_valid_ahead)
			cmos_href_r <= 1'b1;	
		else
			cmos_href_r <= 1'b0;	
	end		
end


always@(posedge clk or negedge rst_n) begin
	if(!rst_n) 
		cmos_href <= 1'b0;
	else begin
		cmos_href <= cmos_href_r;	
	end		
end

assign cmos_clken = cmos_href & cmos_clken_r;


//从数组中以视频格式输出像素数据
wire  [10:0] x_pos;
wire  [10:0] y_pos;

assign x_pos = frame_valid_ahead ? (hcnt - (H_SYNC + H_BACK)): 0;
assign y_pos = frame_valid_ahead ? (vcnt - (V_SYNC + V_BACK)): 0;

always@(posedge clk or negedge rst_n) begin
	if(!rst_n) begin
		cmos_index <= 0;
		cmos_data <= 24'd0;
	end	
	else begin
		cmos_index <= y_pos * 1920 + x_pos * 3 + 54;
		cmos_data <= {rBmpData[cmos_index],rBmpData[cmos_index+1],rBmpData[cmos_index+2]};//按照BGR888存放  
	end		
end


//--------------------------图像处理算法实现----------------------------//

wire 	   per_frame_vsync = cmos_vsync;
wire       per_frame_href  = cmos_href;
wire       per_frame_clken = cmos_clken;
wire [7:0] per_img_red     = cmos_data[7:0];
wire [7:0] per_img_green   = cmos_data[15:8];
wire [7:0] per_img_blue    = cmos_data[23:16];

wire 	   post0_frame_vsync ;
wire       post0_frame_href  ;
wire       post0_frame_clken ;
wire [7:0] post0_img_Y       ;
wire [7:0] post0_img_Cb      ;
wire [7:0] post0_img_Cr      ;


//最后经过图像处理算法处理完的结果
wire 	   post_frame_vsync ;
wire       post_frame_href  ;
wire       post_frame_clken ;
wire       post_img_Bit     ;
wire [7:0] post_img_Y       ;

picture_process  u_picture_process(
	.clk               (clk),
	.rst_n             (rst_n),
	
	//Image data prepred to be processed
	.per_frame_vsync   (per_frame_vsync),
    .per_frame_href    (per_frame_href ),
    .per_frame_clken   (per_frame_clken),
    .per_img_red       (per_img_red    ),
    .per_img_green     (per_img_green  ),
    .per_img_blue      (per_img_blue   ),
	
    //Image data has been processed
	.post_frame_vsync (post_frame_vsync),
	.post_frame_href  (post_frame_href ),
	.post_frame_clken (post_frame_clken),
	.post_img_Bit     (post_img_Bit    ),
	.post_img_Y       (post_img_Y      )
);


//输出图片
wire 	   PCI1_vip_out_frame_vsync ;
wire       PCI1_vip_out_frame_href  ;
wire       PCI1_vip_out_frame_clken ;
wire [7:0] PCI1_vip_out_img_R       ;
wire [7:0] PCI1_vip_out_img_G       ;
wire [7:0] PCI1_vip_out_img_B       ;

assign  PCI1_vip_out_frame_vsync = post_frame_vsync;
assign  PCI1_vip_out_frame_href  = post_frame_href;
assign  PCI1_vip_out_frame_clken = post_frame_clken;
assign  PCI1_vip_out_img_R   = {8{post_img_Bit}};
assign  PCI1_vip_out_img_G   = {8{post_img_Bit}};
assign  PCI1_vip_out_img_B   = {8{post_img_Bit}};


//assign  PCI1_vip_out_img_R  = post_img_Y;
//assign  PCI1_vip_out_img_G  = post_img_Y;
//assign  PCI1_vip_out_img_B  = post_img_Y;

reg [31:0] PCI1_vip_cnt ; 
reg        PCI1_vip_vsync_r ;     //寄存VIP输出的场同步
reg        PCI1_vip_out_en  ;     //寄存VIP处理图像的使能信号,仅维持一帧的时间

always@(posedge clk or negedge rst_n) begin
	if(!rst_n) 
		PCI1_vip_vsync_r <= 1'b0;
	else begin
		PCI1_vip_vsync_r <= PCI1_vip_out_frame_vsync;	
	end		
end


always@(posedge clk or negedge rst_n) begin
	if(!rst_n) 
		PCI1_vip_out_en <= 1'b1;
	else if(PCI1_vip_vsync_r & (!PCI1_vip_out_frame_vsync)) begin
		PCI1_vip_out_en <= 1'b0;	
	end		
end

always@(posedge clk or negedge rst_n) begin
	if(!rst_n) 
		PCI1_vip_cnt <= 32'd0;
	else if(PCI1_vip_out_en) begin
		if(PCI1_vip_out_frame_href & PCI1_vip_out_frame_clken) begin
		    //$display("output picture22222");
			PCI1_vip_cnt <= PCI1_vip_cnt + 3;
			vip_pixel_data_1[PCI1_vip_cnt+0] <= PCI1_vip_out_img_R;
			vip_pixel_data_1[PCI1_vip_cnt+1] <= PCI1_vip_out_img_G;
			vip_pixel_data_1[PCI1_vip_cnt+2] <= PCI1_vip_out_img_B;
		end		
	end		
end


endmodule

picture_process 代码:



module picture_process(
    input	        clk              ,
	input	        rst_n            ,
	//Image data prepred to be processed
	input	        per_frame_vsync  ,
    input	        per_frame_href   ,
    input	        per_frame_clken  ,
    input  [7:0]	per_img_red      ,
    input  [7:0]    per_img_green    ,
    input  [7:0]	per_img_blue     ,
	//Image data has been processed
	output	        post_frame_vsync ,
	output	        post_frame_href  ,
	output	        post_frame_clken ,
	output  	    post_img_Bit      ,
	output [7:0]    post_img_Y      
);

wire	    post0_frame_vsync ;
wire	    post0_frame_href  ;
wire	    post0_frame_clken ;
wire [7:0]	post0_img_Y       ;
wire [7:0]	post0_img_Cb      ;
wire [7:0]	post0_img_Cr      ;

assign  post_img_Y = post0_img_Cb;



//彩色转灰度
picture_RGB888_YCbCr444  u_PICTURE_RGB888_YCbCr444(
    //global signal
	.clk               (clk),
	.rst_n             (rst_n),
	
	//Image data prepred to be processed
	.per_frame_vsync   (per_frame_vsync),
    .per_frame_href    (per_frame_href ),
    .per_frame_clken   (per_frame_clken),
    .per_img_red       (per_img_red    ),
    .per_img_green     (per_img_green  ),
    .per_img_blue      (per_img_blue   ),
	
    //Image data has been processed
	.post_frame_vsync  (post0_frame_vsync),
	.post_frame_href   (post0_frame_href ),
	.post_frame_clken  (post0_frame_clken),
	.post_img_Y        (post0_img_Y      ),
	.post_img_Cb       (post0_img_Cb     ),
	.post_img_Cr       (post0_img_Cr     )
);

//二值化
picture_binarization #(                           
    .THRESHOLD         (8'd150))  //设置二值化阈值
u_picture_binarization(
    //global signal
    .clk               (clk),
	.rst_n             (rst_n),
	
	//Image data prepred to be processed
	.per_frame_vsync   (post0_frame_vsync),
    .per_frame_href    (post0_frame_href ),
    .per_frame_clken   (post0_frame_clken),
    .per_img_Y         (post0_img_Cb     ),
	
    //Image data has been processed
	.post_frame_vsync  (post_frame_vsync),
	.post_frame_href   (post_frame_href ),
	.post_frame_clken  (post_frame_clken),
	.post_img_Bit      (post_img_Bit    )
);

endmodule

picture_RGB888_YCbCr444 代码



module picture_RGB888_YCbCr444(
    //global signal
    input			clk              ,
	input			rst_n            ,
	//Image data prepred to be processed
	input			per_frame_vsync  ,
    input			per_frame_href   ,
    input			per_frame_clken  ,
    input [7:0]		per_img_red      ,
    input [7:0]		per_img_green    ,
    input [7:0]		per_img_blue     ,
	//Image data has been processed
	output			post_frame_vsync ,
	output			post_frame_href  ,
	output			post_frame_clken ,
	output [7:0]	post_img_Y       ,
	output [7:0]	post_img_Cb      ,
	output [7:0]	post_img_Cr      
);


//--------------------------------------------
/*********************************************
//Refer to <OV7725 Camera Module Software Applicaton Note> page 5
	Y 	=	(77 *R 	+ 	150*G 	+ 	29 *B)>>8
	Cb 	=	(-43*R	- 	85 *G	+ 	128*B)>>8 + 128
	Cr 	=	(128*R 	-	107*G  	-	21 *B)>>8 + 128
--->
	Y 	=	(77 *R 	+ 	150*G 	+ 	29 *B)>>8
	Cb 	=	(-43*R	- 	85 *G	+ 	128*B + 32768)>>8
	Cr 	=	(128*R 	-	107*G  	-	21 *B + 32768)>>8
**********************************************/
//Step 1
reg	[15:0]	img_red_r0,		img_red_r1,		img_red_r2;	
reg	[15:0]	img_green_r0,	img_green_r1,	img_green_r2; 
reg	[15:0]	img_blue_r0,	img_blue_r1,	img_blue_r2; 
always@(posedge clk or negedge rst_n)begin
	if(!rst_n)begin
		img_red_r0		<=	0; 		
		img_red_r1		<=	0; 		
		img_red_r2		<=	0; 	
		img_green_r0	<=	0; 		
		img_green_r1	<=	0; 		
		img_green_r2	<=	0; 	
		img_blue_r0		<=	0; 		
		img_blue_r1		<=	0; 		
		img_blue_r2		<=	0; 			
	end
	else begin
		img_red_r0		<=	per_img_red 	* 	8'd77; 		
		img_red_r1		<=	per_img_red 	* 	8'd43; 	
		img_red_r2		<=	per_img_red 	* 	8'd128; 		
		img_green_r0	<=	per_img_green 	* 	8'd150; 		
		img_green_r1	<=	per_img_green 	* 	8'd85; 			
		img_green_r2	<=	per_img_green 	* 	8'd107; 
		img_blue_r0		<=	per_img_blue 	* 	8'd29; 		
		img_blue_r1		<=	per_img_blue 	* 	8'd128; 			
		img_blue_r2		<=	per_img_blue 	* 	8'd21; 		
	end
end

//--------------------------------------------------
//Step 2
reg	[15:0]	img_Y_r0;	
reg	[15:0]	img_Cb_r0; 
reg	[15:0]	img_Cr_r0; 
always@(posedge clk or negedge rst_n)
begin
	if(!rst_n)
		begin
		img_Y_r0	<=	0; 		
		img_Cb_r0	<=	0; 		
		img_Cr_r0	<=	0; 	
		end
	else
		begin
		img_Y_r0	<=	img_red_r0 	+ 	img_green_r0 	+ 	img_blue_r0; 		
		img_Cb_r0	<=	img_blue_r1 - 	img_red_r1 		- 	img_green_r1	+	16'd32768; 		
		img_Cr_r0	<=	img_red_r2 	- 	img_green_r2 	- 	img_blue_r2		+	16'd32768; 		
		end
end

//--------------------------------------------------
//Step 3
reg	[7:0]	img_Y_r1;	
reg	[7:0]	img_Cb_r1; 
reg	[7:0]	img_Cr_r1; 
always@(posedge clk or negedge rst_n)
begin
	if(!rst_n)
		begin
		img_Y_r1	<=	0; 		
		img_Cb_r1	<=	0; 		
		img_Cr_r1	<=	0; 	
		end
	else
		begin
		img_Y_r1	<=	img_Y_r0[15:8];
		img_Cb_r1	<=	img_Cb_r0[15:8];
		img_Cr_r1	<=	img_Cr_r0[15:8]; 
		end
end

//------------------------------------------
//lag 3 clocks signal sync  
reg	[2:0]	per_frame_vsync_r;
reg	[2:0]	per_frame_href_r;	
reg	[2:0]	per_frame_clken_r;
always@(posedge clk or negedge rst_n)
begin
	if(!rst_n)
		begin
		per_frame_vsync_r <= 0;
		per_frame_href_r <= 0;
		per_frame_clken_r <= 0;
		end
	else
		begin
		per_frame_vsync_r 	<= 	{per_frame_vsync_r[1:0], 	per_frame_vsync};
		per_frame_href_r 	<= 	{per_frame_href_r[1:0], 	per_frame_href};
		per_frame_clken_r 	<= 	{per_frame_clken_r[1:0], 	per_frame_clken};
		end
end
assign	post_frame_vsync 	= 	per_frame_vsync_r[2];
assign	post_frame_href 	= 	per_frame_href_r[2];
assign	post_frame_clken 	= 	per_frame_clken_r[2];
assign	post_img_Y 	= 	post_frame_href ? img_Y_r1 : 8'd0;
assign	post_img_Cb =	post_frame_href ? img_Cb_r1: 8'd0;
assign	post_img_Cr = 	post_frame_href ? img_Cr_r1: 8'd0;

endmodule

picture_binarization代码



module picture_binarization #(                           
  parameter  THRESHOLD  = 8'd80)  //设置二值化阈值
(
    //global signal
    input			clk              ,
	input			rst_n            ,
	//Image data prepred to be processed
	input			per_frame_vsync  ,
    input			per_frame_href   ,
    input			per_frame_clken  ,
    input  [7:0]	per_img_Y        ,
	//Image data has been processed
	output			post_frame_vsync ,
	output			post_frame_href  ,
	output			post_frame_clken ,
	output   	    post_img_Bit        

);

//reg define
reg    post_frame_vsync_r;
reg    post_frame_href_r;
reg    post_frame_clken_r;
reg    post_img_Bit_r;

assign  post_frame_vsync    = post_frame_vsync_r  ;
assign  post_frame_href     = post_frame_href_r   ;
assign  post_frame_clken    = post_frame_clken_r  ;
assign  post_img_Bit        = post_img_Bit_r      ;


//二值化
always @(posedge clk or negedge rst_n) begin
    if(!rst_n)
        post_img_Bit_r <= 1'b0;
    else if(per_img_Y < THRESHOLD)   //阈值
        post_img_Bit_r <= 1'b1; //白
    else
        post_img_Bit_r <= 1'b0; //黑
end

//延时1拍以同步时钟信号
always@(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        post_frame_vsync_r <= 1'd0;
        post_frame_href_r <= 1'd0;
        post_frame_clken_r <= 1'd0;
    end
    else begin
        post_frame_vsync_r <= per_frame_vsync;
		post_frame_href_r  <= per_frame_href;
        post_frame_clken_r <= per_frame_clken;
    end
end

endmodule

 源文件免费下载:基于Vivado图像算法处理的仿真搭建-其它文档类资源-CSDN下载

 感谢crazy_bingo前辈的分享。

  • 6
    点赞
  • 50
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值