FPGA图像处理-灰度化

news/2025/2/6 4:13:13/

简介

verilog实现彩色图像的灰度化算法,并进行Modelsim仿真。
图像处理操作中最简单的一类就是点操作,一个像素的输出只取决于输入图像的相应像素值。
RGBGRAY公式:
GRAY = 0.299R + 0.587G + 0.114B
由于FPGA不方便小数运算,所以放大256倍进行运算,然后右移8位:
GRAY = (77R + 150G + 29B) >> 8
彩色图像的灰度化属于点操作,但两级寄存器之间组合逻辑过多会导致时序出问题,所以对该公式进行流水线处理,分为三级流水线:

  • 第一级处理乘法
  • 第二级处理加法
  • 第三级处理移位

模块说明

module rgb2gray(input clk,input rst_n,// input data & validinput iValid,input [7:0] red,input [7:0] green,input [7:0] blue,// output data & validoutput oValid,output [7:0] gray
);

为了简单起见,输入输出都是valid+data的形式

第一级流水线:乘法

// 第一级乘法寄存器
reg [15:0] red_r;
reg [15:0] green_r;
reg [15:0] blue_r;always @(posedge clk, negedge rst_n) beginif(!rst_n) beginred_r   <= 0;green_r <= 0;blue_r  <= 0;end else beginred_r   <= red * 8'd77;green_r <= green * 8'd150;blue_r  <= blue * 8'd29;end
end

第二级流水线:加法

// 第二级加法寄存器
reg [15:0] gray_r1;always @(posedge clk, negedge rst_n) beginif(!rst_n)gray_r1 <= 0;elsegray_r1 <= red_r + green_r + blue_r;
end

第三级流水线:移位

// 第三级移位寄存器
reg [7:0] gray_r2;always @(posedge clk, negedge rst_n) beginif(!rst_n)gray_r2 <= 0;elsegray_r2 <= gray_r1[15:8];
end

valid延迟输出

因为流水线消耗了3个时钟周期,所以输出valid相较于输入valid要延迟3

// valid打三拍
reg [2:0] valid_shift;always @(posedge clk, negedge rst_n) beginif(!rst_n)valid_shift <= 0;elsevalid_shift <= {valid_shift[1:0], iValid};
endassign oValid = valid_shift[2];

Modelsim仿真

写个testbench模拟50个像素输入:

`timescale 1ns/1ns
module rgb2gray_tb;reg clk = 1'b1;always #10 clk = ~clk;reg rst_n = 1'b0;reg         iValid = 1'b0;reg [7:0]   red    = 8'd0;reg [7:0]   green  = 8'd0;reg [7:0]   blue   = 8'd0;// 用于对比wire [7:0] gray_ref = red * 0.299 + green * 0.587 + blue * 0.114;wire            oValid;wire    [7:0]   gray;initial begin#20 rst_n <= 1'b1;// 仿真50个像素repeat(50) begin#20;iValid <= 1'b1;red    <= $random;green  <= $random;blue   <= $random;end#100 $stop;endrgb2gray inst_rgb2gray(.clk    (clk),.rst_n  (rst_n),.iValid (iValid),.red    (red),.green  (green),.blue   (blue),.oValid (oValid),.gray   (gray));
endmodule

波形图如下:
在这里插入图片描述
图中gray_ref是参考答案,可以看出,graygray_ref慢三个时钟周期,因为模块内部有三级流水线。
输出与参考答案偶尔有误差,那是因为FPGA中没有进行浮点数运算,将小数放大了256倍,然后取整用于运算,最后再缩小256倍,肯定是有误差的,不过影响不大,可以忽略。


http://www.ppmy.cn/news/876066.html

相关文章

搭建微服务工程 【详细步骤】

一、准备阶段 &#x1f349; 本篇文章用到的技术栈 mysqlmybatis[mp]springbootspringcloud alibaba 需要用到的数据库 订单数据库: SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS 0;-- ---------------------------- -- Table structure for shop_order -- --------------…

django+pyecharts制作工单系统实时刷新可视化仪表盘并设置报表定时发送

目录 仪表盘整体项目文件夹结构 demo应用效果 demo应用 demo应用的sql语句 demo应用定义的查询mysql类 在demo/views.py文件中 demo应用部分完整代码 urls.py views.py index.html 没有模糊背景 bindex.html 有模糊背景 demo2应用 demo2应用效果 2,将demo和demo2应用结…

D29 Vue2 + Vue3 K64-K83

D29.Vue F10.组件编码流程 组件自定义事件 全局事件总线&#xff08;K64-K66&#xff09; 1.组件编码流程 A.组件编码流程&#xff1a; 1&#xff09;拆分静态组件&#xff1a;组件要按照功能点拆分&#xff0c;命名不要与html元素冲突 2&#xff09;实现动态组件…

D19

1、 编译时异常和运行时异常的区别 * 编译期异常&#xff1a;Java程序必须显示处理&#xff0c;否则程序就会发生错误&#xff0c;无法通过编译 * 运行期异常&#xff1a;无需显示处理&#xff0c;也可以和编译时异常一样处理 2、throws和throw的区别 throws 用在方法声明后面…

米尔基于STM32MP135核心板,助力充电桩发展

随着电动车的普及和人们环保意识的增强&#xff0c;充电桩作为电动车充电设备的重要一环&#xff0c;充电桩行业正迅速发展&#xff0c;消费市场的大量应用也造就市场的需求量不断增长。因此&#xff0c;产品的功能、可靠性、安全性等要求也变得尤为重要&#xff0c;而采用传统…

rust学习-泛型和trait

泛型 Option&#xff0c;Vec&#xff0c;HashMap<K, V>&#xff0c;Result<T, E>等&#xff0c;取函数以减少代码重复的机制 背景 两个函数&#xff0c;不同点只是名称和签名类型 fn largest_i32(list: &[i32]) -> i32 {let mut largest list[0];for &…

Win10系统优化工具

原址 : https://blog.csdn.net/qq_34072173/article/details/83988002 软件下载地址 : https://www.lanzous.com/i4f0rub

win10优化工具哪个好

不少刚安装好win10系统的用户觉得win10系统很卡&#xff0c;这是因为你没有进行win10优化导致的&#xff0c;今天小编就来跟各位介绍几款win10优化&#xff0c;希望对您的优化工作有帮助。 我们安装好电脑操作系统如果直接使用的话性能是得不到完全的发挥的&#xff0c;所有通过…