伪红外图像处理
创始人
2024-05-29 12:50:55
0

伪红外图像处理

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

4ae613acd91f46bc425326df176916b4.png

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


演示伪红外图像处理。

介绍

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

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

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

8818c991943a92217910f479896ad843.png来源:知乎

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

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

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

理论

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

  • 坏点校正

1d6f8bb0a95908b38819d8528a0ae6b3.png

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

  • 中值滤波器

73b295001d8ac26a271b21594b921d62.png

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

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

7326c5c13fccbc8dd1e8fecaa946acb2.png

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

  • 图像锐化

2b32e5bc24ea45a13e420a255b8572d4.png

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

  • 边缘检测

8d6ae69ec14446b4e1e8ec0c3c219e30.png

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

2a5cbfc267c1a47db5ebce44b104f49d.png

架构

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

95acbc00fa9612652461b34a82f37c0c.png架构f1ebd7c8dcf03667ecdd0cde00bf25b3.png

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

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

5c99f05144a594d658c4eebb42ba1164.png

设计

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

373d50e828c650477609181e4d98f23c.png5670e72e8714bd971a43d631beb3c607.png

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

接口

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

673a14ac2b264a2af8e9ac6fb39db75d.png
module axi_stream2frame#(parameter DATA_WIDTH = 24
)(input                       clk                   , // Syste clockinput                       rst_n                 , // Asynchronous reset active low
//------------------------- Configuration interface ----------------------------------input  [11:0]               cfg_img_w             , // Image widthinput  [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 frameinput     [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 receiveoutput reg [DATA_WIDTH-1:0] s_frm_data            , // Data transferred output reg                  s_frm_sof             , // Start of Frameoutput reg                  s_frm_eof             , // End of Frameoutput reg                  s_frm_sol             , // Start of Lineoutput 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。

f2eab55865a7f9c2f35ec5768d99673b.png

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

413b3ead5f02925a92edfa2113b7d0c1.png1842c17b9c06887d81e9a53632975f05.png11cc6828803a4d539732e142bca31a22.png5fa1baef33e5491614044eb568283661.png

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

配置模块

使用 APB 接口进行配置。

0efdb217e419bab3b8fa97e20ab1bc47.png
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);
}

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

be0f460a61913e5b6fe23d8a1daf6d93.png
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);

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

f4371dd510800ec31ac38119d835d0d6.png

演示

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

为了比较原始图像和处理后的两个图像,在 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

相关内容

热门资讯

城市规划“体检套餐”标准更新 转自:千龙网据新华社北京5月16日电(记者 王立彬)为城市规划定期体检,查“症状”、消“病灶”,减轻...
南昌地铁2号线东延线实现“双电...   本报讯(洪观新闻记者 蔡欢)日前,记者获悉,南昌地铁2号线东延线迎来重要节点——梧岗变电站至昌东...
太空采矿,离现实还有多远 转自:上观新闻华中科技大学提出的月球玄武基地方案模拟图。浩瀚宇宙中蕴藏的丰富资源,一直吸引着科学家去...
俄乌和平谈判已结束:持续近2个... 财联社5月16日讯(编辑 牛占林)当地时间周五,土耳其外交部和一名乌克兰高级官员表示,土耳其、俄罗斯...
多地阳性率明显上升,新冠感染又... 近期,全国多地新冠阳性率呈现明显上升趋势。5月16日,话题#新冠感染又抬头#登上热搜,引发广泛关注。...
“五老”赋能成长路 多方协同劳... 转自:南湖晚报   N晚报记者 居 郦 摄影 吴雪渔   立夏初至,万物生长。五月,是南湖区新...
美政府据称计划将100万巴勒斯... 隔夜股市美股周五收高,标普500指数涨0.7%,为连续第五个交易日上涨,道指涨0.78%,纳指涨0....
《数字中国建设2025年行动方...   新华社5月16日电(记者 高亢)记者16日获悉,国家数据局综合司于近日印发《数字中国建设2025...
都有数|5·20快到了,给TA... 转自:北京日报客户端今天是世界电信日,也是签署第一个《国际电报公约》的纪念日。自从杭州于5月全面停止...
智能设备24小时监测健康数据,... 转自:上观新闻从微信步数排名到24小时监测身体各项指标,从体脂秤每日监控BMI(身体质量指数)到精准...
孙颖莎说对比赛很兴奋 转自:河北新闻网 【#孙颖莎说对比赛很兴奋# 】#孙颖莎...
浅析《中华人民共和国民法典》 转自:邯郸日报 邯郸普法 《中华人民共和国民法典》被称为“社会生活的百科全书”...
600余名跑者沿七里河健身绿道... 转自:邢台网本报讯(记者尹丽芳、张婵娟)5月16日,随着发令枪响,以“太行泉城、义涌邢襄”为主题的泉...
“问题”主播成网红,违法犯罪经... 转自:北京日报客户端“如果你们还想听我讲在‘里面’的故事,还有我当‘酒托’的经历,记得进粉丝群,给我...
错误的洗碗方式,现在改掉还来得... 刷碗这看似简单的活儿其实有不少“技术含量”很多人可能都“洗错”了!一些洗碗习惯不仅不能把碗筷真正洗干...
推动民法典走到群众身边走进群众...   本报北京5月16日电(记者巩宸宇 徐日丹)今年是《中华人民共和国民法典》颁布五周年。16日上午,...
官方通报汕头违建豪宅英之园将强... 来源:@澎湃新闻微博 【#官方通报汕头违建豪宅英之园将强...
国际博物馆日 嘉兴好戏连台 转自:嘉兴日报   在国际博物馆日即将到来之际,嘉兴马家浜文化博物馆近日推出展览“冰河巨兽的乐园——...
第22届中国—东盟博览会高官会...   本报讯(记者韦静)记者从5月14日在南宁举办的第22届中国—东盟博览会高官会获悉,第22届东博会...
第二十届光博会 在武汉开幕   5月16日,观众在光博会上参观光束探测和功率测量设备。  当日,第二十届“中国光谷”国际光电子博...