Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >伪红外图像处理

伪红外图像处理

作者头像
FPGA技术江湖
发布于 2025-02-18 06:12:23
发布于 2025-02-18 06:12:23
7800
代码可运行
举报
文章被收录于专栏:FPGA技术江湖FPGA技术江湖
运行总次数:0
代码可运行

伪红外图像处理

副标题:优秀的IC/FPGA开源项目-伪红外图像处理

《优秀的IC/FPGA开源项目》是新开的系列,旨在介绍单一项目,会比《优秀的 Verilog/FPGA开源项目》内容介绍更加详细,包括但不限于综合、上板测试等。两者相辅相成,互补互充~

演示伪红外图像处理

介绍

红外摄像机因为对可见光不敏感,所以在一些特殊行业应用越来越广泛。

红外摄像机甚至可以透过太阳镜看到人眼,并且摄像机图像不受白天或夜晚的影响,并且几乎没有环境光。

因为真正的红外sensor价格比较昂贵,所以这次选用一种伪红外sensor,即利用相机自己的光源,即安装在镜头旁边的 LED,反射红外光后进项图像采集,这是一种利用近红外成像,和我们熟知的红外摄像头还是有区别的。

来源:知乎

该项目展示了一些红外图像处理算法,这些算法可以提高图像质量。

所选FPGA是 ZYNQ-020 SoC,摄像头是便宜的 Raspberry PI 摄像头,带有两个红外 LED,最大分辨率为 1080p@60Hz。

该项目中呈现的体系结构是可扩展的,可以轻松添加更多算法。

理论

我选择了五种基于 3x3 内核的图像处理算法:

  • 坏点校正

这是所有这类传感器的普遍问题,是一种常见的预处理算法。

  • 中值滤波器

常见的噪声平滑预处理算法。

  • 低通滤波器(平滑滤波器)

噪声平滑,这个算法使图像平滑,不会像中值滤波器那样使图像模糊。

  • 图像锐化

通过“边缘锐化”提高图像质量,即强调边缘。

  • 边缘检测

应用其中一种算法后,对图像边缘处理后,图像尺寸会减小(可选)。

架构

所有算法都基于 3x3 内核,这就是为什么所有算法内核 (PE) 都必须与 FIFO 通信,每个 PE 都有一行的延迟。只有当第二行数据到达时才开始应用算法内核,考虑到图像处理时候会对边界有影响,但是我们需要输出端输出相同的图像大小。

架构

选择模块是一个可扩展的 MUX 网络,在上图情况下,具有五个图像处理算法,由六个级联的 MUX-es 组成,一个用于滤波器输出,一个用于输入信号。数据流可以配置,在这种情况下,视频流从输入到输出,它通过的图像处理元素的顺序和数量是可配置的。

算法内核的结构如下所示,基本上在这种情况下是一个延迟线,它以视频流作为输入并输出一个 3x3 矩阵,输出是处理后的帧。

设计

在该架构中,我在 VDMA 和 Gamma Correction 模块之间插入了我的模块。

我为每个行缓冲区添加了一个 FIFO。

接口

所有模块都使用规定好的帧接口 (FI),它与参考设计中使用的 AXI Stream 接口非常相似(https://reference.digilentinc.com/learn/programmable-logic/tutorials/zybo-z7-pcam-5c-demo/start),可以在两者之间进行转换。从 AXI Stream 到 Frame 不需要转换,反之则必须生成一些额外的信号。AXI Stream 接口只有帧开始和行结束控制信号。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
module axi_stream2frame#(
 parameter DATA_WIDTH = 24
)(
 input                       clk                   , // Syste clock
 input                       rst_n                 , // Asynchronous reset active low
//------------------------- Configuration interface ----------------------------------
 input  [11:0]               cfg_img_w             , // Image width
 input  [11:0]               cfg_img_h             , // Image width
//------------------------- AXI-Stream interface -------------------------------------
 input                       m_axi_stream_tuser    , // Start of frame 
 input                       m_axi_stream_tvalid   , // Slave has valid data 
 input                       m_axi_stream_tlast    , // End of frame
 input     [DATA_WIDTH-1:0]  m_axi_stream_tdata    , // Data transferred 
 output                      m_axi_stream_tready   , // Master is ready to receive
// ------------------------------ Frame Interface -----------------------------------
 output reg                  s_frm_val             , // Master has valid data 
 input                       s_frm_rdy             , // Slave is ready to receive
 output reg [DATA_WIDTH-1:0] s_frm_data            , // Data transferred 
 output reg                  s_frm_sof             , // Start of Frame
 output reg                  s_frm_eof             , // End of Frame
 output reg                  s_frm_sol             , // Start of Line
 output reg                  s_frm_eol               // End of Line
);
reg [11:0] pix_cnt ;
reg [11:0] line_cnt;
wire invalrdy;
wire outvalrdy;
wire set_eof;
assign invalrdy = m_axi_stream_tvalid & m_axi_stream_tready;
assign outvalrdy = s_frm_rdy & s_frm_val;
assign m_axi_stream_tready = s_frm_rdy;
assign set_eof = (line_cnt == (cfg_img_h - 1'd1)) & m_axi_stream_tlast & invalrdy;
  
always@(posedge clk or negedge rst_n)
if(~rst_n                        ) pix_cnt <= 11'd0         ; else
if(m_axi_stream_tuser & invalrdy ) pix_cnt <= 11'd0         ; else // Reset at start of frame
if(m_axi_stream_tlast & invalrdy ) pix_cnt <= 11'd0         ; else // Reset at end of frame
if(invalrdy                      ) pix_cnt <= pix_cnt + 1'd1;      // Increment at each pixel
always@(posedge clk or negedge rst_n)
if(~rst_n                       ) line_cnt <= 11'd0          ; else
if(m_axi_stream_tuser & invalrdy) line_cnt <= 11'd0          ; else // Reset at start of frame
if(m_axi_stream_tlast & invalrdy) line_cnt <= line_cnt + 1'd1;      // Increment at each pixel
always@(posedge clk or negedge rst_n)
if(~rst_n                              ) s_frm_sol <= 1'b0; else
if(outvalrdy & s_frm_sol               ) s_frm_sol <= 1'b0; else // Reset sol is transmitted
if(m_axi_stream_tuser & invalrdy       ) s_frm_sol <= 1'b1; else // Set start of line after last pixel of line is transmitted
if(outvalrdy & s_frm_eol & (~s_frm_eof)) s_frm_sol <= 1'b1;      // Set at start of frame
always@(posedge clk or negedge rst_n)
if(~rst_n               ) s_frm_eof <= 1'b0; else
if(outvalrdy & s_frm_eof) s_frm_eof <= 1'b0; else // Reset after eof is transmitted
if(set_eof              ) s_frm_eof <= 1'b1;      // Set when last pixel is received
always@(posedge clk or negedge rst_n)
if(~rst_n                            ) s_frm_val <= 1'b0; else
if(s_frm_rdy & (~m_axi_stream_tvalid)) s_frm_val <= 1'b0; else // Reset when ready and no valid data at the input
if(invalrdy                          ) s_frm_val <= 1'b1;   // Set if data is received
always@(posedge clk or negedge rst_n)
if(~rst_n                       ) s_frm_eol <= 1'b0; else
if(outvalrdy & s_frm_eol        ) s_frm_eol <= 1'b0; else // Reset after eol is transmitted
if(m_axi_stream_tlast & invalrdy) s_frm_eol <= 1'b1;      // Set when last pixel in a row is received
always@(posedge clk or negedge rst_n)
if(~rst_n                        ) s_frm_sof <= 1'b0; else
if(outvalrdy & s_frm_sof         ) s_frm_sof <= 1'b0; else // Reset after sof is                               transmitted
if(m_axi_stream_tuser  & invalrdy) s_frm_sof <= 1'b1;      // Set when first pixel is received
always@(posedge clk or negedge rst_n)
if(~rst_n  ) s_frm_data <= {(DATA_WIDTH){1'b0}}; else
if(invalrdy) s_frm_data <= m_axi_stream_tdata  ;
endmodule //axi_stream2Frame

配置sensor

这个摄像头是搭配树莓派使用的,所有驱动都是闭源的,所以没有配置示例。我在 SCL 和 SDA 引脚上的 I2C 引脚上焊接了两根电线。将相机连接到 Raspeberry Pi 并将逻辑分析仪连接到焊线,我按照相机接口指南

https://projects.raspberrypi.org/en/projects/getting-started-with-picamera

逻辑分析仪解码了I2C,抓取的值将在最后附上excel。

该配置已添加到 C++ 代码中。

摄像头是 RGB 摄像头,只有在房间黑暗时才会启动红外摄像头。为了解决这个问题,我在sensor前面粘上了一块塑料,这是红外 LED 前面的过滤器。这不是一个很好的解决方案,但可以。

配置模块

使用 APB 接口进行配置。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
void filter_cfg()
{
 Xil_Out32(APB_BASE_ADDR + CFG_IMG_WIDTH_ADDR, IMG_W);
 Xil_Out32(APB_BASE_ADDR + CFG_IMG_HEIGHT_ADDR, IMG_H);
 Xil_Out32(APB_BASE_ADDR + CFG_PIX_CORR_SEL_ADDR, 0);
 Xil_Out32(APB_BASE_ADDR + CFG_SHARP_SEL_ADDR, 0);
 Xil_Out32(APB_BASE_ADDR + CFG_SMOOTH_SEL_ADDR, 0);
 Xil_Out32(APB_BASE_ADDR + CFG_MEDIAN_SEL_ADDR, 0);
 Xil_Out32(APB_BASE_ADDR + CFG_LAPLACE_SEL_ADDR, 0);
 Xil_Out32(APB_BASE_ADDR + CFG_OUTPUT_SEL_ADDR, 0);
 Xil_Out32(APB_BASE_ADDR + CFG_PIX_CORR_THR_ADDR, 0);
 Xil_Out32(APB_BASE_ADDR + CFG_SHARP_COEF_ADDR, 0);
 Xil_Out32(APB_BASE_ADDR + CFG_TEST_MODE_EN_ADDR, 0);
}

上面给出的配置是每个选择器模块的选择。现在它被配置为输入流不进行任何处理的情况下转到输出。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
void filter_cfg()
{
 Xil_Out32(APB_BASE_ADDR + CFG_IMG_WIDTH_ADDR, IMG_W);
 Xil_Out32(APB_BASE_ADDR + CFG_IMG_HEIGHT_ADDR, IMG_H);
 Xil_Out32(APB_BASE_ADDR + CFG_PIX_CORR_SEL_ADDR, 0);
 Xil_Out32(APB_BASE_ADDR + CFG_SHARP_SEL_ADDR, 0);
 Xil_Out32(APB_BASE_ADDR + CFG_SMOOTH_SEL_ADDR, SMOOTH_IN_CODE);
 Xil_Out32(APB_BASE_ADDR + CFG_MEDIAN_SEL_ADDR, 0);
 Xil_Out32(APB_BASE_ADDR + CFG_LAPLACE_SEL_ADDR, SMOOTH_IN_CODE);
 Xil_Out32(APB_BASE_ADDR + CFG_OUTPUT_SEL_ADDR, LAPLACE_IN_CODE);
 Xil_Out32(APB_BASE_ADDR + CFG_PIX_CORR_THR_ADDR, 0);
 Xil_Out32(APB_BASE_ADDR + CFG_SHARP_COEF_ADDR, 0);
 Xil_Out32(APB_BASE_ADDR + CFG_TEST_MODE_EN_ADDR, 0);
} 

Xil_Out32(APB_BASE_ADDR + CFG_SMOOTH_SEL_ADDR, SMOOTH_IN_CODE);

将输入视频流放入算法核心。

演示

我展示了带平滑和不带平滑的拉普拉斯滤波器,我们可以观察到图像有噪声,应用平滑滤波器后图像有所变化。

为了比较原始图像和处理后的两个图像,在 Gamma 校正之后添加了第二个 VDMA,,现在校正后的图像和原始图像都在 DDR 中,因此可以复制裁剪处理后的图像并将裁剪区域替换为原始图像。

工程链接

I2C 解码的 csv

https://github.com/hszilard13/Infa-red-based-Image-processing-Zybo/blob/master/config_1080p_rgb.csv

整体工程

https://github.com/hszilard13/Infared-based-Image-processing-Zybo

END

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-02-15,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 FPGA技术江湖 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
fpga学习——zynq图像处理中的DVP流接口封装
之前文章介绍了基于zynq的图像处理架构问题。其中,作为开发者,需要重点关注图像传感器接口、处理算法、显示接口,这些模块。现在我们一同学习用于视频数据接口的DVP模块,并将其封装成AXI-stream接口便于直接和VDMA IP通信。
全栈程序员站长
2022/09/02
1.7K0
fpga学习——zynq图像处理中的DVP流接口封装
FPGA零基础学习:SDR SDRAM 驱动设计
本系列将带来FPGA的系统性学习,从最基本的数字电路基础开始,最详细操作步骤,最直白的言语描述,手把手的“傻瓜式”讲解,让电子、信息、通信类专业学生、初入职场小白及打算进阶提升的职业开发者都可以有系统性学习的机会。
FPGA技术江湖
2021/03/23
1K0
FPGA零基础学习:SDR SDRAM 驱动设计
sdram控制器设计
同步动态随机存取内存(synchronous dynamic random-access memory,简称SDRAM)是有一个同步接口的动态随机存取内存(DRAM)。SDRAM的特点是需要定期进行刷新操作,这也要求SDRAM需要一个控制器来对SDRAM进行控制,更为详细的SDRAM的知识可以上网进行查找,这里不再做过多的阐述。
全栈程序员站长
2022/09/07
6430
sdram控制器设计
FPGA零基础学习:SPI 协议驱动设计
本系列将带来FPGA的系统性学习,从最基本的数字电路基础开始,最详细操作步骤,最直白的言语描述,手把手的“傻瓜式”讲解,让电子、信息、通信类专业学生、初入职场小白及打算进阶提升的职业开发者都可以有系统性学习的机会。
FPGA技术江湖
2020/12/30
1.6K0
FPGA零基础学习:IIC协议驱动设计
本系列将带来FPGA的系统性学习,从最基本的数字电路基础开始,最详细操作步骤,最直白的言语描述,手把手的“傻瓜式”讲解,让电子、信息、通信类专业学生、初入职场小白及打算进阶提升的职业开发者都可以有系统性学习的机会。
FPGA技术江湖
2021/03/23
1.3K0
FPGA零基础学习:IIC协议驱动设计
源码系列:基于FPGA的中值滤波器设计(附源码)
今天给大侠带来基于FPGA的中值滤波器设计,附源码,获取源码,请在“FPGA技术江湖”公众号内回复“中值滤波器设计源码”,可获取源码文件。话不多说,上货。
FPGA技术江湖
2020/12/30
1.1K0
灰度图像的 Sobel 边缘检测算法的 HDL实现(二)
这一步直接通过 HDL 中乘法器的描述来实现, 综合时会自动布线为片内乘法器,如下:
碎碎思
2020/06/30
1.1K0
FPGA零基础学习:SPI 协议驱动设计(上)
本系列将带来FPGA的系统性学习,从最基本的数字电路基础开始,最详细操作步骤,最直白的言语描述,手把手的“傻瓜式”讲解,让电子、信息、通信类专业学生、初入职场小白及打算进阶提升的职业开发者都可以有系统性学习的机会。
FPGA技术江湖
2021/03/23
1.1K0
FPGA零基础学习:SPI 协议驱动设计(上)
FPGA零基础学习:SPI 协议驱动设计(下)
该模块负责将外部写fifo中的数据写入到flash中。wr_fifo_rd为写fifo的读使能信号,wrdata为从写fifo中读出的数据,wr_len为需要写入flash中数据的长度,wr_addr为写入地址。
FPGA技术江湖
2021/03/23
1.4K0
FPGA零基础学习:SPI 协议驱动设计(下)
FPGA零基础学习:图像显示系统设计
大侠好,欢迎来到FPGA技术江湖。本系列将带来FPGA的系统性学习,从最基本的数字电路基础开始,最详细操作步骤,最直白的言语描述,手把手的“傻瓜式”讲解,让电子、信息、通信类专业学生、初入职场小白及打算进阶提升的职业开发者都可以有系统性学习的机会。
FPGA技术江湖
2021/03/23
5490
FPGA零基础学习:图像显示系统设计
FPGA综合项目——SDRAM控制器
再者就是通信处理模块,具体的通信设置,发送什么命令是写?什么命令是读?发的什么数据?等等。
全栈程序员站长
2022/09/16
6540
FPGA综合项目——SDRAM控制器
【收藏】FPGA数字IC刷题58个Verilog代码及讲解(状态机、跨时钟、同步/异步FIFO、DMUX、奇数/小数分频)
牛客 Verilog 刷题入门篇1~24 + 进阶篇1~34 题解代码,所有代码均能通过测试,配合视频讲解效果更佳。本文给出代码,部分题目给出必要说明。 很多题目本身出题有些问题,着重理解题目,没必要钻牛角尖。
FPGA探索者
2022/11/01
3K0
【收藏】FPGA数字IC刷题58个Verilog代码及讲解(状态机、跨时钟、同步/异步FIFO、DMUX、奇数/小数分频)
FPGA系统性学习笔记连载_Day13【简易计时器实验】之【Xilinx Spartan-6实现】篇
本系列为FPGA系统性学习学员学习笔记整理分享,如有学习或者购买开发板意向,可加交流群联系群主。
FPGA技术江湖
2021/04/06
7780
FPGA系统性学习笔记连载_Day13【简易计时器实验】之【Xilinx Spartan-6实现】篇
VCS与Verdi的联合仿真
Verdi主要用于生成fsdb模型,同VCS使用的vcd文件相比,verdi使用的fsdb相当于vcd文件经过霍夫编码压缩之后的精简版,可用于查看fsdb波形并追踪RTL代码。
根究FPGA
2020/07/28
9.6K0
VCS与Verdi的联合仿真
基于FPGA的实时图像边缘检测系统设计(下)
今天给大侠带来基于FPGA的实时图像边缘检测系统设计,由于篇幅较长,分三篇。今天带来第三篇,下篇,话不多说,上货。
FPGA技术江湖
2021/04/19
7780
基于FPGA的实时图像边缘检测系统设计(下)
【FPGA】课程设计:简单计时器闹钟
视频地址:https://live.csdn.net/v/embed/213189
zstar
2022/06/14
1.2K0
【FPGA】课程设计:简单计时器闹钟
基于FPGA的SDRAM控制器设计(4)[通俗易懂]
前面的三篇文章,我们已经简述了基本的SDRAM的基本操作。这里总结一下SDRAM的几个模块,SDRAM的上电初始化,自刷新、读写模块、顶层仲裁控制。了解了上面的操作,我们已经可以完成SDRAM控制器的代码完成,接下来我们便完善SDRAM控制器的接口,简化该SDRAM控制器设计,使得该SDRAM控制器可以很容易的使用。下面的接口定义如下:
全栈程序员站长
2022/07/28
6970
基于FPGA的SDRAM控制器设计(4)[通俗易懂]
FPGA零基础学习之Vivado-RTC实时时钟系统设计
本系列将带来FPGA的系统性学习,从最基本的数字电路基础开始,最详细操作步骤,最直白的言语描述,手把手的“傻瓜式”讲解,让电子、信息、通信类专业学生、初入职场小白及打算进阶提升的职业开发者都可以有系统性学习的机会。
FPGA技术江湖
2023/08/22
5270
FPGA零基础学习之Vivado-RTC实时时钟系统设计
fpga通过uart向上位机传输ad7606采集数据
前文提供了ad7606的驱动程序,本文通过串口将8路adc采集的数据传输给上位机显示。
FPGA技术江湖
2025/03/14
1300
fpga通过uart向上位机传输ad7606采集数据
【Verilog刷题篇】硬件工程师从0到入门3|组合逻辑复习+时序逻辑入门
问题描述:请使用此4选1数据选择器和必要的逻辑门实现下列表达式。 L=A∙B+A∙~C+B∙C 数据选择器的逻辑符号如下图:
程序员洲洲
2024/06/07
1250
【Verilog刷题篇】硬件工程师从0到入门3|组合逻辑复习+时序逻辑入门
推荐阅读
相关推荐
fpga学习——zynq图像处理中的DVP流接口封装
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验