本帖最后由 UT发布 于 2025-4-2 15:57 编辑
软件版本:Anlogic -TD5.6.1-64bit 操作系统:WIN10 64bit 硬件平台:适用安路(Anlogic)FPGA 1概述本文简述了图像拉普拉斯锐化的算法,讲解如何进行Verilog的算法实现,并进行上板实验。 2算法原理简介图像的拉普拉斯锐化是根据图像每个像素领域内的像素到该像素的突变程度来计算的,计算的是图像像素的变化程度。我们知道,一阶微分函数描述了函数图像是朝哪个方向变化的,或增长或降低。二阶微分函数描述的则是图像变化的速度,是急剧增长(下降)还是平缓的增长(下降)。根据上述的描述,可以知道二阶微分可以得到图像色彩的过渡程度,比如白色与黑色的过渡。 换句话说,当邻域中心像素灰度低于它所在的领域内其它像素的平均灰度时,此中心像素的灰度应被进一步降低,当邻域中心像素灰度高于它所在的邻域内其它像素的平均灰度时,此中心像素的灰度应被进一步提高,以此实现图像的锐化处理。 3算法仿真
3.1Matlab算法仿真
3.1.1Matlab算法代码分析
- clear;clear all;clc;
-
- image_in = imread('lena_1280x720.jpg');
- [row,col,n] = size(image_in);
-
- lap_image = zeros(size(image_in), 'like', image_in);
- lap_image0 = zeros(size(image_in), 'like', image_in);
- for i = 2:1:row-1
- for j = 2:1:col-1
- lap_image0(i,j,1)=...
- image_in(i-1,j,1)+...
- image_in(i,j-1,1)+...
- image_in(i,j+1,1)+...
- image_in(i+1,j,1)-...
- image_in(i,j ,1)*4;
-
- lap_image0(i,j,2)=...
- image_in(i-1,j,2)+...
- image_in(i,j-1,2)+...
- image_in(i,j+1,2)+...
- image_in(i+1,j,2)-...
- image_in(i,j ,2)*4;
-
- lap_image0(i,j,3)=...
- image_in(i-1,j,3)+...
- image_in(i,j-1,3)+...
- image_in(i,j+1,3)+...
- image_in(i+1,j,3)-...
- image_in(i,j ,3)*4;
- end
- end
- lap_image = image_in - lap_image0;
-
- image_in1 = imnoise(image_in,'salt & pepper',0.05);
- lap_image1 = zeros(size(image_in), 'like', image_in);
- lap_image11 = zeros(size(image_in), 'like', image_in);
- for i = 2:1:row-1
- for j = 2:1:col-1
- lap_image1(i,j ,1)=...
- image_in1(i-1,j,1)+...
- image_in1(i,j-1,1)+...
- image_in1(i,j+1,1)+...
- image_in1(i+1,j,1)-...
- image_in1(i,j ,1)*4;
-
- lap_image1(i,j ,2)=...
- image_in1(i-1,j,2)+...
- image_in1(i,j-1,2)+...
- image_in1(i,j+1,2)+...
- image_in1(i+1,j,2)-...
- image_in1(i,j ,2)*4;
-
- lap_image1(i,j ,3)=...
- image_in1(i-1,j,3)+...
- image_in1(i,j-1,3)+...
- image_in1(i,j+1,3)+...
- image_in1(i+1,j,3)-...
- image_in1(i,j ,3)*4;
- end
- end
- lap_image11 = image_in1 - lap_image1;
-
- image_in2 = imnoise(image_in,'gaussian',0.05);
- lap_image2 = zeros(size(image_in), 'like', image_in);
- lap_image22 = zeros(size(image_in), 'like', image_in);
- for i = 2:1:row-1
- for j = 2:1:col-1
- lap_image2(i,j ,1)=...
- image_in2(i-1,j,1)+...
- image_in2(i,j-1,1)+...
- image_in2(i,j+1,1)+...
- image_in2(i+1,j,1)-...
- image_in2(i,j ,1)*4;
-
- lap_image2(i,j ,2)=...
- image_in2(i-1,j,2)+...
- image_in2(i,j-1,2)+...
- image_in2(i,j+1,2)+...
- image_in2(i+1,j,2)-...
- image_in2(i,j ,2)*4;
-
- lap_image2(i,j ,3)=...
- image_in2(i-1,j,3)+...
- image_in2(i,j-1,3)+...
- image_in2(i,j+1,3)+...
- image_in2(i+1,j,3)-...
- image_in2(i,j ,3)*4;
- end
- end
- lap_image22 = image_in2 - lap_image2;
-
- figure
- subplot(321);
- imshow(image_in ), title('the original gray image');
- subplot(322);
- imshow(lap_image), title('the lap image image');
- subplot(323);
- imshow(image_in1), title('the salt & pepper image');
- subplot(324);
- imshow(lap_image11), title('the lap image1 image');
- subplot(325);
- imshow(image_in2), title('the gaussian image');
- subplot(326);
- imshow(lap_image22), title('the lap image2 image');
复制代码
3.1.2Matlab实验结果3.2Verilog算法仿真
3.2.1Modelsim仿真
3.2.1.1仿真执行在件夹Algorithm_simulation下进行算法的仿真,分为sim,src和tb三个子文件夹。在sim文件夹下有win系统的快捷执行文件sim.bat,可以一键进行仿真,src文件下放的是Verilog的核心图像算法及其顶层与输入图像激励,tb文件下放的是测试激励文件及输出图像的保存。 双击执行sim文件夹下sim.bat,自动打开Modelsim仿真,自动添加仿真波形,执行完成后自动保存图像,仿真波形如图所示: 3.2.1.2仿真关键部分代码解析- #
- # Create work library
- #
- vlib work
- #
- # Compile sources
- #
- vlog "../src/*.v"
- vlog "../tb/*.v"
- #
- # Call vsim to invoke simulator
- #
- vsim -voptargs=+acc work.top_tb
- #
- # Add waves
- #
- do wave.do
- #
- # Run simulation
- #
- run -all
- #
- # End
复制代码
- reg en;
- reg [12:0] h_syn_cnt = 'd0;
- reg [12:0] v_syn_cnt = 'd0;
- reg [23:0] image [0 : H_ACTIVE*V_ACTIVE-1];
- reg [31:0] image_cnt = 'd0;
-
- //读取txt文件到image数组中
- initial begin
- $readmemh("../matlab_src/image_720_1280_3.txt", image);
- end
-
- // 行扫描计数器
- always@(posedge i_clk)
- begin
- if(h_syn_cnt == H_TOTAL_TIME-1)
- h_syn_cnt <= 0;
- else
- h_syn_cnt <= h_syn_cnt + 1;
- end
-
- // 列扫描计数器
- always@(posedge i_clk)
- begin
- if(h_syn_cnt == H_TOTAL_TIME-1)
- begin
- if(v_syn_cnt == V_TOTAL_TIME-1)
- v_syn_cnt <= 0;
- else
- v_syn_cnt <= v_syn_cnt + 1;
- end
- end
-
- // 行同步控制
- always@(posedge i_clk)
- begin
- if(h_syn_cnt < H_SYNC_TIME)
- o_hsyn <= 0;
- else
- o_hsyn <= 1;
- end
-
- // 场同步控制
- always@(posedge i_clk)
- begin
- if(v_syn_cnt < V_SYNC_TIME)
- o_vsyn <= 0;
- else
- o_vsyn <= 1;
- end
-
- // 坐标使能.
- always@(posedge i_clk)
- begin
- if(v_syn_cnt >= V_SYNC_TIME + V_BACK_PORCH && v_syn_cnt < V_SYNC_TIME + V_BACK_PORCH + V_ACTIVE)
- begin
- if(h_syn_cnt >= H_SYNC_TIME + H_BACK_PORCH && h_syn_cnt < H_SYNC_TIME + H_BACK_PORCH + H_ACTIVE)
- en <= 1;
- else
- en <= 0;
- end
- else
- en <= 0;
- end
-
- always@(posedge i_clk)
- begin
- if(en)
- begin
- o_r <= image[image_cnt][23:16];
- o_g <= image[image_cnt][15:8];
- o_b <= image[image_cnt][7:0];
- image_cnt <= image_cnt + 1;
- end
- else if(image_cnt == H_ACTIVE*V_ACTIVE)
- begin
- o_r <= 8'h00;
- o_g <= 8'h00;
- o_b <= 8'h00;
- image_cnt <= 'd0;
- end
- else
- begin
- o_r <= 8'h00;
- o_g <= 8'h00;
- o_b <= 8'h00;
- image_cnt <= image_cnt;
- end
- end
-
- always@(posedge i_clk)
- begin
-
- // if(image_cnt >= H_ACTIVE*V_ACTIVE)
- // o_en <= 0;
- // else
- o_en <= en;
- end
复制代码
- reg clk;
- reg rst_n;
-
- integer image_txt;
-
- reg [31:0] pixel_cnt;
- wire[23:0] data;
- wire de;
-
-
- top u_top
- (
- .i_clk (clk ),
- .i_rst_n (rst_n ),
- .o_gray_data (data ),
- .o_gray_de (de )
- );
-
- always #(1) clk = ~clk;
-
- initial
- begin
- clk = 1;
- rst_n = 0;
- #100
- rst_n = 1;
-
- end
-
- glbl glbl();
-
- initial
- begin
- image_txt = $fopen("../matlab_src/image_720_1280_3_out.txt");
- end
-
- always@(posedge clk or negedge rst_n)
- begin
- if(!rst_n)
- begin
- pixel_cnt <= 0;
- end
- else if(de)
- begin
- pixel_cnt = pixel_cnt + 1;
- $fwrite(image_txt,"%h\n",data);
- end
- end
-
- always@(posedge clk )
- begin
- if(pixel_cnt == 720*1280)
- begin
- $display("*******************************************************************************");
- $display("*** Success:image_720_1280_3_out.txt is output complete! %t", $realtime, "ps***");
- $display("*******************************************************************************");
- $fclose(image_txt);
- $stop;
- end
- end
复制代码
3.2.2Modelsim实验结果- clear;clear all;clc;
-
- row = 720;
- col = 1280;
- n = 3;
-
- image_sim_pass = uint8(zeros(row,col,n));
- fid = fopen('image_720_1280_3_out.txt','r');
- for x = 1:row
- for y = 1:col
- RGB = fscanf(fid,'%s',1);
- image_sim_pass(x,y,1) = uint8(hex2dec(RGB(1:2)));
- image_sim_pass(x,y,2) = uint8(hex2dec(RGB(3:4)));
- image_sim_pass(x,y,3) = uint8(hex2dec(RGB(5:6)));
- end
- end
- fclose(fid);
-
- image_1 = imread('lena_1280x720.jpg');
-
- subplot(121);
- imshow(image_1), title('The original image');
-
- subplot(122);
- imshow(image_sim_pass),title('After processing images');
-
- imwrite(image_sim_pass,'lena_720x128_sim_pass.jpg');
复制代码
4工程实现
4.1Verilog代码分析变量声明 - reg [2:0] i_hsyn_d;
- reg [2:0] i_vsyn_d;
- reg [2:0] i_en_d;
-
- wire [11:0] sum_r;
- wire [11:0] sum_g;
- wire [11:0] sum_b;
-
- reg [11:0] sum_r1;
- reg [11:0] sum_g1;
- reg [11:0] sum_b1;
-
- reg [11:0] sum_r2;
- reg [11:0] sum_g2;
- reg [11:0] sum_b2;
-
- reg [7:0] lap_r;
- reg [7:0] lap_g;
- reg [7:0] lap_b;
-
- wire [7:0] r_temp_11;
- wire [7:0] r_temp_12;
- wire [7:0] r_temp_13;
- wire [7:0] r_temp_21;
- wire [7:0] r_temp_22;
- wire [7:0] r_temp_23;
- wire [7:0] r_temp_31;
- wire [7:0] r_temp_32;
- wire [7:0] r_temp_33;
-
- wire [7:0] g_temp_11;
- wire [7:0] g_temp_12;
- wire [7:0] g_temp_13;
- wire [7:0] g_temp_21;
- wire [7:0] g_temp_22;
- wire [7:0] g_temp_23;
- wire [7:0] g_temp_31;
- wire [7:0] g_temp_32;
- wire [7:0] g_temp_33;
-
- wire [7:0] b_temp_11;
- wire [7:0] b_temp_12;
- wire [7:0] b_temp_13;
- wire [7:0] b_temp_21;
- wire [7:0] b_temp_22;
- wire [7:0] b_temp_23;
- wire [7:0] b_temp_31;
- wire [7:0] b_temp_32;
- wire [7:0] b_temp_33;
复制代码
输出赋值 - assign o_hs = i_hsyn_d[2];
- assign o_vs = i_vsyn_d[2];
- assign o_en = i_en_d[2] ;
- assign o_r = lap_r;
- assign o_g = lap_g;
- assign o_b = lap_b;
复制代码
信号同步化 - always@(posedge i_clk )
- begin
- i_hsyn_d <= {i_hsyn_d[1:0],i_hsyn};
- i_vsyn_d <= {i_vsyn_d[1:0],i_vsyn};
- i_en_d <= {i_en_d[1:0],i_en};
-
- end
复制代码
调用3x3模板 - image_template u_r_template
- (
- .i_clk (i_clk ),
- .i_rst_n (i_rst_n ),
- .i_en (i_en ),
- .i_data (i_r ),
- .o_en ( ),
- .o_temp_11 (r_temp_11 ),
- .o_temp_12 (r_temp_12 ),
- .o_temp_13 (r_temp_13 ),
- .o_temp_21 (r_temp_21 ),
- .o_temp_22 (r_temp_22 ),
- .o_temp_23 (r_temp_23 ),
- .o_temp_31 (r_temp_31 ),
- .o_temp_32 (r_temp_32 ),
- .o_temp_33 (r_temp_33 )
- );
复制代码
调用3x3模板 - image_template u_g_template
- (
- .i_clk (i_clk ),
- .i_rst_n (i_rst_n ),
- .i_en (i_en ),
- .i_data (i_g ),
- .o_en ( ),
- .o_temp_11 (g_temp_11 ),
- .o_temp_12 (g_temp_12 ),
- .o_temp_13 (g_temp_13 ),
- .o_temp_21 (g_temp_21 ),
- .o_temp_22 (g_temp_22 ),
- .o_temp_23 (g_temp_23 ),
- .o_temp_31 (g_temp_31 ),
- .o_temp_32 (g_temp_32 ),
- .o_temp_33 (g_temp_33 )
- );
复制代码
调用3x3模板 - image_template u_b_template
- (
- .i_clk (i_clk ),
- .i_rst_n (i_rst_n ),
- .i_en (i_en ),
- .i_data (i_b ),
- .o_en ( ),
- .o_temp_11 (b_temp_11 ),
- .o_temp_12 (b_temp_12 ),
- .o_temp_13 (b_temp_13 ),
- .o_temp_21 (b_temp_21 ),
- .o_temp_22 (b_temp_22 ),
- .o_temp_23 (b_temp_23 ),
- .o_temp_31 (b_temp_31 ),
- .o_temp_32 (b_temp_32 ),
- .o_temp_33 (b_temp_33 )
- );
复制代码
执行加法运算 - always@(posedge i_clk or negedge i_rst_n)
- begin
- if(!i_rst_n)
- begin
- sum_r1 <= 12'd0;
- sum_g1 <= 12'd0;
- sum_b1 <= 12'd0;
- sum_r2 <= 12'd0;
- sum_g2 <= 12'd0;
- sum_b2 <= 12'd0;
- end
- else
- begin
- sum_r1 <= r_temp_12 + r_temp_21 + r_temp_23 + r_temp_32;
- sum_r2 <= {2'd0,r_temp_22,2'd0} + {4'd0,r_temp_22};
-
- sum_g1 <= g_temp_12 + g_temp_21 + g_temp_23 + g_temp_32;
- sum_g2 <= {2'd0,g_temp_22,2'd0} + {4'd0,g_temp_22};
-
- sum_b1 <= b_temp_12 + b_temp_21 + b_temp_23 + b_temp_32;
- sum_b2 <= {2'd0,b_temp_22,2'd0} + {4'd0,b_temp_22};
- end
- end
复制代码
执行减法运算 - assign sum_r = sum_r2 - sum_r1;
- assign sum_g = sum_g2 - sum_g1;
- assign sum_b = sum_b2 - sum_b1;
复制代码
执行拉普拉斯锐化处理 - always@(posedge i_clk or negedge i_rst_n)
- begin
- if(!i_rst_n)
- begin
- lap_r <= 8'd0;
- end
- else if(sum_r[11:8] > 0)
- begin
- lap_r <= 8'd255;
- end
- else if(sum_r2 < sum_r1)
- begin
- lap_r <= 8'd0;
- end
- else
- begin
- lap_r <= sum_r[7:0];
- end
- end
-
- always@(posedge i_clk or negedge i_rst_n)
- begin
- if(!i_rst_n)
- begin
- lap_g <= 8'd0;
- end
- else if(sum_g[11:8] > 0)
- begin
- lap_g <= 8'd255;
- end
- else if(sum_g2 < sum_g1)
- begin
- lap_g <= 8'd0;
- end
- else
- begin
- lap_g <= sum_g[7:0];
- end
- end
-
- always@(posedge i_clk or negedge i_rst_n)
- begin
- if(!i_rst_n)
- begin
- lap_b <= 8'd0;
- end
- else if(sum_b[11:8] > 0)
- begin
- lap_b <= 8'd255;
- end
- else if(sum_b2 < sum_b1)
- begin
- lap_b <= 8'd0;
- end
- else
- begin
- lap_b <= sum_b[7:0];
- end
- end
复制代码
4.2工程结构工程结构如图所示: 图像数据通过摄像头采集进来,先缓存在fifo中,然后通过写状态机,将图像数据送进DDR进行缓存,缓存后的图像数据从DDR中取出,通过读状态机送出到fifo中,然后算法处理模块在fifo中取出数据,完成数据处理后送到LCD进行显示输出。 5上板实验点击下载后,可以看到正常的输出如下所示,摄像头的分辨率为640x480
|