PotatoPie 4.0 实验教程(25) —— FPGA实现摄像头图像直方图均衡变换

本文主要是介绍PotatoPie 4.0 实验教程(25) —— FPGA实现摄像头图像直方图均衡变换,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

图像的直方图均衡是什么?

图像的直方图均衡是一种用于增强图像对比度的图像处理技术。在直方图均衡中,图像的像素值被重新分配,以使得图像的直方图变得更均匀,即各个像素值的分布更加平衡。这意味着直方图中每个像素值的频率大致相同,从而使得图像的对比度增强。

直方图均衡可以应用于灰度图像和彩色图像,并且通常用于图像增强、图像预处理以及计算机视觉应用中。它有以下几个主要作用和优势:

  1. 增强对比度:直方图均衡可以增强图像的对比度,使得图像中的细节更加清晰、突出。通过重新分配像素值,可以拉伸直方图,使得图像中的像素值范围更广,从而增加了图像的动态范围。

  2. 消除背景噪声:直方图均衡可以帮助消除图像中的背景噪声,提高图像的质量。通过增强图像的对比度,可以更好地区分目标与背景,减少背景噪声的影响。

  3. 提高图像质量:直方图均衡可以改善图像的视觉质量,使图像更加清晰、生动,提高了图像的观赏性和识别性。

  4. 改善图像分割和特征提取:直方图均衡可以使得图像中不同目标的灰度级别更加明显,有利于图像分割和特征提取。这对于后续的图像分析、目标检测和识别等任务非常重要。

  5. 预处理步骤:直方图均衡通常作为图像预处理的一部分,用于提高后续图像处理算法的性能和准确性。例如,在图像识别、目标跟踪和计算机视觉任务中,对图像进行直方图均衡可以改善算法的鲁棒性和准确率。

总的来说,直方图均衡是一种简单而有效的图像增强技术,可以提高图像的质量和可用性,使得图像在各种应用领域中都能取得更好的效果。

直方图均衡算法的步骤

直方图均衡的步骤通常包括以下几个阶段:

  1. 计算图像的灰度直方图:统计图像中每个灰度级别的像素数量。
  2. 计算累积分布函数(CDF):对灰度直方图进行归一化处理,得到像素值的累积分布函数,该函数描述了每个灰度级别在图像中出现的累积概率。
  3. 根据CDF进行像素值映射:使用累积分布函数对图像的像素值进行重新映射,以使得图像的直方图更加均匀。通常情况下,这涉及到将原始像素值映射到新的像素值,以便在直方图中实现更均匀的分布。
  4. 应用像素值映射:根据映射关系,将图像中的每个像素值替换为对应的新值,从而完成直方图均衡化。

python实现图像的直方图均衡变换源码

PotatoPie 4.0 实验教程(25) —— FPGA实现摄像头图像直方图均衡变换-Anlogic-安路论坛-FPGA CPLD-ChipDebug

这段代码实现了图像的直方图均衡化,并使用 Matplotlib 库在 Python 中进行可视化展示。以下是对代码功能的详细说明:

  1. 导入必要的库

    • os:用于处理文件路径。
    • numpy:用于数组操作和数学计算。
    • cv2:OpenCV 库,用于图像处理。
    • matplotlib.pyplot:用于绘制图像和直方图。
  2. 获取图像路径

    • 使用 os.path.dirname 和 os.path.abspath 函数获取当前 Python 脚本所在目录的路径。
    • 使用 os.path.join 函数构造图像文件的完整路径。
  3. 读取图像

    • 使用 OpenCV 的 cv2.imread 函数读取图像。
  4. 将图像转换为灰度图像

    • 使用 OpenCV 的 cv2.cvtColor 函数将彩色图像转换为灰度图像。
  5. 计算直方图

    • 创建一个长度为 256 的数组 histogram,用于存储灰度级别的像素数量。
    • 使用双重循环遍历图像的每个像素,并在 histogram 中累计每个灰度级别的像素数量。
  6. 计算累积分布函数

    • 创建一个长度为 256 的数组 cumulative_distribution,用于存储每个灰度级别的累积分布函数值。
    • 使用双重循环遍历直方图,计算每个灰度级别的累积像素数量,并将其除以总像素数得到累积分布函数值。
  7. 计算直方图均衡化的灰度值映射表

    • 创建一个长度为 256 的数组 LUT,用于存储直方图均衡化后的灰度值映射表。
    • 将累积分布函数值乘以 255 并四舍五入,得到灰度值映射表。
  8. 直方图均衡化

    • 创建一个与原始图像相同大小的数组 image_equal,用于存储直方图均衡化后的图像。
    • 使用双重循环遍历原始图像的每个像素,根据灰度值映射表将每个像素的灰度值替换为均衡化后的灰度值。
  9. 可视化

    • 使用 Matplotlib 的 plt.imshow 和 plt.bar 函数分别显示原始图像和其直方图。
    • 使用 Matplotlib 的 plt.plot 函数绘制累积分布函数曲线。
    • 使用 Matplotlib 的 plt.show 函数显示图像及其直方图的子图布局。

通过以上步骤,代码实现了直方图均衡化并可视化显示了原始图像、均衡化后的图像、直方图以及累积分布函数。

MATLAB实现图像的直方图均衡变换源码

上面的代码实现了图像的直方图均衡化,具体步骤如下:

  1. 读取图像并转换为灰度图像: 使用imread函数读取名为’dog.png’的图像,并使用rgb2gray函数将彩色图像转换为灰度图像。

  2. 计算直方图: 首先创建一个256×1的零矩阵histogram,用于存储灰度级别的直方图。然后使用嵌套的循环遍历图像的每个像素点,将每个灰度级别出现的频数累加到相应的直方图位置上。

  3. 计算累积分布函数: 创建一个256×1的零矩阵cumulative_distribution,用于存储累积分布函数的值。然后通过循环计算累积分布函数的值,其中使用变量sum累积直方图的频数,并将其除以图像的总像素数(行数乘以列数)得到归一化后的累积分布函数。

  4. 计算灰度值映射表: 创建一个256×1的零矩阵LUT,用于存储直方图均衡化后的灰度值映射表。然后通过循环遍历累积分布函数,对每个灰度级别的累积分布函数值乘以255并四舍五入,得到灰度值映射表。

  5. 直方图均衡化: 创建一个与原始图像大小相同的零矩阵image_equal,用于存储直方图均衡化后的图像。然后通过嵌套的循环遍历原始图像的每个像素点,根据灰度值映射表将每个像素点的灰度值替换为对应的直方图均衡化后的灰度值。

  6. 显示结果: 使用subplot函数将原始图像、直方图、直方图均衡化后的图像以及其直方图和累积分布图显示在一个图像窗口中。标题使用中文显示,并指定使用微软雅黑字体。

工程分析

链接直达

https://item.taobao.com/item.htm?ft=t&id=776516984361

工程层次图

demo18相比,只是多了一个img_histogram的模块,也就是下面这一段代码,在从SDRAM读出来之后,经它处理后再输出hdmi_tx模块。

img_histogram u_img_histogram
(.i_clk          (clk_pixel                ),.i_rst_n        (sys_rst_n                ),.i_hs           (VGA_HS                   ),.i_vs           (VGA_VS                   ),.i_de           (VGA_DE                   ),.i_x_pos        (lcd_xpos                 ),.i_y_pos        (lcd_ypos                 ),.o_hs           (histogram_hs             ),.o_vs           (histogram_vs             ),.o_de           (histogram_de             ),.o_r            (histogram_r              ),.o_g            (histogram_g              ),.o_b            (histogram_b              ) 
);

img_histogram直方图均衡模块源代码分析

从层次图可到这个模块包含两个子ROM模块, 上面这个img_histogram ROM是我们要做直方图均衡的图像数据,dog.png就存在这里,为什么这个实验没有直接对摄像头进行处理,因为直方图需要大量的RAM,而EG4的RAM没有这么大,所以我们用ROM存一个小图来验证这个算法。

下面那个u_img_equal_ram_dp 是用来存储直方图映射表。

接下来我们讲述直方图均衡化的FPGA算法关键点:

1. 从ROM读取dog.png的图像数据

由于我们需要在指定位置处理像,而我们显示屏大于图像的尺寸,因此需要行场计数到达指定位置时才从ROM读取图像数据。

我们用这几个参数定义显示处理图像的位置

parameter H_ACTIVE = 160; //显示区域宽度
parameter V_ACTIVE = 120; //显示区域高度
parameter BEGIN_X = 640; //显示起始坐标
parameter BEGIN_Y = 360; //显示起始坐标

然后分别进行/显示区域行计数和列计数,

if(h_cnt == H_ACTIVE - 1'b1)h_cnt <= 11'd0;else h_cnt <= h_cnt + 11'd1;..... 省略if(v_cnt == V_ACTIVE - 1'b1)v_cnt <= 11'd0;else v_cnt <= v_cnt + 11'd1;

往下看就看到代码定义ROM的地方了

 

//存储dog.png图片数据的ROM

dog_160x120 u_image_buffer(

.doa ({r_d0,g_d0,b_d0}),

.addra (rd_addr ),

.clka (i_clk )

);

接下来的这行代码处理了图像数据ROM的地址计数。

rd_addr <= v_cnt * H_ACTIVE + h_cnt;

2.图像的灰度化

PotatoPie 4.0 实验教程(25) —— FPGA实现摄像头图像直方图均衡变换-Anlogic-安路论坛-FPGA CPLD-ChipDebug

3.计算直方图

跟matlab和python代码一样,统计一帧图像数据中每个灰度出现的次数

hist_ram[gray_d0[15:8]]<=hist_ram[gray_d0[15:8]]+1'b1;

4.计算累积分布函数建立映射表

PotatoPie 4.0 实验教程(25) —— FPGA实现摄像头图像直方图均衡变换-Anlogic-安路论坛-FPGA CPLD-ChipDebug

5. 将计算结果写映射表的ROM

例化双端RAM用于存储映射表

// 存储直方图均衡化后的灰度值映射表,输出时直接用灰度值作为地址进行查表
ram_dp#(.DATA_WIDTH   (8          ),.ADDRESS_WIDTH  (8             )
) u_img_equal_ram_dp(.i_clk      (i_clk        ),.i_data_a    (image_equal    ),.i_addr_a    (wr_addr_cnt    ),.i_wea      (sum_hist_flag_d3  ),.o_qout_a    (          ),.i_data_b    (          ),.i_addr_b    (gray_d0[15:8]    ),.i_web      (          ),.o_qout_b    (hist_out      )
);

显示的时候,直接用灰度值作为地址进行查表读出值即可。

管脚约束

与PotatoPie 4.0 实验教程(18) —— FPGA实现OV5640摄像头采集以SDRAM作为显存进行HDMI输出显示相同,不作赘述。

时序约束

与PotatoPie 4.0 实验教程(18) —— FPGA实现OV5640摄像头采集以SDRAM作为显存进行HDMI输出显示相同,不作赘述。

实验结果

这篇关于PotatoPie 4.0 实验教程(25) —— FPGA实现摄像头图像直方图均衡变换的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/955882

相关文章

C++使用栈实现括号匹配的代码详解

《C++使用栈实现括号匹配的代码详解》在编程中,括号匹配是一个常见问题,尤其是在处理数学表达式、编译器解析等任务时,栈是一种非常适合处理此类问题的数据结构,能够精确地管理括号的匹配问题,本文将通过C+... 目录引言问题描述代码讲解代码解析栈的状态表示测试总结引言在编程中,括号匹配是一个常见问题,尤其是在

Java实现检查多个时间段是否有重合

《Java实现检查多个时间段是否有重合》这篇文章主要为大家详细介绍了如何使用Java实现检查多个时间段是否有重合,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录流程概述步骤详解China编程步骤1:定义时间段类步骤2:添加时间段步骤3:检查时间段是否有重合步骤4:输出结果示例代码结语作

使用C++实现链表元素的反转

《使用C++实现链表元素的反转》反转链表是链表操作中一个经典的问题,也是面试中常见的考题,本文将从思路到实现一步步地讲解如何实现链表的反转,帮助初学者理解这一操作,我们将使用C++代码演示具体实现,同... 目录问题定义思路分析代码实现带头节点的链表代码讲解其他实现方式时间和空间复杂度分析总结问题定义给定

Java覆盖第三方jar包中的某一个类的实现方法

《Java覆盖第三方jar包中的某一个类的实现方法》在我们日常的开发中,经常需要使用第三方的jar包,有时候我们会发现第三方的jar包中的某一个类有问题,或者我们需要定制化修改其中的逻辑,那么应该如何... 目录一、需求描述二、示例描述三、操作步骤四、验证结果五、实现原理一、需求描述需求描述如下:需要在

如何使用Java实现请求deepseek

《如何使用Java实现请求deepseek》这篇文章主要为大家详细介绍了如何使用Java实现请求deepseek功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1.deepseek的api创建2.Java实现请求deepseek2.1 pom文件2.2 json转化文件2.2

python使用fastapi实现多语言国际化的操作指南

《python使用fastapi实现多语言国际化的操作指南》本文介绍了使用Python和FastAPI实现多语言国际化的操作指南,包括多语言架构技术栈、翻译管理、前端本地化、语言切换机制以及常见陷阱和... 目录多语言国际化实现指南项目多语言架构技术栈目录结构翻译工作流1. 翻译数据存储2. 翻译生成脚本

Spring Cloud LoadBalancer 负载均衡详解

《SpringCloudLoadBalancer负载均衡详解》本文介绍了如何在SpringCloud中使用SpringCloudLoadBalancer实现客户端负载均衡,并详细讲解了轮询策略和... 目录1. 在 idea 上运行多个服务2. 问题引入3. 负载均衡4. Spring Cloud Load

如何通过Python实现一个消息队列

《如何通过Python实现一个消息队列》这篇文章主要为大家详细介绍了如何通过Python实现一个简单的消息队列,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录如何通过 python 实现消息队列如何把 http 请求放在队列中执行1. 使用 queue.Queue 和 reque

Python如何实现PDF隐私信息检测

《Python如何实现PDF隐私信息检测》随着越来越多的个人信息以电子形式存储和传输,确保这些信息的安全至关重要,本文将介绍如何使用Python检测PDF文件中的隐私信息,需要的可以参考下... 目录项目背景技术栈代码解析功能说明运行结php果在当今,数据隐私保护变得尤为重要。随着越来越多的个人信息以电子形

使用 sql-research-assistant进行 SQL 数据库研究的实战指南(代码实现演示)

《使用sql-research-assistant进行SQL数据库研究的实战指南(代码实现演示)》本文介绍了sql-research-assistant工具,该工具基于LangChain框架,集... 目录技术背景介绍核心原理解析代码实现演示安装和配置项目集成LangSmith 配置(可选)启动服务应用场景