问答 店铺
热搜: ZYNQ FPGA discuz

QQ登录

只需一步,快速开始

微信登录

微信扫码,快速开始

微信扫一扫 分享朋友圈

已有 55 人浏览分享

开启左侧

FPGA图像处理-图像log对数变换

[复制链接]
55 0
安路-FPGA课程
安路课程: 图像算法 » 图像新手入门实验
安路系列: EG4
本帖最后由 UT发布 于 2025-3-31 16:10 编辑

1概述

本文简述了图像log对数变换的算法,讲解如何进行Verilog的算法实现,并进行上板实验。

2算法原理简介

对数变换可以将图像的低灰度值部分扩展,显示出低灰度部分更多的细节,将其高灰度值部分压缩,减少高灰度值部分的细节,从而达到强调图像低灰度部分的目的。

图像对数变换一般公式为:

g = c*log(1 + f)

其中c为常数系数,f为像素值范围0~255

如图所示,对数曲线在像素值较低的区域斜率较大,像素值较高的区域斜率比较低,所以图像经过对数变换之后,在较暗的区域对比度将得到提升,因而能增强图像暗部的细节。

image.jpg

3算法仿真
3.1Matlab算法仿真
3.1.1Matlab算法代码分析

Log运算算法部分:

  1. clear;clear all;clc;
  2. image_in = imread('lena_1280x720.jpg');
  3. [row,col,n] = size(image_in);
  4. image_in1=im2double(image_in);
  5. image_out=log_transform(image_in1);
  6. image_out1=mat2gray(log(1+double(image_in)));
  7. figure
  8. subplot(131);
  9. imshow(image_in), title('the original image');
  10. subplot(132);
  11. imshow(image_out), title('the translated image ');
  12. subplot(133);
  13. imshow(image_out1), title('the translated image 1');
  14. function image_out = log_transform(image_in)
  15. [m,n]=size(image_in);
  16. a=image_in;
  17. for i=1:m
  18.     for j=1:n
  19.         a(i,j)=40*log(image_in(i,j)+1);
  20.     end
  21. end
  22. image_out=mat2gray(a);
  23. end
  24. 使用matlab生成log系数的代码如下:
  25. clear;clear all;clc;
  26. % g = c*log(1 + f)  
  27. num = 256;
  28. f = [0:1:255];
  29. c =40;
  30. g = c*log(1+f);
  31. %=================================================================
  32. fid = fopen('log_para_256.coe','w');
  33. fprintf(fid,'memory_initialization_radix = 10;\n');
  34. fprintf(fid,'memory_initialization_vector =\n');
  35. for n = 1:num
  36.         log(n) = round(g(n));
  37. end
  38. for n = 1: num - 1
  39.     fprintf(fid,'%d, \n',log(n));
  40. end
  41. fprintf(fid,'%d;',log(256));
  42. fclose(fid);
  43. %=================================================================
  44. fid1 = fopen('../src/image_rom_log_para.v','w');
  45. fprintf(fid1,'module image_rom_log_para\n');
  46. fprintf(fid1,'(\n');
  47. fprintf(fid1,'        input                    clka,\n');
  48. fprintf(fid1,'        input                [7:0]        addra,\n');
  49. fprintf(fid1,'        input                                ena,\n');
  50. fprintf(fid1,'        output                [7:0]        douta\n');
  51. fprintf(fid1,');\n');
  52. fprintf(fid1,'reg [7:0] DATA;\n');
  53. fprintf(fid1,'assign        douta = DATA;\n');
  54. fprintf(fid1,'always@(*)\n');
  55. fprintf(fid1,'begin\n');
  56. fprintf(fid1,'        case(addra)\n');
  57. for n = 1:num
  58.         log(n) = round(g(n));
  59. end
  60. for n = 1: num
  61.     fprintf(fid1,'%d : DATA <= %d; \n',n-1,log(n));
  62. end
  63. fprintf(fid1,'         default:   DATA<= 0;\n');
  64. fprintf(fid1,'        endcase\n');
  65. fprintf(fid1,'end\n');
  66. fprintf(fid1,'endmodule\n');
  67. fclose(fid1);
  68. %=================================================================
  69. hold on
  70. plot(f);
  71. plot(g);
  72. legend('f','log g');
  73. hold off
复制代码
3.1.2Matlab实验结果
image.jpg

实验结果可以得出较暗的区域对比度将得到提升,增强了图像暗部的细节。

3.2Verilog算法仿真
3.2.1Modelsim仿真
3.2.1.1仿真执行

在件夹Algorithm_simulation下进行算法的仿真,分为simsrctb三个子文件夹。在sim文件夹下有win系统的快捷执行文件sim.bat,可以一键进行仿真,src文件下放的是Verilog的核心图像算法及其顶层与输入图像激励,tb文件下放的是测试激励文件及输出图像的保存。

双击执行sim文件夹下sim.bat,自动打开Modelsim仿真,自动添加仿真波形,执行完成后自动保存图像,仿真波形如图所示:

image.jpg
3.2.1.2仿真关键部分代码解析

Sim.do执行仿真代码,文件内容如下:

  1. #
  2. # Create work library
  3. #
  4. vlib work
  5. #
  6. # Compile sources
  7. #
  8. vlog "../src/*.v"
  9. vlog "../tb/*.v"
  10. #
  11. # Call vsim to invoke simulator
  12. #
  13. vsim -voptargs=+acc work.top_tb
  14. #
  15. # Add waves
  16. #
  17. do wave.do
  18. #
  19. # Run simulation
  20. #
  21. run -all
  22. #
  23. # End
复制代码

图像输入代码部分:

  1. reg                 en;
  2. reg [12:0]         h_syn_cnt = 'd0;
  3. reg [12:0]         v_syn_cnt = 'd0;
  4. reg [23:0]         image [0 : H_ACTIVE*V_ACTIVE-1];
  5. reg [31:0]         image_cnt = 'd0;
  6. //读取txt文件到image数组中
  7. initial begin
  8.         $readmemh("../../matlab_src/image_720_1280_3.txt", image);
  9. end
  10. // 行扫描计数器
  11. always@(posedge i_clk)
  12. begin
  13.         if(h_syn_cnt == H_TOTAL_TIME-1)
  14.         h_syn_cnt <= 0;
  15.     else
  16.         h_syn_cnt <= h_syn_cnt + 1;
  17. end
  18. // 列扫描计数器
  19. always@(posedge i_clk)
  20. begin
  21.         if(h_syn_cnt == H_TOTAL_TIME-1)
  22.         begin
  23.         if(v_syn_cnt == V_TOTAL_TIME-1)
  24.             v_syn_cnt <= 0;
  25.         else
  26.             v_syn_cnt <= v_syn_cnt + 1;
  27.         end
  28. end
  29. // 行同步控制
  30. always@(posedge i_clk)
  31. begin
  32.     if(h_syn_cnt < H_SYNC_TIME)
  33.         o_hsyn <= 0;
  34.     else
  35.         o_hsyn <= 1;
  36. end
  37. // 场同步控制
  38. always@(posedge i_clk)
  39. begin
  40.     if(v_syn_cnt < V_SYNC_TIME)
  41.         o_vsyn <= 0;
  42.     else
  43.         o_vsyn <= 1;
  44. end
  45. // 坐标使能.
  46. always@(posedge i_clk)
  47. begin
  48.     if(v_syn_cnt >= V_SYNC_TIME + V_BACK_PORCH && v_syn_cnt < V_SYNC_TIME + V_BACK_PORCH + V_ACTIVE)
  49.     begin
  50.         if(h_syn_cnt >= H_SYNC_TIME + H_BACK_PORCH && h_syn_cnt < H_SYNC_TIME + H_BACK_PORCH + H_ACTIVE)
  51.             en <= 1;
  52.         else
  53.             en <= 0;
  54.     end
  55.     else
  56.         en <= 0;
  57. end
  58. always@(posedge i_clk)
  59. begin
  60.     if(en)
  61.         begin
  62.                 o_r                 <= image[image_cnt][23:16];
  63.                 o_g                 <= image[image_cnt][15:8];
  64.                 o_b                 <= image[image_cnt][7:0];
  65.             image_cnt         <= image_cnt + 1;
  66.         end
  67.         else if(image_cnt == H_ACTIVE*V_ACTIVE)
  68.         begin
  69.                 o_r                 <= 8'h00;
  70.                 o_g                 <= 8'h00;
  71.                 o_b                 <= 8'h00;
  72.             image_cnt         <= 'd0;
  73.         end        
  74.     else
  75.         begin
  76.                 o_r                 <= 8'h00;
  77.                 o_g                 <= 8'h00;
  78.                 o_b                 <= 8'h00;
  79.             image_cnt         <= image_cnt;
  80.         end        
  81. end
  82. always@(posedge i_clk)
  83. begin
  84.         o_en <= en;
  85. end
复制代码

图形输出保存代码部分:

  1. reg             clk;
  2. reg             rst_n;
  3. integer                 image_txt;
  4. reg [31:0]                 pixel_cnt;
  5. wire[23:0]          data;
  6. wire            de;
  7. top u_top
  8. (
  9.     .i_clk                              (clk                ),
  10.     .i_rst_n                      (rst_n              ),
  11.     .o_gray_data             (data               ),
  12.     .o_gray_de               (de                 )
  13. );
  14. always #(1) clk = ~clk;
  15. initial
  16. begin
  17.         clk   = 1;
  18.     rst_n = 0;         
  19.         #100
  20.     rst_n = 1;
  21.         
  22. end
  23. initial
  24. begin
  25.     image_txt = $fopen("../matlab_src/image_720_1280_3_out.txt");
  26. end
  27. always@(posedge clk or negedge rst_n)
  28. begin
  29.     if(!rst_n)
  30.         begin
  31.         pixel_cnt <= 0;
  32.     end
  33.     else if(de)
  34.         begin
  35.         pixel_cnt = pixel_cnt + 1;
  36.         $fwrite(image_txt,"%h\n",data);
  37.     end
  38. end
  39. always@(posedge clk )
  40. begin
  41.         if(pixel_cnt == 720*1280)
  42.         begin
  43.                 $display("*******************************************************************************");               
  44.                 $display("*** Success:image_720_1280_3_out.txt is output complete! %t", $realtime, "ps***");
  45.                 $display("*******************************************************************************");
  46.                         $fclose(image_txt);
  47.                 $stop;
  48.         end        
  49. end
复制代码
3.2.2Modelsim实验结果

matlab查看输入输出的图像代码部分:

  1. clear;clear all;clc;
  2. row = 720;  
  3. col = 1280;  
  4. n   = 3;   
  5. image_sim_pass = uint8(zeros(row,col,n));
  6. fid = fopen('image_720_1280_3_out.txt','r');
  7. for x = 1:row
  8.     for y = 1:col
  9.         RGB = fscanf(fid,'%s',1);
  10.         image_sim_pass(x,y,1) = uint8(hex2dec(RGB(1:2)));
  11.         image_sim_pass(x,y,2) = uint8(hex2dec(RGB(3:4)));
  12.         image_sim_pass(x,y,3) = uint8(hex2dec(RGB(5:6)));              
  13.     end
  14. end
  15. fclose(fid);
  16. image_1 = imread('lena_1280x720.jpg');
  17. subplot(121);
  18. imshow(image_1), title('The original image');
  19. subplot(122);
  20. imshow(image_sim_pass),title('After processing images');
  21. imwrite(image_sim_pass,'lena_1280x720_sim_pass.jpg');   
复制代码

如图所示,仿真结果:

image.jpg
4工程实现
4.1Verilog代码分析

由于提前使用matlab计算好了log系数,这里代码很简单直接查表就行。

  1. //同步输出使能信号
  2.         assign o_hs = i_hsyn;
  3.         assign o_vs = i_vsyn;
  4.         assign o_en = i_en;
  5. rom查表
  6. image_rom_log_para u_i_r
  7. (
  8.         .clka        (i_clk                ),
  9.         .addra        (i_r                ),
  10.         .ena        (1'b1                ),
  11.         .douta        (o_r                )
  12. );
  13. rom查表
  14. image_rom_log_para u_i_g
  15. (
  16.         .clka        (i_clk                ),
  17.         .addra        (i_g                ),
  18.         .ena        (1'b1                ),
  19.         .douta        (o_g                )
  20. );
  21. rom查表
  22. image_rom_log_para u_i_b
  23. (
  24.         .clka        (i_clk                ),
  25.         .addra        (i_b                ),
  26.         .ena        (1'b1                ),
  27.         .douta        (o_b                )
  28. );
  29. endmodule
  30. module image_rom_log_para
  31. (
  32.         input                    clka,
  33.         input                [7:0]        addra,
  34.         input                                ena,
  35.         output                [7:0]        douta
  36. );
  37. reg [7:0] DATA;
  38. assign        douta = DATA;
  39. always@(*)
  40. begin
  41.         case(addra)
  42. 0 : DATA <= 0;
  43. 1 : DATA <= 28;
  44. 2 : DATA <= 44;
  45. 3 : DATA <= 55;
  46. 4 : DATA <= 64;
  47. 5 : DATA <= 72;
  48. 6 : DATA <= 78;
  49. 7 : DATA <= 83;
  50. 8 : DATA <= 88;
  51. 9 : DATA <= 92;
  52. 10 : DATA <= 96;
  53. 11 : DATA <= 99;
  54. 12 : DATA <= 103;
  55. 13 : DATA <= 106;
  56. 14 : DATA <= 108;
  57. 15 : DATA <= 111;
  58. 16 : DATA <= 113;
  59. 17 : DATA <= 116;
  60. 18 : DATA <= 118;
  61. 19 : DATA <= 120;
  62. 20 : DATA <= 122;
  63. 21 : DATA <= 124;
  64. 22 : DATA <= 125;
  65. 23 : DATA <= 127;
  66. 24 : DATA <= 129;
  67. 25 : DATA <= 130;
  68. 26 : DATA <= 132;
  69. 27 : DATA <= 133;
  70. 28 : DATA <= 135;
  71. 29 : DATA <= 136;
  72. 30 : DATA <= 137;
  73. 31 : DATA <= 139;
  74. 32 : DATA <= 140;
  75. 33 : DATA <= 141;
  76. 34 : DATA <= 142;
  77. 35 : DATA <= 143;
  78. 36 : DATA <= 144;
  79. 37 : DATA <= 146;
  80. 38 : DATA <= 147;
  81. 39 : DATA <= 148;
  82. 40 : DATA <= 149;
  83. 41 : DATA <= 150;
  84. 42 : DATA <= 150;
  85. 43 : DATA <= 151;
  86. 44 : DATA <= 152;
  87. 45 : DATA <= 153;
  88. 46 : DATA <= 154;
  89. 47 : DATA <= 155;
  90. 48 : DATA <= 156;
  91. 49 : DATA <= 156;
  92. 50 : DATA <= 157;
  93. 51 : DATA <= 158;
  94. 52 : DATA <= 159;
  95. 53 : DATA <= 160;
  96. 54 : DATA <= 160;
  97. 55 : DATA <= 161;
  98. 56 : DATA <= 162;
  99. 57 : DATA <= 162;
  100. 58 : DATA <= 163;
  101. 59 : DATA <= 164;
  102. 60 : DATA <= 164;
  103. 61 : DATA <= 165;
  104. 62 : DATA <= 166;
  105. 63 : DATA <= 166;
  106. 64 : DATA <= 167;
  107. 65 : DATA <= 168;
  108. 66 : DATA <= 168;
  109. 67 : DATA <= 169;
  110. 68 : DATA <= 169;
  111. 69 : DATA <= 170;
  112. 70 : DATA <= 171;
  113. 71 : DATA <= 171;
  114. 72 : DATA <= 172;
  115. 73 : DATA <= 172;
  116. 74 : DATA <= 173;
  117. 75 : DATA <= 173;
  118. 76 : DATA <= 174;
  119. 77 : DATA <= 174;
  120. 78 : DATA <= 175;
  121. 79 : DATA <= 175;
  122. 80 : DATA <= 176;
  123. 81 : DATA <= 176;
  124. 82 : DATA <= 177;
  125. 83 : DATA <= 177;
  126. 84 : DATA <= 178;
  127. 85 : DATA <= 178;
  128. 86 : DATA <= 179;
  129. 87 : DATA <= 179;
  130. 88 : DATA <= 180;
  131. 89 : DATA <= 180;
  132. 90 : DATA <= 180;
  133. 91 : DATA <= 181;
  134. 92 : DATA <= 181;
  135. 93 : DATA <= 182;
  136. 94 : DATA <= 182;
  137. 95 : DATA <= 183;
  138. 96 : DATA <= 183;
  139. 97 : DATA <= 183;
  140. 98 : DATA <= 184;
  141. 99 : DATA <= 184;
  142. 100 : DATA <= 185;
  143. 101 : DATA <= 185;
  144. 102 : DATA <= 185;
  145. 103 : DATA <= 186;
  146. 104 : DATA <= 186;
  147. 105 : DATA <= 187;
  148. 106 : DATA <= 187;
  149. 107 : DATA <= 187;
  150. 108 : DATA <= 188;
  151. 109 : DATA <= 188;
  152. 110 : DATA <= 188;
  153. 111 : DATA <= 189;
  154. 112 : DATA <= 189;
  155. 113 : DATA <= 189;
  156. 114 : DATA <= 190;
  157. 115 : DATA <= 190;
  158. 116 : DATA <= 190;
  159. 117 : DATA <= 191;
  160. 118 : DATA <= 191;
  161. 119 : DATA <= 191;
  162. 120 : DATA <= 192;
  163. 121 : DATA <= 192;
  164. 122 : DATA <= 192;
  165. 123 : DATA <= 193;
  166. 124 : DATA <= 193;
  167. 125 : DATA <= 193;
  168. 126 : DATA <= 194;
  169. 127 : DATA <= 194;
  170. 128 : DATA <= 194;
  171. 129 : DATA <= 195;
  172. 130 : DATA <= 195;
  173. 131 : DATA <= 195;
  174. 132 : DATA <= 196;
  175. 133 : DATA <= 196;
  176. 134 : DATA <= 196;
  177. 135 : DATA <= 197;
  178. 136 : DATA <= 197;
  179. 137 : DATA <= 197;
  180. 138 : DATA <= 197;
  181. 139 : DATA <= 198;
  182. 140 : DATA <= 198;
  183. 141 : DATA <= 198;
  184. 142 : DATA <= 199;
  185. 143 : DATA <= 199;
  186. 144 : DATA <= 199;
  187. 145 : DATA <= 199;
  188. 146 : DATA <= 200;
  189. 147 : DATA <= 200;
  190. 148 : DATA <= 200;
  191. 149 : DATA <= 200;
  192. 150 : DATA <= 201;
  193. 151 : DATA <= 201;
  194. 152 : DATA <= 201;
  195. 153 : DATA <= 201;
  196. 154 : DATA <= 202;
  197. 155 : DATA <= 202;
  198. 156 : DATA <= 202;
  199. 157 : DATA <= 203;
  200. 158 : DATA <= 203;
  201. 159 : DATA <= 203;
  202. 160 : DATA <= 203;
  203. 161 : DATA <= 204;
  204. 162 : DATA <= 204;
  205. 163 : DATA <= 204;
  206. 164 : DATA <= 204;
  207. 165 : DATA <= 204;
  208. 166 : DATA <= 205;
  209. 167 : DATA <= 205;
  210. 168 : DATA <= 205;
  211. 169 : DATA <= 205;
  212. 170 : DATA <= 206;
  213. 171 : DATA <= 206;
  214. 172 : DATA <= 206;
  215. 173 : DATA <= 206;
  216. 174 : DATA <= 207;
  217. 175 : DATA <= 207;
  218. 176 : DATA <= 207;
  219. 177 : DATA <= 207;
  220. 178 : DATA <= 207;
  221. 179 : DATA <= 208;
  222. 180 : DATA <= 208;
  223. 181 : DATA <= 208;
  224. 182 : DATA <= 208;
  225. 183 : DATA <= 209;
  226. 184 : DATA <= 209;
  227. 185 : DATA <= 209;
  228. 186 : DATA <= 209;
  229. 187 : DATA <= 209;
  230. 188 : DATA <= 210;
  231. 189 : DATA <= 210;
  232. 190 : DATA <= 210;
  233. 191 : DATA <= 210;
  234. 192 : DATA <= 211;
  235. 193 : DATA <= 211;
  236. 194 : DATA <= 211;
  237. 195 : DATA <= 211;
  238. 196 : DATA <= 211;
  239. 197 : DATA <= 212;
  240. 198 : DATA <= 212;
  241. 199 : DATA <= 212;
  242. 200 : DATA <= 212;
  243. 201 : DATA <= 212;
  244. 202 : DATA <= 213;
  245. 203 : DATA <= 213;
  246. 204 : DATA <= 213;
  247. 205 : DATA <= 213;
  248. 206 : DATA <= 213;
  249. 207 : DATA <= 214;
  250. 208 : DATA <= 214;
  251. 209 : DATA <= 214;
  252. 210 : DATA <= 214;
  253. 211 : DATA <= 214;
  254. 212 : DATA <= 214;
  255. 213 : DATA <= 215;
  256. 214 : DATA <= 215;
  257. 215 : DATA <= 215;
  258. 216 : DATA <= 215;
  259. 217 : DATA <= 215;
  260. 218 : DATA <= 216;
  261. 219 : DATA <= 216;
  262. 220 : DATA <= 216;
  263. 221 : DATA <= 216;
  264. 222 : DATA <= 216;
  265. 223 : DATA <= 216;
  266. 224 : DATA <= 217;
  267. 225 : DATA <= 217;
  268. 226 : DATA <= 217;
  269. 227 : DATA <= 217;
  270. 228 : DATA <= 217;
  271. 229 : DATA <= 218;
  272. 230 : DATA <= 218;
  273. 231 : DATA <= 218;
  274. 232 : DATA <= 218;
  275. 233 : DATA <= 218;
  276. 234 : DATA <= 218;
  277. 235 : DATA <= 219;
  278. 236 : DATA <= 219;
  279. 237 : DATA <= 219;
  280. 238 : DATA <= 219;
  281. 239 : DATA <= 219;
  282. 240 : DATA <= 219;
  283. 241 : DATA <= 220;
  284. 242 : DATA <= 220;
  285. 243 : DATA <= 220;
  286. 244 : DATA <= 220;
  287. 245 : DATA <= 220;
  288. 246 : DATA <= 220;
  289. 247 : DATA <= 221;
  290. 248 : DATA <= 221;
  291. 249 : DATA <= 221;
  292. 250 : DATA <= 221;
  293. 251 : DATA <= 221;
  294. 252 : DATA <= 221;
  295. 253 : DATA <= 221;
  296. 254 : DATA <= 222;
  297. 255 : DATA <= 222;
  298.          default:   DATA<= 0;
  299.         endcase
  300. end
  301. endmodule
复制代码
4.2工程结构

工程结构如图所示:

image.jpg

图像数据通过摄像头采集进来,先缓存在fifo中,然后通过写状态机,将图像数据送进DDR进行缓存,缓存后的图像数据从DDR中取出,通过读状态机送出到fifo中,然后算法处理模块在fifo中取出数据,完成数据处理后送到LCD进行显示输出。

5上板实验
image.jpg

点击下载后,可以看到正常的输出如下所示,摄像头的分辨率为640x480

image.jpg



您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

0

关注

0

粉丝

269

主题
精彩推荐
热门资讯
网友晒图
图文推荐

  • 微信公众平台

  • 扫描访问手机版