本帖最后由 FPGA课程 于 2024-10-17 13:24 编辑
软件版本:VIVADO2021.1
操作系统:WIN10 64bit
硬件平台:适用 XILINX A7/K7/Z7/ZU/KU 系列 FPGA
实验平台:米联客-MLK-H3-CZ08-7100开发板
板卡获取平台:https://milianke.tmall.com/
登录“米联客”FPGA社区 http://www.uisrc.com 视频课程、答疑解惑!
1 图像伽马变换算法简介
伽马变换主要用于图像的校正,将灰度过高或者灰度过低的图片进行修正,增强对比度,简单的说就是让图像 从曝光强度的线性响应变得更接近人眼感受的响应。变换公式就是对原图像上每一个像素值做乘积运算: g= c* rY 其中 c 为常数系数,r 为图像像素值,取值范围 0~255,Y为伽马变换因子,Y值以 1 为分界,值越小,对图像 低灰度部分的扩展作用就越强,值越大,对图像高灰度部分的扩展作用就越强,通过不同的Y值,就可以达到增强 低灰度或高灰度部分细节的作用。伽马变换对于图像对比度偏低,并且整体亮度值偏高(对于相机过曝)情况下的 图像增强效果明显。 伽马变换对图像的修正作用其实就是通过增强低灰度或高灰度的细节实现的,从伽马曲线可以直观理解:
我们之所以对图像进行 gamma 变换是因为人眼对外界光源的感光值与输入光强不是呈线性关系的,而是呈指 数型关系的。在低照度下,人眼更容易分辨出亮度的变化,随着照度的增加,人眼不易分辨出亮度的变化。而摄像 机感光与输入光强呈线性关系。为能更有效的保存图像亮度信息,需进行 Gamma 变换。未经 Gamma 变换和经过 Gamma 变换保存图像信息如下图:可以观察到,未经 Gamma 变换的情况下,低灰度时,有较大范围的灰度值被保 存成同一个值,造成信息丢失;同时高灰度值时,很多比较接近的灰度值却被保存成不同的值,造成空间浪费。经 过 Gamma 变换后,改善了存储的有效性和效率。 下图中第一幅图为原图,第二幅图系数为 0.75,第三幅图系数为 1.5。由图中显示的信息可得第二幅比第一幅 图明显增亮,第三幅图则比第一幅图更暗淡。
2 设计分析2.1Matlab代码分析 - [row,col,n] = size(image_in);
- image_out =imadjust(image_in,[],[],0.75); %imadjust 对图像灰度进行调整并调高亮度,第一个[]为原图中要变换 的灰度范围,第二个[]为变换后的灰度范围
- image_out1=imadjust(image_in,[],[],1.5);
- 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');
- //使用matlab 生成伽马变换后系数的代码如下: clear;clear all;clc;
- num = 256;
- r = [0:1:255];
- c =16;
- g = c*sqrt(r);
- %==========================写.coe 文件========================== fid = fopen('gamma_sqrt_para_256.coe','w');
- fprintf(fid,'memory_initialization_radix = 10;\n'); fprintf(fid,'memory_initialization_vector =\n');
- for n = 1:num
- gamma(n) = round(g(n)); end
- for n = 1: num - 1
- fprintf(fid,'%d, \n',gamma(n)); end
- fprintf(fid,'%d;',gamma(256)); fclose(fid);
- %============================写 rom 存储器=============================== fid1 = fopen('../src/image_rom_gamma_sqrt_para.v','w');
- fprintf(fid1,'module image_rom_gamma_sqrt_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
- gamma(n) = round(g(n)); end
- for n = 1: num
- fprintf(fid1,'%d : DATA <= %d; \n',n-1,gamma(n)); end
- fprintf(fid1,' default: DATA<= 0;\n');
- fprintf(fid1,' endcase\n'); fprintf(fid1,'end\n');
- fprintf(fid1,'endmodule\n'); fclose(fid1);
- %=================================================================
- g1 = (r.^2)/255; %系数为 1
- %================================================================= fid = fopen('gamma_square_para_256.coe','w');
- fprintf(fid,'memory_initialization_radix = 10;\n'); fprintf(fid,'memory_initialization_vector =\n');
- for n = 1:num
- gamma(n) = round(g1(n)); end
- for n = 1: num - 1
- fprintf(fid,'%d, \n',gamma(n)); end
- fprintf(fid,'%d;',gamma(256)); fclose(fid);
- %================================================================= fid1 = fopen('../src/image_rom_gamma_square_para.v','w');
- fprintf(fid1,'module image_rom_gamma_square_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
- gamma(n) = round(g1(n)); end
- for n = 1: num
- fprintf(fid1,'%d : DATA <= %d; \n',n-1,gamma(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(r);
- plot(g);
- plot(g1);
- legend('f','gamma g','gamma g1');
- hold off
复制代码
2.2Verilog代码分析 由于提前使用 matlab 计算好了伽马变换后的值,这里代码很简单直接查表就行。 - assign o_hs = i_hsyn; assign o_vs = i_vsyn; assign o_en = i_en;
- generate
- if (GAMMA_ALGORITHM == "GAMMA_SQUARE") begin
- image_rom_gamma_square_para u i r (
- .clka(i_clk ),
- .addra (i_r ),
- .ena (1'b1 ),
- .douta (o_r )
- );
- image_rom_gamma_square_para u_i_g (
- .clka(i_clk ),
- .addra (i_g ),
- .ena (1'b1 ),
- .douta (o_g )
- );
- image_rom_gamma_square_para u i b (
- .clka(i_clk ),
- .addra (i_g ),
- .ena (1'b1 ),
- .douta (o_b )
- ); end
- elseif(GAMMA_ALGORITHM == "GAMMA_SQRT") begin
- image_rom_gamma_sqrt_para u i r (
- .clka(i_clk ),
- .addra (i_r ),
- .ena (1'b1 ),
- .douta (o_r )
- );
- image_rom_gamma_sqrt_para u_i_g (
- .clka(i_clk ),
- .addra (i_g ),
- .ena (1'b1 ),
- .douta (o_g )
- );
- image_rom_gamma_sqrt_para u i b (
- .clka(i_clk ),
- .addra (i_g ),
- .ena (1'b1 ),
- .douta (o_b )
- ); end
- endgenerate
复制代码
3 工程结构分析
我们将图像 GAMMA 变换的模块做成 IP 后,在vivado 中进行工程的搭建,工程结构如图所示:
4 仿真及结果
4.1Matlab实验结果
4.2Modelsim实验结果
5 搭建 Vitis-sdk 工程创建 soc_base sdk platform 和 APP 工程的过程不再重复,可以阅读 3-3-01_sdk_base_app。以下给出创建好 soc_base sdk platform 的截图和对应工程 APP 的截图。 5.1 创建 SDKPlatform工程
5.2SDKAPP工程
6 硬件连接
硬件连接如图所示:
7 上板实验结果实验结果如图所示:
|