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

news2024/11/15 21:33:03

文章目录

  • 一、什么是伽马校正?
  • 二、伽马校正的由来
  • 三、Matlab实现伽马校正
    • 3.1 matlab代码
    • 3.2 matlab结果
  • 四、Verilog实现伽马校正
    • 4.1 生成初始化ROM文件
    • 4.2 Verilog代码
    • 4.3 仿真结果


一、什么是伽马校正?

  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的一致。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2141353.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

代码随想录冲冲冲 Day47 单调栈Part1

739. 每日温度 初步了解单调栈&#xff0c;根本思想就是如果求的是一个元素右边或左边第一个最大的元素 那么就是递增栈&#xff0c;如果是最小的就是递减栈 首先先放入一个0代表 第一个元素的index 之后开始for loop 当后面的值小于等于这个top时 就要先把index放入st中&a…

Leetcode 找到字符串中所有字母异位词

在 C 中&#xff0c;两个 vector<int> 类型的变量进行 操作时&#xff0c;会逐个比较它们的元素&#xff0c;只有当两个向量的长度相同且每个位置上的元素值都相同时&#xff0c; 操作才会返回 true。 因此&#xff0c;在这道题的代码中&#xff0c;sCount pCount 这一…

Flip动画的实现示例demo

Flip动画的实现示例demo 文章说明核心代码效果展示Flip动画工具类的封装 文章说明 文章主要为了学习flip动画的实现思路&#xff0c;并且采用此示例效果来理解该实现思路的含义 参考渡一前端袁老师的讲解视频 核心代码 采用简单的y轴变化的动画效果为示例 <!DOCTYPE html>…

【K230 实战项目】气象时钟

【CanMV K230 AI视觉】 气象时钟 功能描述&#xff1a;说明HMDI资源3.5寸屏幕 使用方法 为了方便小伙伴们理解&#xff0c;请查看视频 B站连接 功能描述&#xff1a; 天气信息获取&#xff1a;通过连接到互联网&#xff0c;实时获取天气数据&#xff0c;包括温度、湿度、天气状…

【STM32】独立看门狗(IWDG)原理详解及编程实践(上)

本篇文章是对STM32单片机“独立看门狗&#xff08;IWDG&#xff09;”的原理进行讲解。希望我的分享对你有所帮助&#xff01; 目录 一、什么是独立看门狗 &#xff08;一&#xff09;简介 &#xff08;二&#xff09;、独立看门狗的原理 &#xff08;三&#xff09;、具体操…

vulkano (rust) 画一个三角形 (vulkan 渲染窗口初始化 (Linux) 下篇)

上文说到, vulkan 相比 OpenGL (ES), 更加贴近底层硬件, 许多东西需要应用软件手动管理, 所以 vulkan 的初始化过程比较麻烦, 或者说学习曲线比较陡峭. 但是, 这种麻烦是一次性的, 一旦学会了, 就能开始享受 vulkan 的诸多好处啦 ~ 本文以绘制一个三角形为例, 介绍 vulkan 的初…

2024最新版,人大赵鑫老师《大语言模型》新书pdf分享

本书主要面向希望系统学习大语言模型技术的读者&#xff0c;将重点突出核心概念与 算法&#xff0c;并且配以示例与代码&#xff08;伪代码&#xff09;帮助读者理解特定算法的实现逻辑。由于大语言模型技术的快速更迭&#xff0c;本书无法覆盖所有相关内容&#xff0c;旨在梳理…

瓶中水位检测系统源码分享

瓶中水位检测检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Computer Vis…

【数据结构】图的概念和存储结构

快乐的流畅&#xff1a;个人主页 个人专栏&#xff1a;《C游记》《进击的C》《Linux迷航》 远方有一堆篝火&#xff0c;在为久候之人燃烧&#xff01; 文章目录 引言一、图的概念二、图的存储结构2.1 邻接矩阵2.1.1 成员变量与默认成员函数2.1.2 GetIndex2.1.3 AddEdge2.1.4 Pr…

使用 Java 初步搭建简单Spring 项目框架:

一、准备工作 安装 Java Development Kit (JDK)&#xff0c;确保环境变量配置正确。 安装一个集成开发环境&#xff08;IDE&#xff09;&#xff0c;如 IntelliJ IDEA 或 Eclipse。 二、创建项目——具体步骤 在 ider 中创建一个新的 Maven 项目 使用 Maven&#xff1a; 在…

Linux bash脚本本地开发环境(Git Bash)配置

参考资料 VSCode: Windows 下配置 VSCode运行shellVSCodeを使用したシェルスクリプトの開発環境作成 目录 一. 必备VSCode插件二. 插件配置说明2.1 Bash IDE2.2 Code Runner2.3 shell-format 一. 必备VSCode插件 Bash IDE 该插件为 Bash 脚本提供了一些实用的开发工具和功能&…

鸿蒙 ArkUI组件二

ArkUI组件&#xff08;续&#xff09; 文本组件 在HarmonyOS中&#xff0c;Text/Span组件是文本控件中的一个关键部分。Text控件可以用来显示文本内容&#xff0c;而Span只能作为Text组件的子组件显示文本内容。 Text/Span组件的用法非常简单和直观。我们可以通过Text组件来显…

重生归来之挖掘stm32底层知识(1)——寄存器

概念理解 要使用stm32首先要知道什么是引脚和寄存器。 如下图所示&#xff0c;芯片通过这些金属丝与电路板连接&#xff0c;这些金属丝叫做引脚。一般做软件开发是不需要了解芯片是怎么焊的&#xff0c;只要会使用就行。我们平常通过编程来控制这些引脚的输入和输出&#xff0c…

应用软件系统开发实操二:任务需求描述

工信部软件界信息技术服务业2020、2021、2022年度数据&#xff08;目前只有这3年的完整数据&#xff09;&#xff0c;以SQL的格式&#xff0c;存放在实操平台上&#xff0c;通过浏览器下载的方式获取。获取数据后&#xff0c;采用自己选择的技术对数据进行处理。阅读下面的要求…

php语言基本语法

HP&#xff08;Hypertext Preprocessor&#xff09;是一种广泛使用的开源服务器端脚本语言&#xff0c;特别适合于Web开发。 它能够嵌入到HTML中&#xff0c;执行动态网页内容。 PHP的一些基本语法元素&#xff1a; 1. 基本结构 PHP代码通常嵌入到HTML中&#xff0c;以<…

C/C++实现植物大战僵尸(PVZ)(打地鼠版)

&#x1f680;欢迎互三&#x1f449;&#xff1a;程序猿方梓燚 &#x1f48e;&#x1f48e; &#x1f680;关注博主&#xff0c;后期持续更新系列文章 &#x1f680;如果有错误感谢请大家批评指出&#xff0c;及时修改 &#x1f680;感谢大家点赞&#x1f44d;收藏⭐评论✍ 游戏…

Django_Vue3_ElementUI_Release_003_前端Vue3项目初始化

1. 概念扫盲 Node.js是基于ChromeV8引擎&#xff0c;让JS在服务端运行的开发平台&#xff0c;就是JS的一种解释器WebPack就是模块打包机&#xff0c;把浏览器不能直接运行的拓展语言找到并打包为合适的格式给浏览器直接使用Vue基于WebPack构件项目的&#xff0c;并带有合理默认…

MoCo对比损失

MoCo&#xff08;Momentum Contrast&#xff0c;动量对比学习&#xff09;是一种自监督学习方法&#xff0c;由Facebook AI Research提出&#xff0c;主要用于无监督学习视觉表示。在MoCo中&#xff0c;对比损失&#xff08;Contrastive Loss&#xff09;扮演着至关重要的角色&…

在麒麟操作系统中查看进程运行时间

在麒麟操作系统中查看进程运行时间 1、使用ps命令查看进程运行时间1.1 基本命令结构1.2 示例&#xff1a;查看sshd进程的运行时间 2、总结 &#x1f496;The Begin&#x1f496;点点关注&#xff0c;收藏不迷路&#x1f496; 在Linux操作系统中&#xff0c;包括麒麟&#xff08…

使用Mockito进行单元测试

1、单元测试介绍 Mockito和Junit是用于单元测试的常用框架。单元测试即&#xff1a;从最小的可测试单元&#xff08;如函数、方法或类&#xff09;开始&#xff0c;确保每个单元都能按预期工作。单元测试是白盒测试的核心部分&#xff0c;它有助于发现单元内部的错误。 单元测试…