【FPGA】中值滤波处理BMP图片

2023-05-16

文章目录

  • 一、中值滤波
  • 二、BMP图片格式
  • 三、功能实现
      • 1.代码设计思路
      • 2.shift IP核
      • 3.代码实现
  • 四、结果测试
  • 参考博客

一、中值滤波

中值滤波法是一种非线性平滑技术,它将每一像素点的灰度值设置为该点某邻域窗口内的所有像素点灰度值的中值。
中值滤波是基于排序统计理论的一种能有效抑制噪声的非线性信号处理技术,中值滤波的基本原理是把数字图像或数字序列中一点的值用该点的一个邻域中各点值的中值代替,让周围的像素值接近真实值,从而消除孤立的噪声点。

二、BMP图片格式

bmp文件的存储格式是Windows系统中广泛使用的图像文件格式,对图像不做任何程度的压缩处理,主要分为位图头文件,位图信息头,调色板信息,像素数据四大部分,由于通常是处理RBG图像,因此仅讨论RGB的情况

位图头文件 :文件的格式、大小等信息,前14Byte;主要关心的是图像尺寸,像素数据开始位置。
位图信息头:提供图像数据的尺寸、位平面数、压缩方式、颜色索引等信息,前40Byte;主要关心的是图像宽度,图像高度。
调色板信息:保留字,不关心
像素数据 :像素数据,8bit一个像素数据,即1Byte。

三、功能实现

1.代码设计思路

在这里插入图片描述

第一步:对3x3窗口的每一行进行排序,得到每行max,mid,min数
第二步:对第一步排序得到的第一列3个max排序取min,第二列3个mid排序取mid,第三列 3个min排序取max
第三步:对第二步产生的三个数进行排序,取mid得到中值

2.shift IP核

altera提供了矩阵的IP核,我们设置好位宽8、两路输出、每行640个深度(图像长度),这样就能生成一个3x3的矩阵
在这里插入图片描述shift ip核仿真图:

3.代码实现

在这里插入图片描述
我们首先把输入的数据放进filter_3x3模块,然后通过shift IP核生成一个3x3的窗口,然后再通过sort_3模块对窗口里9个数进行排序得到中值并输出。

median_filter顶层模块

module median_filter(
    input               clk     ,
    input               rst_n   ,
    
    input               iValid  ,
    input       [7:0]   iData   ,

    output      [7:0]   oData
);

//参数定义
wire    [7:0]filter_11;
wire    [7:0]filter_12;
wire    [7:0]filter_13;

wire    [7:0]filter_21;
wire    [7:0]filter_22;
wire    [7:0]filter_23;

wire    [7:0]filter_31;
wire    [7:0]filter_32;
wire    [7:0]filter_33;
																																															
wire    [7:0]max1;
wire    [7:0]max2;
wire    [7:0]max3;

wire    [7:0]mid1;
wire    [7:0]mid2;
wire    [7:0]mid3;

wire    [7:0]min1;
wire    [7:0]min2;
wire    [7:0]min3;

wire    [7:0]min_of_max;
wire    [7:0]max_of_min;
wire    [7:0]mid_of_mid;

filter_3x3 inst_filter_3x3(
    .clk      (clk),
    .rst_n    (rst_n),
    .iValid   (iValid),
    .iData    (iData),

    .oData_11 (filter_11), 
    .oData_12 (filter_12), 
    .oData_13 (filter_13),

    .oData_21 (filter_21), 
    .oData_22 (filter_22), 
    .oData_23 (filter_23),

    .oData_31 (filter_31), 
    .oData_32 (filter_32), 
    .oData_33 (filter_33)
);

//第一步:对3x3窗口的每一行进行排序,得到每行max,mid,min数
sort_3 inst_sort_3_11(
    .clk   (clk),
    .rst_n (rst_n),
    .data1 (filter_11),
    .data2 (filter_12),
    .data3 (filter_13),
    .max   (max1),
    .mid   (mid1),
    .min   (min1)
);
sort_3 inst_sort_3_12(
    .clk   (clk),
    .rst_n (rst_n),
    .data1 (filter_21),
    .data2 (filter_22),
    .data3 (filter_23),
    .max   (max2),
    .mid   (mid2),
    .min   (min2)
);
sort_3 inst_sort_3_13(
    .clk   (clk),
    .rst_n (rst_n),
    .data1 (filter_31),
    .data2 (filter_32),
    .data3 (filter_33),
    .max   (max3),
    .mid   (mid3),
    .min   (min3)
);

//第二步:对第一步排序得到的第一列3个max排序取min,第二列3个mid排序取mid,第三列 3个min排序取max
sort_3 inst_sort_3_21(
    .clk   (clk),
    .rst_n (rst_n),
    .data1 (max1),
    .data2 (max2),
    .data3 (max3),
    .max   (),
    .mid   (),
    .min   (min_of_max)
);
sort_3 inst_sort_3_22(
    .clk   (clk),
    .rst_n (rst_n),
    .data1 (mid1),
    .data2 (mid2),
    .data3 (mid3),
    .max   (),
    .mid   (mid_of_mid),
    .min   ()
);
sort_3 inst_sort_3_23(
    .clk   (clk),
    .rst_n (rst_n),
    .data1 (min1),
    .data2 (min2),
    .data3 (min3),
    .max   (max_of_min),
    .mid   (),
    .min   ()
);

//第三步:对第二步产生的三个数进行排序,取mid得到中值
sort_3 inst_sort_3_3(
    .clk   (clk),
    .rst_n (rst_n),
    .data1 (min_of_max),
    .data2 (mid_of_mid),
    .data3 (max_of_min),
    .max   (),
    .mid   (oData),
    .min   ()
);
endmodule

fitlet_3x3模块

module filter_3x3(
    input               clk         ,
    input               rst_n       ,


    input       [7:0]   iData       ,
    input               iValid      ,

    output  reg [7:0]   oData_11    ,
    output  reg [7:0]   oData_12    ,
    output  reg [7:0]   oData_13    ,

    output  reg [7:0]   oData_21    ,
    output  reg [7:0]   oData_22    ,
    output  reg [7:0]   oData_23    ,

    output  reg [7:0]   oData_31    ,
    output  reg [7:0]   oData_32    ,
    output  reg [7:0]   oData_33    
);

    reg     [7:0]   row3_data   ;
    wire    [7:0]   row2_data   ;
    wire    [7:0]   row1_data   ;

     // shift_ram实现2行缓存
    line_shift_ram inst_line_shift_ram(
        .clock    (clk),
        .clken    (iValid),
        .shiftin  (row3_data),
        .taps0x   (row2_data),
        .taps1x   (row1_data),
        .shiftout ()
    );

    // 将输入数据寄存作为窗口第三行起始数据,同时也作为行缓存的输入
    always @(posedge clk, negedge rst_n) begin
        if(!rst_n)
            row3_data <= 0;
        else if(iValid)
            row3_data <= iData;
        else 
            row3_data <= 0;
    end

    // 获取3x3模板
    always @(posedge clk, negedge rst_n) begin
        if(!rst_n) begin
            {oData_11, oData_12, oData_13} <= 3'b000;
            {oData_21, oData_22, oData_23} <= 3'b000;
            {oData_31, oData_32, oData_33} <= 3'b000;
        end else if(iValid) begin
            {oData_11, oData_12, oData_13} <= {oData_12, oData_13, row1_data};
            {oData_21, oData_22, oData_23} <= {oData_22, oData_23, row2_data};
            {oData_31, oData_32, oData_33} <= {oData_32, oData_33, row3_data};
        end
    end

endmodule

sort_3模块

//排序模块,对三个数进行排序
module sort_3(
    input               clk     ,
    input               rst_n   ,
    input       [7:0]   data1   ,
    input       [7:0]   data2   ,
    input       [7:0]   data3   ,
    output reg  [7:0]   max     ,
    output reg  [7:0]   mid     ,
    output reg  [7:0]   min
);

//max最大数
always @(posedge clk or negedge rst_n)begin
    if(!rst_n)
        max <= 1'b0 ;
    else if(data1 >= data2 && data1 >= data3)
        max <= data1;
    else if(data2 >= data1 && data2 >= data3)
        max <= data2;
    else
        max <= data3;
end

//mid中间数
always @(posedge clk or negedge rst_n)begin
    if(!rst_n)
        mid <= 1'b0 ;
    else if((data1 >= data2 && data1 <= data3) || (data1 >= data3 && data1 <= data2))
        mid <= data1;
    else if((data2 >= data1 && data2 <= data3) || (data2 >= data3 && data2 <= data1))
        mid <= data2;
    else
        mid <= data3;
end

//min最小数
always @(posedge clk or negedge rst_n)begin
    if(!rst_n)
        min <= 1'b0 ;
    else if(data1 <= data2 && data1 <= data3)
        min <= data1;
    else if(data2 <= data1 && data2 <= data3)
        min <= data2;
    else
        min <= data3;
end
endmodule

tb文件

`timescale 1ns / 1ns

module bmp_tb;
reg				clk		;
reg				rst_n	;
reg				iValid	;
reg		[7:0]	iData	;
wire	[7:0]	oData	;


//图像属性:图像宽度 图像高度 图像尺寸 图像像素点起始位
integer bmp_width;
integer bmp_high;
integer bmp_size;
integer start_index;

//bmp file id
integer bmp_file_id;
integer bmp_dout_id;
integer dout_txt_id;

//文件句柄
integer h;
//文件bmp文件数据
reg		[7:0]	rd_data  [0:307200];//根据自己图片大小
reg		[7:0]	dout_data  [0:307200];

//写操作
reg		[23:0]	wr_data;
integer i = 0;
integer index,index0;



median_filter median_filter_inst(
    .clk	(clk	),
    .rst_n	(rst_n	),

    .iValid	(iValid	),
    .iData	(iData	),

    .oData	(oData	)
);


//时钟周期设置
parameter CYCLE =20;
initial begin
	clk = 1;
	forever
	#(CYCLE/2)
	clk=~clk;
end
//复位设置
initial begin
	rst_n = 1;
	#(CYCLE*2);
	rst_n = 0;
	#(CYCLE*3);
	rst_n = 1;
end

initial
begin
	iValid = 0;
	#(6*CYCLE)
	//打开原始图像
	bmp_file_id = $fopen("D:\\desktop\\in_img.bmp","rb");
	//打开输出图像
	bmp_dout_id = $fopen("D:\\desktop\\out_img.bmp","wb");
	//打开输出数据
	dout_txt_id = $fopen("D:\\desktop\\out_img.txt","w+");

	//读取bmp文件
	h = $fread(rd_data,bmp_file_id);

    // 图像宽度
	bmp_width = {rd_data[21], rd_data[20], rd_data[19], rd_data[18]};
	// 图像高度
	bmp_high = {rd_data[25], rd_data[24], rd_data[23], rd_data[22]};
	// 像素起始位置
	start_index = {rd_data[13], rd_data[12], rd_data[11], rd_data[10]};
	// 图像尺寸
	bmp_size = {rd_data[5], rd_data[4], rd_data[3], rd_data[2]};
	// bmp_size = 307200;
	$fclose(bmp_file_id);

	index = start_index;
	repeat(646)begin
	#(CYCLE);
	iData = rd_data[index];
	iValid = 1;
	index = index + 1;
	end
	repeat(bmp_size-646)begin
	#(CYCLE);
	dout_data[index-646] = oData;
	iData = rd_data[index];
	index = index + 1;
	end
	iValid = 0;
	repeat(646)begin
	#(CYCLE);
	dout_data[index-646] = oData;
	iData = rd_data[index];
	index = index + 1;
	end

	//输出BMP
	for(i = 0; i < bmp_size; i = i + 1)begin
		if(i < start_index)
             $fwrite(bmp_dout_id, "%c", rd_data[i]);//注意参数%c
		else 
			 $fwrite(bmp_dout_id, "%c", dout_data[i]);
    end
    $fclose(bmp_dout_id);

	//输出txt,只存像素点
    for(index0 = start_index; index0 < bmp_size-2; index0 = index0 + 3)begin
        wr_data = {dout_data[index0 + 2], dout_data[index0 + 1], dout_data[index0]};
        $fwrite(dout_txt_id, "%d,", wr_data[7:0]);
        $fwrite(dout_txt_id, "%d,", wr_data[15:8]);
        $fwrite(dout_txt_id, "%d\n", wr_data[23:16]);
    end
    $fclose(dout_txt_id);
   
end

endmodule

四、结果测试

代码完成后,在tb文件里的对应路径创建好所需要输出图片的bmp和txt文件,然后进行仿真
在这里插入图片描述

在这里插入图片描述
仿真完成后可以看到得到了滤波后的图片在这里插入图片描述

原图与滤波后图对比
在这里插入图片描述在这里插入图片描述

参考博客

中值滤波代码参考:
http://t.csdn.cn/XnTAc
http://t.csdn.cn/JWYsX
bmp图片格式:
http://t.csdn.cn/enoq8
shift IP核
http://t.csdn.cn/zbWdU

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【FPGA】中值滤波处理BMP图片 的相关文章

  • xilinx xdma PCIe中断bug

    xilinx xdma PCIe中断存在bug bug1 此中断虽然是msi或者msx中断 但是不中断cpu bug2 此中断不是边沿中断 而是电平中断 在驱动层需要不断地轮训查询中断事件 bug3 此中断持续时间必须长 而且在收到中断应答
  • 【数字IC】从零开始的Verilog SPI设计

    从零开始的Verilog SPI协议设计 一 写在前面 1 1 协议标准 1 2 数字IC组件代码 1 3 设计要求 1 4 其他协议解读 1 4 1 UART协议 1 4 2 SPI协议 1 4 3 I2C协议 1 4 4 AXI协议 二
  • Lattice Diamond安装

    1 下载 到Lattice官网 http www latticesemi com 注册一个lattice的账号后就可以去下载Diamond 登陆后如下图 根据自己系统情况选择对应的版本 我用的是32位win8 Diamond软件安装包和La
  • 【PIPE】流水线设计中的基本模块

    大概分成以下几节 1 概述及协议 2 valid forward valid超前 3 bubble collapse 消除气爆 4 input output skid 不知中文怎么说 5 pipe halt 流水停顿 6 idle pres
  • 保存为 JPEG with Pillow 的图像与原始图像不同。

    我有一个 3 d numpy 数组 并使用 Pillow 将其保存为 JPEG 图像 当我使用 Pillow 重新加载图像时 生成的 numpy 数组有所不同 我为此编写了一个演示代码 from PIL import Image impor
  • 64 位 ALU 输出在 TestBench 波上显示高阻抗

    我必须制作一个 64 位 ALU 它接受 A 和 B 64 位输入 进位输入输入并输出 64 位结果以及 1 位进位输出 还有一个 5 位功能选择 FS 其中 FS 0 控制 B 是否反转 使用 2to1 多路复用器 F 1 对 A 执行相
  • java中bmp转jpg

    Java中如何将bmp转换为jpg 我知道如何使用ImageIO但有没有更快或更好的方法呢 这是我在网上找到的 ImageIO 方法 Create file for the source File input new File c temp
  • bmp 文件应该用于网站吗

    在网站上使用 bmp 文件时是否存在问题 文件大小除外 使用 2002 年后的浏览器或 Internet Explorer 没有问题 它们会显示它 IE 支持它和其他 你可以找到代码适用于 Mozilla Firefox and 适用于 C
  • 如何在 Java 中从原始 byte[] 创建 BMP 文件

    我有一个 C 应用程序 它与相机通信并获取原始图像数据 然后我有一个 C 中的 Byte 我想用 JNI 将其发送到 Java 但是 我需要将原始 Byte 转换为真实的文件格式 bmp 是我的第一选择 如果我使用 BITMAPFILEIN
  • 使用 VHDL 实例化 FPGA 中的 RAM

    我试图按照中的指导实现双端口 RAM这篇优秀的博文 http danstrother com 2010 09 11 inferring rams in fpgas 然而 ModelSim 在编译时给出以下警告 Warning fifo ra
  • 如何生成异步复位verilog总是阻塞凿子

    Chisel 始终生成敏感度列表中仅包含时钟的块 always posedge clk begin end 是否可以将模块配置为使用异步重置并生成这样的始终块 always posedge clk or posedge reset begi
  • VHDL门控时钟如何避免

    我收到了避免使用门控时钟的建议 因为它可能会导致松弛和时序限制问题 但我想问一下我可以认为什么是门控时钟 例如 此代码对时钟进行门控 因为 StopCount 对它进行门控 process ModuleCLK begin if rising
  • 在 C# 中将所有内容转换为 JPG

    我有一个如下所示的函数 Convert To JPG public string AlltoJPG FileInfo foo Get file extension string fileExtension foo Extension Get
  • if 语句导致 Verilog 中的锁存推断?

    我正在编写用于合成算法的 Verilog 代码 我对哪些情况可能导致推断锁存器有点困惑 下面是这样的一段代码 虽然它在模拟中工作得很好 但我担心它可能会导致硬件问题 always b1 or b2 b1 map b2 map m1 map
  • 如何将位图照片转换为十六进制颜色代码?

    我正在尝试为我的简历创建一个程序 但我在转换时遇到问题bitmap照片就是灰度照片转为十六进制 或者更好地称之为代码 如果颜色 有人可以帮助我吗 我尝试将其转换为Base64字符串但它不起作用 openFileDialog1 new Ope
  • 赋值语句中的“others=>'0'”是什么意思?

    cmd register process rst n clk begin if rst n 0 then cmd r lt others gt 0 elsif clk event and clk 1 then cmd r lt end if
  • 无法使用c保存图像文件?

    我尝试将一个 bmp 图像克隆到另一个 bmp 图像中 但最终的图像无法打开 include
  • FPGA大输入数据

    我正在尝试向 FPGA 发送 4 KB 字符串 最简单的方法是什么 是我正在使用的fpga的链接 我正在使用 Verilog 和 Quartus 您的问题的答案在很大程度上取决于将数据输入 FPGA 的内容 即使没有您需要遵守的特定协议 S
  • delphi TBitmap是否支持alpha通道

    我听人们说事实并非如此 但是 我创建了一个 TBitmap 并通过以下方式清除了整个区域 For I 1 to bmp Width do For J 0 to bmp Height do bmp canvas Pixels I J 0000
  • 读/写简单 BMP 图像 C++

    我正在尝试读取简单的 BMP 文件 并且在不执行任何操作的情况下将其再次写回文件 我不知道读取文件或写回文件时出错在哪里 我在阅读和写作时添加了填充 文件读取 std vector

随机推荐

  • YOLOv5 数据集划分及生成labels

    0 本人文件夹存放格式 xff08 因为要测试多个数据集和不同的yolov5版本和其他算法 xff0c 所以数据集整体放到外面 xff09 1 划分数据集 验证集 测试集 coding utf 8 import os import rand
  • mission planner发送数据之mavlink

    前段时间研究mp的地面站 xff0c 看了几天有点体会 xff0c 看网上的解析比较少 xff0c 写上来和大家分享下 xff0c 全是自己的理解 xff0c 东西比较少 xff0c 硬货不多 xff0c 还请见谅 最开始是想做个无人机超声
  • 实验三、嵌入式Linux网络通信实验

    实验三 嵌入式Linux网络通信实验 一 实验目的 1 掌握TCP与UDP协议原理 2 掌握套接字通信原理 2 掌握TCP套接字服务器端与客户端通信方法 二 实验基本要求 1 学习TCP与UDP协议原理 2 掌握TCP套接字服务器端与客户端
  • QT重载keyPress焦点问题

    最近项目上需要用到键盘上的快捷键 xff0c 就重载了键盘的按下事件 xff0c 以为万事大吉 实际界面上有很多控件 xff0c 导致如果鼠标点击了其中一个不能接收焦点的控件 xff0c 就不知道焦点传到了什么地方 上网查大致两种思路 xf
  • QT实现地图或图片的细节图(抓取图片的细节,放大图片)

    最近由于项目上的要求 xff0c 需要实现一个细节图 xff0c 就是一个矩形框中加载一个大图 xff0c 右下或者左下方有一个小矩形框 xff0c 可以加载全图 xff0c 并显示大矩形框中图片在全图的位置 xff0c 有点拗口 xff0
  • centos7 搭建vtk7.1.1+Qt开发环境+运行编译工程

    一 CMAKE安装 vtk必须用cmake编译 xff0c 但是 xff0c 由于高版本的cmake没有支持qt5的gui xff0c 所以选择低版本的 xff0c 但是低版本的必须得依赖于qt4 xff0c 而qt4相较于qt5 xff0
  • centos搭建vtk开发环境

    一 OpenGL3 0 vtk有个硬性要求就是OpenGL3 0及以上版本 xff0c 由于笔者此前使用的是centos7 xff0c 照着网上的教程配置OpenGL xff0c 但是之后glxinfo grep OpenGL发现openg
  • 读取ugrid格式文件

    include lt iostream gt include lt vector gt include lt string gt include lt fstream gt using namespace std int main int
  • C语言:#define详解

    define定义标识符 语法 xff1a define name stuff tips xff1a 我们在define定义标识符的时候 xff0c 不建议在后面加上 xff1b xff0c 这样很容易出问题 比如说在以下的情况中 xff1a
  • FPGA学习-UART串口发送单字节(UART时序分析+真正的FPGA设计看图写代码)

    首先看UART发送时序图 xff1a 要发送一个完整字节 xff0c 需要 1位起始位 43 8位数据位 43 1位停止位 xff0c 图上的第11位 xff0c 是确认一个字节发送完的一位 重点是每一位之间的发送时间需要保持一致 xff0
  • STM32串口2初始化

    在STM32提供的官方库里只有串口一的初始化代码 xff0c 但当你需要用到两个以上的串口 xff0c 就得自己写相应的代码 xff0c 下面是串口2的 xff0c 其他的串口也差不多 usart2 c include 34 sys h 3
  • VINS-Fusion跑kitti stereo及stereo+GPS数据

    Stereo source vfusion devel setup bash roslaunch vins vins rviz launch source vfusion devel setup bash rosrun loop fusio
  • vue 配置代理,简单解决跨域问题

    开发环境下 xff0c 借助vue cli简单解决跨域问题 配置方式一 xff1a 在vue config js文件中添加以下代码 xff1a devServer proxy 39 被代理的基础路径 39 这种方式只能配置一个代理 xff0
  • Wireshark网络抓包疯狂聊天程序

    文章目录 一 疯狂聊天环境配置二 使用wireshark进行抓包三 分析抓包四 参考文献 一 疯狂聊天环境配置 下载好疯狂聊天软件后 xff0c 打开计算机管理 xff0c 设备管理器 网络适配器中需要禁用这几项 xff0c 否则无法双向通
  • 游戏客户端编程

    文章目录 一 代码框架二 新建项目三 演示效果 一 代码框架 本次实验使用的网游客户端框架来自课堂老师的资料 链接 xff1a https pan baidu com s 1WSkrRTFPuN1N34BsySkeaQ 提取码 xff1a
  • 数学图形与机器视觉基础(1)

    文章目录 一 图片处理及分析1 修改图片位数和颜色并进行分析2 修改图片格式并进行分析 二 用奇异值分解 xff08 SVD xff09 对一张图片进行特征值提取 xff08 降维 xff09 处理三 采用图像的开闭运算 腐蚀 膨胀 xff
  • STM32之串口通信

    文章目录 一 串口通信与USART二 程序编写输出Hello Windows三 GPIO波形参考链接 一 串口通信与USART 二 程序编写输出Hello Windows 串口通信 串口通信是一种设备间非常常用的串行通行方式 xff0c 其
  • 【FPGA】UART串口通信

    文章目录 一 通信方式1 串行通信2 并行通信 二 UART串口通信1 模块设计与时序图2 代码实现 三 测试结果1 仿真结果2 上板验证 一 通信方式 1 串行通信 串行通信是指利用一条传输线将数据一位位地顺序传送 xff08 也就是说串
  • 【FPGA】基于状态机实现自动售货机模拟

    文章目录 一 售货机功能二 售货机状态分析及模块划分三 代码实现四 上板验证 一 售货机功能 此自动售货机模拟基于EP4CE6F17C8开发板实现 xff0c 用按键 xff0c led灯 xff0c 数码管表示各个输入输出 功能 xff1
  • 【FPGA】中值滤波处理BMP图片

    文章目录 一 中值滤波二 BMP图片格式三 功能实现1 代码设计思路2 shift IP核3 代码实现 四 结果测试参考博客 一 中值滤波 中值滤波法是一种非线性平滑技术 xff0c 它将每一像素点的灰度值设置为该点某邻域窗口内的所有像素点