傅里叶变换去除图像条纹

去除垂直、水平等条纹杂讯的图像处理步骤

空间域的处理方法比较多,比如傅里叶变换和小波变换等。频域方法处理的一般步骤是:

① 将图像从空间域转换到频域;

② 在频域处理(挑选或剔除特定的频段);

③ 频域处理后再转换到空间域

傅里叶变换频域处理步骤:

① 图像做傅里叶变换--转换到频域;

② 在频域处理(对频谱图像处理,剔除不需要的频段);

③ 反傅里叶变换--转换到空间域;

④ 如果不能一次得到最终效果,可能还需要添加一些blob分析方法

傅里叶变换频域图特点:

傅里叶变换理论与公式这里不做介绍,大家有兴趣自行搜索。先看下如下图片:

 

对应的使用fft_image()转换后的傅里叶频谱图像

read_image (Image, 'C:/Users/3252314061/Desktop/1.png')
fft_image (Image, ImageFFT)

 

 原图水平方向上变化更多,所以频谱图水平方向更亮。竖直方向变化不比水平方向多,所以较水平方向暗。下图正好相反:

傅里叶变换后的频谱图:

原图竖直方向上变化更多,所以频谱图竖直方向更亮。水平方向变化不比竖直方向多,所以较竖直方向暗。

fft_image()变换后频谱图像中心为低频部分,越往边缘是高频部分。

再看看下面的图像,频谱图变化也是沿着圆形的各个方向,反应像素灰度值的变化情况:

 

傅里叶变换去除图像条纹杂讯步骤:

图1--竖直条纹杂讯:

由观察可知,这幅图像有很多竖直条纹杂讯,沿水平方向变化较大,那么频谱图水平方向应该较亮,用fft_image()变换后效果:

那么如果我们想去除竖直条纹,就可以将频谱图中水平的亮线条区域抹掉(用灰度值0填充),如下:

 

 

然后fft_image_inv()反傅里叶变换看下效果:

fft_image_inv (ImageResult, ImageFFTInv)

 

图2-水平条纹杂讯:

 

由观察可知,这幅图像有很多水平条纹杂讯,沿竖直方向变化较大,那么频谱图竖直方向应该较亮,用fft_image()变换后效果: 

 

那么如果我们想去除水平条纹,就可以将频谱图中竖直的亮线条区域抹掉(用灰度值0填充),如下:

 

 

然后fft_image_inv()反傅里叶变换看下效果:

 

图3-水平垂直条纹杂讯: 

 

傅里叶频谱图:

 

水平和竖直方向均抹除:

 

 

反傅里叶变换效果:

 

完整代码(Halcon实现):whaosoft aiot http://143ai.com   

read_image (Image, './imgs/5.PNG')
rgb1_to_gray (Image, GrayImage)
fft_image (GrayImage, ImageFFT)

gen_rectangle1 (ROI_0, 2.97368, 217.535, 179.635, 227.458)
gen_rectangle1 (TMP_Region, 209.41, 217.535, 387.064, 226.465)
union2 (ROI_0, TMP_Region, ROI_0)
gen_rectangle1 (TMP_Region, 193.53, 234.404, 203.455, 374.316)
union2 (ROI_0, TMP_Region, ROI_0)
gen_rectangle1 (TMP_Region, 193.53, 74.6458, 204.447, 207.612)
union2 (ROI_0, TMP_Region, ROI_0)
 
paint_region (ROI_0, ImageFFT, ImageResult, 0, 'fill')
fft_image_inv (ImageResult, ImageFFTInv)

如果是彩色图,就先将彩图通道分离,在每个通道做傅里叶变换处理,然后反变换后合并通道即可。

### AS608指纹传感器与STM32的集成 AS608是一款广泛使用的光学指纹传感器,通常通过串口(UART)接口与微控制器通信。对于STM32平台,可以通过标准库或HAL库实现其驱动程序开发。 #### UART配置 在STM32中,AS608主要依赖于UART模块进行数据传输。以下是UART初始化的一个基本示例: ```c #include "stm32f1xx_hal.h" void MX_USART1_UART_Init(void) { huart1.Instance = USART1; huart1.Init.BaudRate = 9600; // 默认波特率设置为9600bps huart1.Init.WordLength = UART_WORDLENGTH_8B; huart1.Init.StopBits = UART_STOPBITS_1; huart1.Init.Parity = UART_PARITY_NONE; huart1.Init.Mode = UART_MODE_TX_RX; huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE; HAL_UART_Init(&huart1); } ``` 此部分代码用于初始化USART1外设,确保它能够以指定参数运行[^2]。 #### 数据包结构解析 AS608的数据交互基于特定命令帧格式完成。每一帧由起始字节、地址码、指令码以及校验和组成。发送给AS608的每条命令都需要遵循该协议。 以下是一个简单的函数模板用来构建并发送这些命令至传感器: ```c #define FINGERPRINT_STARTCODE (uint16_t)0xEF01 #define FINGERPRINT_ADDR ((uint8_t[]){0xFF, 0xFF, 0xFF, 0xFF}) // 发送命令到AS608 int sendFingerprintCommand(uint8_t cmdPacket[], uint16_t packetLen){ int i=0; while(i<packetLen){ HAL_UART_Transmit(&huart1,&cmdPacket[i],1,100); i++; } return i; } // 构建完整的命令包 void buildAndSendCmd(uint8_t commandCode,uint8_t paramCount,uint8_t params[]){ uint8_t cmdPacket[12]; uint16_t checksum=0; memcpy(cmdPacket,FINGERPRINT_ADDR,sizeof(FINGERPRINT_ADDR)); cmdPacket[sizeof(FINGERPRINT_ADDR)]=(FINGERPRINT_STARTCODE>>8)&0xFF; cmdPacket[sizeof(FINGERPRINT_ADDR)+1]=FINGERPRINT_STARTCODE&0xFF; cmdPacket[sizeof(FINGERPRINT_ADDR)+2]=(paramCount+4)>>8 & 0xFF ; cmdPacket[sizeof(FINGERPRINT_ADDR)+3]=(paramCount+4) & 0xFF ; cmdPacket[sizeof(FINGERPRINT_ADDR)+4]=commandCode; for(int j=0;j<paramCount;j++){ cmdPacket[sizeof(FINGERPRINT_ADDR)+5+j]=params[j]; checksum+=params[j]; } checksum +=(paramCount+4)+(commandCode+FINGERPRINT_STARTCODE); cmdPacket[sizeof(FINGERPRINT_ADDR)+5+paramCount]=(checksum >>8 )&0xFF; cmdPacket[sizeof(FINGERPRINT_ADDR)+5+paramCount+1]=checksum &0xFF; sendFingerprintCommand(cmdPacket,sizeof(cmdPacket)); } ``` 以上代码片段展示了如何创建一个通用的方法来封装向AS608发出的各种请求操作[^3]。 #### 接收响应处理 当接收到来自AS608的消息时,则需按照相同的帧格式对其进行解码分析。这一步骤同样重要,因为只有正确理解返回的结果才能进一步采取行动。 ---
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值