当前位置:首页 > > FPGA开源工作室


基于FPGA的灰度图像处理之幂律(伽马变化

1 背景知识

幂律变换的基本形式为:

----------------------------------------------------------------------------------------(1)

其中c和r为正常数。有时考虑到偏移量 可将式(1)写为

------------------------------------------------------------------------------------(2)

偏移量一般是显示标定问题,作为一个结果,通常在式(1)中忽略不计。对于不同的值,s与r的关系如图1所示。

1 r变换曲线

与对数变换的情况类似,部分r值的幂律曲线将较窄范围的暗色输入值映射为较宽范围的输出值,相反的,对于输入高灰度级值时也成立。然而与对数函数不同的是,随着r值的变化,将简单地得到一簇可能的变化曲线。如图1所示,r>1的值所生成的曲线和r<1的值所生成的曲线的效果完全相反。当c=r=1时简化成了恒等变换。

用于图像获取,打印和显示的各种设备根据幂律来产生响应。习惯上,幂律方程中的指数称为伽马。用于校正这些幂律响应现象的处理称为伽马校正。

2 航拍图幂律变换

如图2所示,a航拍原图b~dc=1且分别等于3.0,4.05.0时应用式(1)给出的变换的结果(此例的原图像由NASA提供)。

2 FPGA实现

3 FPGA实现幂律变换框架图

由图2可知对于灰度图像直接经过幂律变换就可以得到幂律变换图像,但是对于FPGA直接实现对数公式显然难度很大。在FPGA中我们采用基于查找表的方式进行幂律变换。

ROM表的制作:

Matlab源码:

clear all

close all

clc

depth = 256;

width =8;

r = [0:1:255];

x = r; %恒等变换

y =16*sqrt(r);%开根

%z = round(y);

m = (1/256)*r.^2; %r平方

z = round(m);

fid = fopen('E:\matlab_project\log\square.mif','w');%路径

fprintf(fid,'depth= %d; \n',depth);

fprintf(fid,'width= %d; \n',width);

fprintf(fid,'address_radix=uns;\n');

fprintf(fid,'data_radix = uns;\n');

fprintf(fid,'Content Begin \n');

for(k=1:depth)

fprintf(fid,'%d: %d; \n',k-1,z(k));

end

fprintf(fid,'end;');

hold on

plot(x);

plot(y);

plot(m);

hold off

FPGA源码

//------------------------------------------

// power law

//------------------------------------------

wire [7:0] sqrt_data; //root

wire [7:0] square_data;//square

rom_sqrt rom_sqrt_inst(

.address(o_y_8b),

.clken(TFT_de),

.clock(TFT_clk),

.q(sqrt_data)

);

rom_square rom_square_inst(

.address(o_y_8b),

.clken(TFT_de),

.clock(TFT_clk),

.q(square_data)

);

//assign TFT_rgb = {sqrt_data[7:3],sqrt_data[7:2],sqrt_data[7:3]};     //Y

assign TFT_rgb = {square_data[7:3],square_data[7:2],square_data[7:3]}; //Y

//assign TFT_rgb = {o_y_8b[7:3],o_y_8b[7:2],o_y_8b[7:3]};     //Y

实验结果:

4 原图

5原图灰度显示

6整体变暗

7整体变亮

结果分析:

6、图7和图5相比,图6明显变暗,图7明显变亮。此技术可以应用在图像采集系统上,当拍摄的光线较暗时,我们可以采取亮变换;当光线过强时,我们可以采取暗变化,从而达到人眼更适合的效果。

3 基于ov5640的图像采集系统的幂律变换移植

verilog源码:

//------------------------------------------

// power law

//------------------------------------------

wire [7:0] sqrt_data; //root

wire [7:0] sqrt_r_data; //root

wire [7:0] sqrt_g_data; //root

wire [7:0] sqrt_b_data; //root

wire [7:0] square_data;//square

wire [7:0] square_r_data;//square

wire [7:0] square_g_data;//square

wire [7:0] square_b_data;//square

rom_sqrt rom_sqrt_r_inst(

.address({rgb[15:11],3'b0}),

.clken(TFT_DE),

.clock(TFT_VCLK),

.q(sqrt_r_data)

);


rom_sqrt rom_sqrt_g_inst(

.address({rgb[10:5],2'b0}),

.clken(TFT_DE),

.clock(TFT_VCLK),

.q(sqrt_g_data)

);


rom_sqrt rom_sqrt_b_inst(

.address({rgb[4:0],3'b0}),

.clken(TFT_DE),

.clock(TFT_VCLK),

.q(sqrt_b_data)

);


rom_square rom_square_r_inst(

.address({rgb[15:11],3'b0}),

.clken(TFT_DE),

.clock(TFT_VCLK),

.q(square_r_data)

);

rom_square rom_square_g_inst(

.address({rgb[10:5],2'b0}),

.clken(TFT_DE),

.clock(TFT_VCLK),

.q(square_g_data)

);

rom_square rom_square_b_inst(

.address({rgb[4:0],3'b0}),

.clken(TFT_DE),

.clock(TFT_VCLK),

.q(square_b_data)

);


assign TFT_RGB = {square_r_data[7:3],square_g_data[7:2],square_b_data[7:3]};

//Y The image darker

//assign TFT_RGB = {sqrt_r_data[7:3],sqrt_g_data[7:2],sqrt_b_data[7:3]};

//Y  Image brighter

源码解释:

通过对R,G,B三个通道进行square处理后合成新的16bitRGB数据整个图像彩色相比较原RGB图像变暗;通过对R,G,B三个通道进行root处理后合成新的16bitRGB数据整个图像彩色相比较原RGB图像变亮。

有兴趣的同学可以将square数据和sqrt数据线性叠加来输出彩色图像或者与RGB原通道数据进行线性叠加。结果将是下图:

我们可以调整彩色的不同明亮度来达到不同的效果。

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
关闭