本帖最后由 UT发布 于 2025-3-31 16:10 编辑
1概述本文简述了图像log对数变换的算法,讲解如何进行Verilog的算法实现,并进行上板实验。 2算法原理简介对数变换可以将图像的低灰度值部分扩展,显示出低灰度部分更多的细节,将其高灰度值部分压缩,减少高灰度值部分的细节,从而达到强调图像低灰度部分的目的。 g = c*log(1 + f) 如图所示,对数曲线在像素值较低的区域斜率较大,像素值较高的区域斜率比较低,所以图像经过对数变换之后,在较暗的区域对比度将得到提升,因而能增强图像暗部的细节。
3算法仿真3.1Matlab算法仿真 3.1.1Matlab算法代码分析
- clear;clear all;clc;
-
- image_in = imread('lena_1280x720.jpg');
- [row,col,n] = size(image_in);
-
- image_in1=im2double(image_in);
- image_out=log_transform(image_in1);
-
- image_out1=mat2gray(log(1+double(image_in)));
-
- figure
- subplot(131);
- imshow(image_in), title('the original image');
- subplot(132);
- imshow(image_out), title('the translated image ');
- subplot(133);
- imshow(image_out1), title('the translated image 1');
-
- function image_out = log_transform(image_in)
-
- [m,n]=size(image_in);
- a=image_in;
- for i=1:m
- for j=1:n
- a(i,j)=40*log(image_in(i,j)+1);
- end
- end
- image_out=mat2gray(a);
- end
-
- 使用matlab生成log系数的代码如下:
- clear;clear all;clc;
-
- % g = c*log(1 + f)
-
- num = 256;
-
- f = [0:1:255];
-
- c =40;
-
- g = c*log(1+f);
-
- %=================================================================
- fid = fopen('log_para_256.coe','w');
-
- fprintf(fid,'memory_initialization_radix = 10;\n');
- fprintf(fid,'memory_initialization_vector =\n');
-
- for n = 1:num
- log(n) = round(g(n));
- end
-
- for n = 1: num - 1
- fprintf(fid,'%d, \n',log(n));
- end
-
- fprintf(fid,'%d;',log(256));
- fclose(fid);
-
- %=================================================================
- fid1 = fopen('../src/image_rom_log_para.v','w');
-
- fprintf(fid1,'module image_rom_log_para\n');
- fprintf(fid1,'(\n');
- fprintf(fid1,' input clka,\n');
- fprintf(fid1,' input [7:0] addra,\n');
- fprintf(fid1,' input ena,\n');
- fprintf(fid1,' output [7:0] douta\n');
- fprintf(fid1,');\n');
- fprintf(fid1,'reg [7:0] DATA;\n');
- fprintf(fid1,'assign douta = DATA;\n');
- fprintf(fid1,'always@(*)\n');
- fprintf(fid1,'begin\n');
- fprintf(fid1,' case(addra)\n');
-
- for n = 1:num
- log(n) = round(g(n));
- end
-
- for n = 1: num
- fprintf(fid1,'%d : DATA <= %d; \n',n-1,log(n));
- end
- fprintf(fid1,' default: DATA<= 0;\n');
- fprintf(fid1,' endcase\n');
- fprintf(fid1,'end\n');
- fprintf(fid1,'endmodule\n');
- fclose(fid1);
- %=================================================================
-
- hold on
- plot(f);
- plot(g);
- legend('f','log g');
- hold off
复制代码
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
- 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
-
- 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_1280x720_sim_pass.jpg');
复制代码
4工程实现
4.1Verilog代码分析由于提前使用matlab计算好了log系数,这里代码很简单直接查表就行。 - //同步输出使能信号
- assign o_hs = i_hsyn;
- assign o_vs = i_vsyn;
- assign o_en = i_en;
- rom查表
- image_rom_log_para u_i_r
- (
- .clka (i_clk ),
- .addra (i_r ),
- .ena (1'b1 ),
- .douta (o_r )
- );
- rom查表
-
- image_rom_log_para u_i_g
- (
- .clka (i_clk ),
- .addra (i_g ),
- .ena (1'b1 ),
- .douta (o_g )
- );
- rom查表
-
- image_rom_log_para u_i_b
- (
- .clka (i_clk ),
- .addra (i_b ),
- .ena (1'b1 ),
- .douta (o_b )
- );
-
- endmodule
-
- module image_rom_log_para
- (
- input clka,
- input [7:0] addra,
- input ena,
- output [7:0] douta
- );
- reg [7:0] DATA;
- assign douta = DATA;
- always@(*)
- begin
- case(addra)
- 0 : DATA <= 0;
- 1 : DATA <= 28;
- 2 : DATA <= 44;
- 3 : DATA <= 55;
- 4 : DATA <= 64;
- 5 : DATA <= 72;
- 6 : DATA <= 78;
- 7 : DATA <= 83;
- 8 : DATA <= 88;
- 9 : DATA <= 92;
- 10 : DATA <= 96;
- 11 : DATA <= 99;
- 12 : DATA <= 103;
- 13 : DATA <= 106;
- 14 : DATA <= 108;
- 15 : DATA <= 111;
- 16 : DATA <= 113;
- 17 : DATA <= 116;
- 18 : DATA <= 118;
- 19 : DATA <= 120;
- 20 : DATA <= 122;
- 21 : DATA <= 124;
- 22 : DATA <= 125;
- 23 : DATA <= 127;
- 24 : DATA <= 129;
- 25 : DATA <= 130;
- 26 : DATA <= 132;
- 27 : DATA <= 133;
- 28 : DATA <= 135;
- 29 : DATA <= 136;
- 30 : DATA <= 137;
- 31 : DATA <= 139;
- 32 : DATA <= 140;
- 33 : DATA <= 141;
- 34 : DATA <= 142;
- 35 : DATA <= 143;
- 36 : DATA <= 144;
- 37 : DATA <= 146;
- 38 : DATA <= 147;
- 39 : DATA <= 148;
- 40 : DATA <= 149;
- 41 : DATA <= 150;
- 42 : DATA <= 150;
- 43 : DATA <= 151;
- 44 : DATA <= 152;
- 45 : DATA <= 153;
- 46 : DATA <= 154;
- 47 : DATA <= 155;
- 48 : DATA <= 156;
- 49 : DATA <= 156;
- 50 : DATA <= 157;
- 51 : DATA <= 158;
- 52 : DATA <= 159;
- 53 : DATA <= 160;
- 54 : DATA <= 160;
- 55 : DATA <= 161;
- 56 : DATA <= 162;
- 57 : DATA <= 162;
- 58 : DATA <= 163;
- 59 : DATA <= 164;
- 60 : DATA <= 164;
- 61 : DATA <= 165;
- 62 : DATA <= 166;
- 63 : DATA <= 166;
- 64 : DATA <= 167;
- 65 : DATA <= 168;
- 66 : DATA <= 168;
- 67 : DATA <= 169;
- 68 : DATA <= 169;
- 69 : DATA <= 170;
- 70 : DATA <= 171;
- 71 : DATA <= 171;
- 72 : DATA <= 172;
- 73 : DATA <= 172;
- 74 : DATA <= 173;
- 75 : DATA <= 173;
- 76 : DATA <= 174;
- 77 : DATA <= 174;
- 78 : DATA <= 175;
- 79 : DATA <= 175;
- 80 : DATA <= 176;
- 81 : DATA <= 176;
- 82 : DATA <= 177;
- 83 : DATA <= 177;
- 84 : DATA <= 178;
- 85 : DATA <= 178;
- 86 : DATA <= 179;
- 87 : DATA <= 179;
- 88 : DATA <= 180;
- 89 : DATA <= 180;
- 90 : DATA <= 180;
- 91 : DATA <= 181;
- 92 : DATA <= 181;
- 93 : DATA <= 182;
- 94 : DATA <= 182;
- 95 : DATA <= 183;
- 96 : DATA <= 183;
- 97 : DATA <= 183;
- 98 : DATA <= 184;
- 99 : DATA <= 184;
- 100 : DATA <= 185;
- 101 : DATA <= 185;
- 102 : DATA <= 185;
- 103 : DATA <= 186;
- 104 : DATA <= 186;
- 105 : DATA <= 187;
- 106 : DATA <= 187;
- 107 : DATA <= 187;
- 108 : DATA <= 188;
- 109 : DATA <= 188;
- 110 : DATA <= 188;
- 111 : DATA <= 189;
- 112 : DATA <= 189;
- 113 : DATA <= 189;
- 114 : DATA <= 190;
- 115 : DATA <= 190;
- 116 : DATA <= 190;
- 117 : DATA <= 191;
- 118 : DATA <= 191;
- 119 : DATA <= 191;
- 120 : DATA <= 192;
- 121 : DATA <= 192;
- 122 : DATA <= 192;
- 123 : DATA <= 193;
- 124 : DATA <= 193;
- 125 : DATA <= 193;
- 126 : DATA <= 194;
- 127 : DATA <= 194;
- 128 : DATA <= 194;
- 129 : DATA <= 195;
- 130 : DATA <= 195;
- 131 : DATA <= 195;
- 132 : DATA <= 196;
- 133 : DATA <= 196;
- 134 : DATA <= 196;
- 135 : DATA <= 197;
- 136 : DATA <= 197;
- 137 : DATA <= 197;
- 138 : DATA <= 197;
- 139 : DATA <= 198;
- 140 : DATA <= 198;
- 141 : DATA <= 198;
- 142 : DATA <= 199;
- 143 : DATA <= 199;
- 144 : DATA <= 199;
- 145 : DATA <= 199;
- 146 : DATA <= 200;
- 147 : DATA <= 200;
- 148 : DATA <= 200;
- 149 : DATA <= 200;
- 150 : DATA <= 201;
- 151 : DATA <= 201;
- 152 : DATA <= 201;
- 153 : DATA <= 201;
- 154 : DATA <= 202;
- 155 : DATA <= 202;
- 156 : DATA <= 202;
- 157 : DATA <= 203;
- 158 : DATA <= 203;
- 159 : DATA <= 203;
- 160 : DATA <= 203;
- 161 : DATA <= 204;
- 162 : DATA <= 204;
- 163 : DATA <= 204;
- 164 : DATA <= 204;
- 165 : DATA <= 204;
- 166 : DATA <= 205;
- 167 : DATA <= 205;
- 168 : DATA <= 205;
- 169 : DATA <= 205;
- 170 : DATA <= 206;
- 171 : DATA <= 206;
- 172 : DATA <= 206;
- 173 : DATA <= 206;
- 174 : DATA <= 207;
- 175 : DATA <= 207;
- 176 : DATA <= 207;
- 177 : DATA <= 207;
- 178 : DATA <= 207;
- 179 : DATA <= 208;
- 180 : DATA <= 208;
- 181 : DATA <= 208;
- 182 : DATA <= 208;
- 183 : DATA <= 209;
- 184 : DATA <= 209;
- 185 : DATA <= 209;
- 186 : DATA <= 209;
- 187 : DATA <= 209;
- 188 : DATA <= 210;
- 189 : DATA <= 210;
- 190 : DATA <= 210;
- 191 : DATA <= 210;
- 192 : DATA <= 211;
- 193 : DATA <= 211;
- 194 : DATA <= 211;
- 195 : DATA <= 211;
- 196 : DATA <= 211;
- 197 : DATA <= 212;
- 198 : DATA <= 212;
- 199 : DATA <= 212;
- 200 : DATA <= 212;
- 201 : DATA <= 212;
- 202 : DATA <= 213;
- 203 : DATA <= 213;
- 204 : DATA <= 213;
- 205 : DATA <= 213;
- 206 : DATA <= 213;
- 207 : DATA <= 214;
- 208 : DATA <= 214;
- 209 : DATA <= 214;
- 210 : DATA <= 214;
- 211 : DATA <= 214;
- 212 : DATA <= 214;
- 213 : DATA <= 215;
- 214 : DATA <= 215;
- 215 : DATA <= 215;
- 216 : DATA <= 215;
- 217 : DATA <= 215;
- 218 : DATA <= 216;
- 219 : DATA <= 216;
- 220 : DATA <= 216;
- 221 : DATA <= 216;
- 222 : DATA <= 216;
- 223 : DATA <= 216;
- 224 : DATA <= 217;
- 225 : DATA <= 217;
- 226 : DATA <= 217;
- 227 : DATA <= 217;
- 228 : DATA <= 217;
- 229 : DATA <= 218;
- 230 : DATA <= 218;
- 231 : DATA <= 218;
- 232 : DATA <= 218;
- 233 : DATA <= 218;
- 234 : DATA <= 218;
- 235 : DATA <= 219;
- 236 : DATA <= 219;
- 237 : DATA <= 219;
- 238 : DATA <= 219;
- 239 : DATA <= 219;
- 240 : DATA <= 219;
- 241 : DATA <= 220;
- 242 : DATA <= 220;
- 243 : DATA <= 220;
- 244 : DATA <= 220;
- 245 : DATA <= 220;
- 246 : DATA <= 220;
- 247 : DATA <= 221;
- 248 : DATA <= 221;
- 249 : DATA <= 221;
- 250 : DATA <= 221;
- 251 : DATA <= 221;
- 252 : DATA <= 221;
- 253 : DATA <= 221;
- 254 : DATA <= 222;
- 255 : DATA <= 222;
- default: DATA<= 0;
- endcase
- end
- endmodule
复制代码
4.2工程结构图像数据通过摄像头采集进来,先缓存在fifo中,然后通过写状态机,将图像数据送进DDR进行缓存,缓存后的图像数据从DDR中取出,通过读状态机送出到fifo中,然后算法处理模块在fifo中取出数据,完成数据处理后送到LCD进行显示输出。 5上板实验点击下载后,可以看到正常的输出如下所示,摄像头的分辨率为640x480
|