FPGA与Matlab图像处理之伽马校正


一、什么是伽马校正?

  Gamma校正是图像处理中用以调整图像的亮度和对比度来改善图像质量的。Gamma校正是基于人眼对亮度的感知非线性,人眼对亮度的敏感度随着亮度的增加而减少,也就是人眼在图像亮度较低时,人眼对亮度的变换更敏感。例如:人眼在夜晚很容易看见萤火虫,而在白天不容易看到天空中飞翔的鸟。伽马曲线如下所示:

在这里插入图片描述

二、伽马校正的由来

  早期的显示设备(如CRT显示器)在处理光信号时表现出非线性特性。CRT显示器的亮度输出与输入信号的电压之间存在幂律关系:
O = I Y O=I^{Y} O=IY

  Y就是所说的伽马值,例如:给 CRT 显示器输入一个 0.5(I=0.5), CRT 显示器的输出O输出 0.218,输入与输出间存在一个指数大概为 2.2 的幂次关系(这是人们根据实践总结出来的值)。
  不同的Y对于的曲线不一样:

在这里插入图片描述

  • 当伽马值小于1时,会拉伸图像中灰度较低的区域,同时压缩图像中灰度较高的区域,使得图像的暗部变亮,亮度变暗。
  • 当伽马值大于1时,会拉伸图像中灰度较高的区域,同时压缩图像中灰度较低的区域,使得图像的暗部变暗,亮度变亮。

三、Matlab实现伽马校正

  伽马校正就涉及到幂函数运算,直接使用运算就可以了:

3.1 matlab代码

clear all; close all; clc;
% 读取图像
img = imread('...\....\....\....\......\....\.....\dark.bmp'); 
grayImg = rgb2gray(img); % 转换为灰度图像

% 选择伽马值
gamma1 = 2.2; % 例如,使用伽马值2.2
gamma2 = 0.5; % 例如,使用伽马值0.5
% 归一化像素值
normalizedImg = double(grayImg) / 255;

% 应用伽马校正
correctedImg1 = normalizedImg .^ gamma1;
correctedImg2 = normalizedImg .^ gamma2;

% 反归一化像素值
correctedImg1 = uint8(correctedImg1 * 255);
correctedImg2 = uint8(correctedImg2 * 255);

% 显示原始和校正后的图像
figure;
subplot(1, 3, 1);
imshow(grayImg);
title('原始图像');

subplot(1, 3, 2);
imshow(correctedImg1);
title('伽马2.2校正后的图像');

subplot(1, 3, 3);
imshow(correctedImg2);
title('伽马0.5校正后的图像');

3.2 matlab结果

在这里插入图片描述
  可以看到,伽马值2.2使得图像画面亮度部分更亮,暗部部分更暗了,伽马值为0.5使得图像画面亮度部分变暗,暗部部分变亮了。我们不显示灰度图像,直接显示彩色图片:

在这里插入图片描述
  这样也非常的明显看到伽马值对图像亮部暗部的变化。

四、Verilog实现伽马校正

4.1 生成初始化ROM文件

  我们从公式可以看到伽马校正涉及到的是幂函数,但是fpga不擅长处理幂函数,因此我们可以使用一个rom来提前存放好0-255灰阶的幂函数,这样我们输入一个灰度值作为rom的读地址,就能直接得到新的灰度值,ROM的初始文件用Matlab生成,代码如下:

 clear all; close all; clc;
% 设定伽马值
gammaValue = 2.2; % 替换为你想要的伽马值

% 生成伽马校正表
LUT = zeros(256, 1);
for i = 0:255
    LUT(i + 1) = round((i / 255) ^ gammaValue * 255);
end

% 生成MIF文件
mifFileName = 'gamma_correction.mif'; % MIF文件名
fileID = fopen(mifFileName, 'w');

% 写入MIF文件头
fprintf(fileID, 'DEPTH = 256;\n');
fprintf(fileID, 'WIDTH = 8;\n');
fprintf(fileID, 'ADDRESS_RADIX = HEX;\n');
fprintf(fileID, 'DATA_RADIX = HEX;\n');
fprintf(fileID, 'CONTENT BEGIN\n');

% 写入LUT数据
for i = 0:255
    fprintf(fileID, '%02X : %02X;\n', i, LUT(i + 1));
end

fprintf(fileID, 'END;\n');

% 关闭文件
fclose(fileID);

  生成的coe文件如下:
在这里插入图片描述

4.2 Verilog代码

  代码很简单,就例化一个256深度,8位宽的ROM,然后把COE文件烧录进去,输入的灰度图像数据作为ROM的读地址,其他的信号都打一拍输出即可,代码如下:

`timescale 1ns / 1ps

module gamma_map(
    input                                               clk             ,
    input                                               rst             ,
    input                                               i_hsync         ,
    input                                               i_vsync         ,
    input                                               i_data_valid    ,
    input           [23:0]                              i_data          , 

    output                                              o_hsync         ,
    output                                              o_vsync         ,
    output                                              o_data_valid    ,
    output          [23:0]                              o_data  
);


/***************reg*******************/
reg         ro_hsync     ;
reg         ro_vsync     ;  
reg         ro_data_valid;  
/***************wire******************/
wire  [7:0] rom_data    ;
/***************component*************/
gammp_map_rom u0_gamma_rom (
  .clka (clk            ),    // input wire clka
  .addra(i_data[23:16]  ),  // input wire [7 : 0] addra
  .douta(rom_data       )  // output wire [7 : 0] douta
);
/***************assign****************/
assign o_hsync      = ro_hsync              ;
assign o_vsync      = ro_vsync              ;
assign o_data_valid = ro_data_valid         ;
assign o_data       = {rom_data,rom_data,rom_data}    ;

/***************always****************/
always @(posedge clk) begin
    if(rst == 1'b1)
        ro_data_valid <= 'd0;
    else if(i_data_valid == 1'b1)
        ro_data_valid <= i_data_valid;
    else
        ro_data_valid <= 'd0;
end


always @(posedge clk) begin
    if(rst == 1'b1)
        ro_hsync <= 1'b0;
    else 
        ro_hsync <= i_hsync;
end

always @(posedge clk) begin
    if(rst == 1'b1)
        ro_vsync <= 1'b0;
    else 
        ro_vsync <= i_vsync;
end


endmodule

4.3 仿真结果

  仿真输入一个彩色图像,然后生成灰度图像以及伽马矫正后的图像命名为new_img:

rgb2gray u_rgb2gray(
    .clk           ( clk                ),
    .rst           ( reset              ),
    .i_data_valid  ( valid_i            ),
    .i_hsync       ( img_hs             ), 
    .i_vsync       ( img_vs             ), 
    .i_data_r      ( img_data_i[23:16]  ),
    .i_data_g      ( img_data_i[15:8]   ),
    .i_data_b      ( img_data_i[7:0]    ),
    .o_data_valid  ( valid_o            ),
    .o_hsync       ( o_img_hs           ), 
    .o_vsync       ( o_img_vs           ), 
    .o_data_r      ( img_data_o[23:16]  ),
    .o_data_g      ( img_data_o[15:8]   ),
    .o_data_b      ( img_data_o[7:0]    )
);

gamma_map u_gamma_map(
    .clk           ( clk           ),
    .rst           ( reset         ),
    .i_hsync       ( o_img_hs      ),
    .i_vsync       ( o_img_vs      ),
    .i_data_valid  ( valid_o       ),
    .i_data        ( img_data_o    ),
    .o_hsync       (               ),
    .o_vsync       (               ),
    .o_data_valid  ( o_post_cal_gray_data_valid  ),
    .o_data        ( o_post_cal_gray_data        )
);

在这里插入图片描述
在这里插入图片描述
  可以看到gamma值2.2矫正后的图像,亮部区域更亮,暗部区域更暗,和matlab的一致。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱奔跑的虎子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值