FPGA + 图像处理 (二) RGB转YUV色域、转灰度图及仿真

前言

具体关于色域的知识就不细说了,简单来讲YUV中Y通道可以理解为就是图像的灰度图,因此,将RGB转化为YUV是求彩色图的灰度直方图、进行二值化操作等的基础。

HDMI时序生成模块

这里先介绍一下仿真时用于生成HDMI时序,用这个时序来向数据处理模块输入数据,一是可以做到通过同步信号简化对图像数据的管理,二是可以让测试的数据处理模块更方便的适配用HDMI显示的图像处理工程。

 HDMI的单帧时序如图,具体时序知识不细说,下面代码实现的功能简单理解就是当data_req(数据请求)信号拉高时,开始向模块内输入图像数据,连续输入一行的数据,然后直接输出图像数据,当输出数据时拉高hdmi_de(数据有效)信号。因为本次是单帧的图像,所以hdmi_vs(场同步)信号以及hdmi_hs(行同步)信号是用不到的。

要注意不同尺寸的图像对应的参数不同,本模块适用于1280*720像素的图像

module hdmi_tim_gen(input           	clk			,input           	rst_n	    ,input   	[23:0]  data_in		,output          	hdmi_hs		,     //行同步信号output          	hdmi_vs		,     //场同步信号output          	hdmi_de		,     //数据使能output  	[23:0]  hdmi_data	,     //图像数据output		reg		data_req 	
);//1280*720 分辨率时序参数
parameter  H_SYNC   =  11'd40;  
parameter  H_BACK   =  11'd220; 
parameter  H_DISP   =  11'd1280;
parameter  H_FRONT  =  11'd110; 
parameter  H_TOTAL  =  11'd1650;parameter  V_SYNC   =  11'd5;   
parameter  V_BACK   =  11'd20;  
parameter  V_DISP   =  11'd720; 
parameter  V_FRONT  =  11'd5;   
parameter  V_TOTAL  =  11'd750; reg  [11:0] 	cnt_h;
reg  [11:0] 	cnt_v;reg [10:0] pixel_xpos;
reg [10:0] pixel_ypos;assign hdmi_de  = data_req;
assign hdmi_hs  = ( cnt_h < H_SYNC ) ? 1'b0 : 1'b1; 
assign hdmi_vs  = ( cnt_v < V_SYNC ) ? 1'b0 : 1'b1; //图像数据输出
assign hdmi_data = hdmi_de ? data_in : 24'd0;//请求像素点数据输入
always @(posedge clk or negedge rst_n) beginif(!rst_n)data_req <= 1'b0;else if(((cnt_h >= H_SYNC + H_BACK - 2'd2) && (cnt_h < H_SYNC + H_BACK + H_DISP - 2'd2))&& ((cnt_v >= V_SYNC + V_BACK) && (cnt_v < V_SYNC + V_BACK+V_DISP)))data_req <= 1'b1;elsedata_req <= 1'b0;
end//像素点x坐标
always@ (posedge clk or negedge rst_n) beginif(!rst_n)pixel_xpos <= 11'd0;else if(data_req)pixel_xpos <= cnt_h + 2'd2 - H_SYNC - H_BACK ;else pixel_xpos <= 11'd0;
end//像素点y坐标	
always@ (posedge clk or negedge rst_n) beginif(!rst_n)pixel_ypos <= 11'd0;else if((cnt_v >= (V_SYNC + V_BACK)) && (cnt_v < (V_SYNC + V_BACK + V_DISP)))pixel_ypos <= cnt_v + 1'b1 - (V_SYNC + V_BACK) ;else pixel_ypos <= 11'd0;
end//行计数器对像素时钟计数
always @(posedge clk or negedge rst_n) beginif (!rst_n)cnt_h <= 11'd0;else beginif(cnt_h < H_TOTAL - 1'b1)cnt_h <= cnt_h + 1'b1;else cnt_h <= 11'd0;end
end//场计数器对行计数
always @(posedge clk or negedge rst_n) beginif (!rst_n)cnt_v <= 11'd0;else if(cnt_h == H_TOTAL - 1'b1) beginif(cnt_v < V_TOTAL - 1'b1)cnt_v <= cnt_v + 1'b1;else cnt_v <= 11'd0;end
endendmodule

RGB转YUV模块

前面也说过了,YUV中的Y通道就是图像的灰度图,以此,单独将Y通道输出就可以得到彩色图像的灰度图

module rgb2yuv
(input               clk          	,  input               rst_n        	,  input               vs_i    		,  input               de_i    		,  input       [23:0]  data_i     		,  output              vs_o  			,  output              de_o  			,  output      [23:0]  data_yuv       	, output      [7:0]   data_gray       	);//YUV中Y指明亮度,也就是灰度值,(U,V)指色度,即饱和度和色调reg  [15:0]   rgb_r_m0, rgb_r_m1, rgb_r_m2;
reg  [15:0]   rgb_g_m0, rgb_g_m1, rgb_g_m2;
reg  [15:0]   rgb_b_m0, rgb_b_m1, rgb_b_m2;
reg  [15:0]   img_y0 ;
reg  [15:0]   img_cb0;
reg  [15:0]   img_cr0;
reg  [ 7:0]   img_y1 ;
reg  [ 7:0]   img_cb1;
reg  [ 7:0]   img_cr1;
reg  [ 2:0]   vs_i_d;
reg  [ 2:0]   de_i_d   ;//wire define
wire [ 7:0]   rgb888_r;
wire [ 7:0]   rgb888_g;
wire [ 7:0]   rgb888_b;
wire [ 7:0]   img_y;
wire [ 7:0]   img_cb;
wire [ 7:0]   img_cr;assign rgb888_r         = data_i[23:16];
assign rgb888_g         = data_i[15:8];
assign rgb888_b         = data_i[7:0];
//同步输出数据接口信号
assign vs_o   		= vs_i_d[2]      	;
assign de_o 		= de_i_d[2]         ;
assign img_y		= img_y1 			;
assign img_cb		= img_cb1			;
assign img_cr		= img_cr1			;
assign data_yuv		= {img_y,img_cb,img_cr};		
assign data_gray	= img_y;
/********************************************************RGB888 to YCbCrY  = 0.299R +0.587G + 0.114BCb = 0.568(B-Y) + 128 = -0.172R-0.339G + 0.511B + 128CR = 0.713(R-Y) + 128 = 0.511R-0.428G -0.083B + 128Y  = (77 *R    +    150*G    +    29 *B)>>8Cb = (-43*R    -    85 *G    +    128*B)>>8 + 128Cr = (128*R    -    107*G    -    21 *B)>>8 + 128Y  = (77 *R    +    150*G    +    29 *B        )>>8Cb = (-43*R    -    85 *G    +    128*B + 32768)>>8Cr = (128*R    -    107*G    -    21 *B + 32768)>>8
*********************************************************///step1 计算括号内的各乘法项
always @(posedge clk or negedge rst_n) beginif(!rst_n) beginrgb_r_m0 <= 16'd0;rgb_r_m1 <= 16'd0;rgb_r_m2 <= 16'd0;rgb_g_m0 <= 16'd0;rgb_g_m1 <= 16'd0;rgb_g_m2 <= 16'd0;rgb_b_m0 <= 16'd0;rgb_b_m1 <= 16'd0;rgb_b_m2 <= 16'd0;endelse beginrgb_r_m0 <= rgb888_r * 8'd77 ;rgb_r_m1 <= rgb888_r * 8'd43 ;rgb_r_m2 <= rgb888_r * 8'd128;rgb_g_m0 <= rgb888_g * 8'd150;rgb_g_m1 <= rgb888_g * 8'd85 ;rgb_g_m2 <= rgb888_g * 8'd107;rgb_b_m0 <= rgb888_b * 8'd29 ;rgb_b_m1 <= rgb888_b * 8'd128;rgb_b_m2 <= rgb888_b * 8'd21 ;end
end//step2 括号内各项相加
always @(posedge clk or negedge rst_n) beginif(!rst_n) beginimg_y0  <= 16'd0;img_cb0 <= 16'd0;img_cr0 <= 16'd0;endelse beginimg_y0  <= rgb_r_m0 + rgb_g_m0 + rgb_b_m0;img_cb0 <= rgb_b_m1 - rgb_r_m1 - rgb_g_m1 + 16'd32768;img_cr0 <= rgb_r_m2 - rgb_g_m2 - rgb_b_m2 + 16'd32768;endend//step3 括号内计算的数据右移8位
always @(posedge clk or negedge rst_n) beginif(!rst_n) beginimg_y1  <= 8'd0;img_cb1 <= 8'd0;img_cr1 <= 8'd0;endelse beginimg_y1  <= img_y0 [15:8];img_cb1 <= img_cb0[15:8];img_cr1 <= img_cr0[15:8];end
end//延时3拍以同步数据信号
always@(posedge clk or negedge rst_n) beginif(!rst_n) beginvs_i_d 		<= 3'd0;de_i_d    	<= 3'd0;endelse beginvs_i_d 		<= {vs_i_d[1:0], vs_i};de_i_d    	<= {de_i_d[1:0], de_i};end
endendmodule

仿真TB文件

注意文件读取和保存的路径

关于一些仿真中用的系统命令可以参考我的testbench中一些常用的系统命令-CSDN博客这篇

本次仿真读取的是txt文件,需要通过matlab或者python将图像转化为txt,具体实现程序可看本人主页文章

`timescale 1ns/1nsmodule pic_tb();//hdmi_tim_gen模块接口reg             clk,rst_n				;
reg [23:0]      data_in					;wire      		hdmi_hs,hdmi_vs,hdmi_de ;
wire [23:0]  	hdmi_data  				;
wire 			data_req   				;//rgb2yuv模块接口reg  			vs_i,de_i	    ;
wire 			vs_o,de_o	    ;
wire [23:0] 	data_yuv		;
wire [7:0]        data_gray    ;
//延迟1clk,与data同步
always @(posedge clk)beginvs_i <= hdmi_vs;de_i <= hdmi_de;
end initial beginclk = 1;rst_n = 0;#20 rst_n = 1;
end
always #10 clk = ~clk;reg [23:0] img[0:1280*720-1];
reg [31:0] addr;
initial begin$readmemh("D:/pic/img2txt.txt",img);
endalways @(posedge clk or negedge rst_n)beginif(!rst_n)beginaddr <= 0		;data_in <= 0	;endelse if(data_req)begindata_in	 <= img[addr];addr	 <= addr + 1;if(addr == (1280*720-1))addr <= 0;end
endinteger file_out_yuv;
integer file_out_gray;
reg [31:0] out_addr;
initial beginfile_out_yuv = $fopen("D:/pic/fileout_yuv.txt","w");file_out_gray = $fopen("D:/pic/fileout_gray.txt","w");
endalways @(posedge clk or negedge rst_n)beginif(!rst_n)beginout_addr <= 0;endelse if(out_addr == 1280*720)begin$display("task finish \n");$fclose(file_out_yuv);$fclose(file_out_gray);$finish;endelse if(de_o)beginout_addr <= out_addr + 1;$fwrite(file_out_yuv,"%x\n",data_yuv);$fwrite(file_out_gray,"%x\n",data_gray);end
end//例化hdmi_tim_gen模块hdmi_tim_gen u_hdmi_tim_gen(.clk		 	(clk),	.rst_n	  		(rst_n),//input.data_in	 	(data_in),//output.hdmi_hs	 	(hdmi_hs),.hdmi_vs	 	(hdmi_vs),.hdmi_de	 	(hdmi_de),.hdmi_data 		(hdmi_data),.data_req  		(data_req)
);//例化rgb2yuv模块rgb2yuv u_rgb2yuv
(.clk         (clk),  	.rst_n       (rst_n),  		.vs_i    	(vs_i),  	.de_i    	(de_i),  	.data_i     (hdmi_data),.vs_o  		(vs_o),  	.de_o  		(de_o),  	.data_yuv     (data_yuv),.data_gray    (data_gray)	
);endmodule

运行与结果

工程层级

直接在vivado内部仿真即可

 仿真结果

可以看到这部分符合HDMI时序波形

原图

YUV格式

灰度图

结语

本次实验比较简单,直接拷贝到工程,路径也没有问题应该可以直接运行,不过还是把工程附上,供大家免费下载,共同学习。 

【免费】RGB图像转YUV及灰度图FPGA实现工程资源-CSDN文库

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/295071.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Rust---有关介绍

目录 Rust---有关介绍变量的操作Rust 数值库&#xff1a;num某些基础数据类型序列(Range)字符类型单元类型 发散函数表达式&#xff08;&#xff01; 语句&#xff09; Rust—有关介绍 得益于各种零开销抽象、深入到底层的优化潜力、优质的标准库和第三方库实现&#xff0c;Ru…

汽车贴膜改色小程序源码 汽车配色小程序源码 车身改色app源码 带后台 带数据

汽车贴膜改色小程序源码 车身改色app源码 汽车配色小程序源码 带后台 带数据 整站源码&#xff0c;包含完整前端小程序&#xff0c;后台源码&#xff0c;数据库数据。 直接部署&#xff0c;就能使用&#xff0c;源码素材远程开发&#xff0c;可以定制开发。 全开源&#xff0c;…

算法学习——LeetCode力扣图论篇1(797. 所有可能的路径、200. 岛屿数量、695. 岛屿的最大面积)

算法学习——LeetCode力扣图论篇1 797. 所有可能的路径 797. 所有可能的路径 - 力扣&#xff08;LeetCode&#xff09; 描述 给你一个有 n 个节点的 有向无环图&#xff08;DAG&#xff09;&#xff0c;请你找出所有从节点 0 到节点 n-1 的路径并输出&#xff08;不要求按特…

数据结构(初阶)第二节:顺序表

从本文正式进入对数据结构的讲解&#xff0c;开始前友友们要有C语言的基础&#xff0c;熟练掌握动态内存管理、结构体、指针等章节&#xff0c;方便后续的学习。 顺序表&#xff08;Sequence List&#xff09; 线性表的概念&#xff1a;线性表&#xff08;linear list&#xff…

数据结构进阶篇 之 【插入排序】详细讲解(直接插入排序,希尔排序)

千万不要因为一件事不会做而失去信心&#xff0c;你又不是只有这一件事不会&#xff0c;你还有很多呢 一、插入排序 1.直接插入排序 InsertSort 1.1 基本思想 1.2 实现原理 1.3 代码实现 1.4 直接插入排序的特性总结 2.希尔排序 ShellSort 2.1 基本思想 2.2 实现原理 …

Docker命令及部署Java项目

文章目录 简介Docker镜像镜像列表查找镜像拉取镜像删除镜像镜像标签 Docker容器容器启动容器查看容器停止和重启后台模式和进入强制停止容器清理停止的容器容器错误日志容器别名及操作 Docker部署Java项目 简介 Docker是一种容器化技术&#xff0c;可以帮助开发者轻松打包应用…

什么是AIGC,AIGC的应用领域有哪些,以及对AIGC的未来展望有什么值得关注的方向

AIGC:人工智能生成内容的深度解析 在数字技术的浪潮中,AIGC(ArtificialIntelligenceGeneratedContent,人工智能生成内容)逐渐崭露头角,成为继专业生产内容(PGC)和用户生产内容(UGC)之后的新型内容创作方式。它不仅改变了内容生产的传统模式,更在多个行业中展现出…

【原创】基于springboot+vue学生信息管理系统设计与实现

个人主页&#xff1a;程序猿小小杨 个人简介&#xff1a;从事开发多年&#xff0c;Java、Php、Python、前端开发均有涉猎 博客内容&#xff1a;Java项目实战、项目演示、技术分享 文末有作者名片&#xff0c;希望和大家一起共同进步&#xff0c;你只管努力&#xff0c;剩下的交…

国资委确定首批起航企业,重点布局人工智能、量子信息等新兴领域

国务院国资委近日按照“四新”&#xff08;新赛道、新技术、新平台、新机制&#xff09;标准&#xff0c;遴选确定了首批启航企业&#xff0c;加快新领域新赛道布局、培育发展新质生产力。 据了解&#xff0c;去年以来&#xff0c;国务院国资委围绕加快培育创新型国有企业&…

手机销量分析案例

项目背景 某电商商城随着业务量的发展&#xff0c;积累了大量的用户手机销售订单数据。决策层希望能够通过对这些数据的分析了解更多的用户信息及用户的分布&#xff0c;从而可以指导下一年的市场营销方案以及更加精准的定位市场&#xff0c;进行广告投放。 数据说明 数据时…

YARN集群 和 MapReduce 原理及应用

YARN集群模式 本文内容需要基于 Hadoop 集群搭建完成的基础上来实现 如果没有搭建&#xff0c;请先按上一篇: <Linux 系统 CentOS7 上搭建 Hadoop HDFS集群详细步骤> 搭建&#xff1a;https://mp.weixin.qq.com/s/zPYsUexHKsdFax2XeyRdnA 配置hadoop安装目录下的 etc…

【JavaEE初阶系列】——多线程案例三——定时器

目录 &#x1f6a9;定时器是什么 &#x1f6a9;标准库中的定时器 &#x1f6a9;自定义定时器 &#x1f388;构造Task类 &#x1f4dd;相对时间和绝对时间 &#x1f388;构造MyTime类 &#x1f4dd;队列空和队列不为空 &#x1f4dd;wait(带参)解决消耗资源问题 &#…

CentOS7安装Flink1.17伪分布式

前提条件 拥有1台CentOS7 CentOS7安装好jdk&#xff0c;官方文档要求java 11&#xff0c;使用java 8也可以。可参考 CentOS7安装jdk8 下载安装包 下载安装包 [hadoopnode1 ~]$ cd installfile/ [hadoopnode1 installfile]$ wget https://archive.apache.org/dist/flink/flin…

4款在线网页原型图设计软件推荐

与桌面端相比&#xff0c;在线网页原型设计软件的使用具有优势&#xff0c;因为在线网页原型设计软件在整个使用过程中不需要安装&#xff0c;在线网页原型设计软件在任何地方都没有限制。更重要的是&#xff0c;无论是现在使用的 Linux&#xff0c;在线网页原型设计软件在操作…

SV学习笔记(一)

SV&#xff1a;SystemVerilog 开启SV之路 数据类型 內建数据类型 四状态与双状态 &#xff1a; 四状态指0、1、X、Z&#xff0c;包括logic、integer、 reg、 wire。双状态指0、1&#xff0c;包括bit、byte、 shortint、int、longint。 有符号与无符号 &#xff1a; 有符号&am…

使用 FinalShell 进行远程连接(ssh 远程连接 Linux 服务器)

目录 前言 基本使用教程 新建远程连接 连接主机 自定义命令 路由追踪 前言 后端开发&#xff0c;必然需要和服务器打交道&#xff0c;部署应用&#xff0c;排查问题&#xff0c;查看运行日志等等。一般服务器都是集中部署在机房中&#xff0c;也有一些直接是云服务器&am…

UGUI 进阶

UI事件监听接口 目前所有的控件都只提供了常用的事件监听列表 如果想做一些类似长按&#xff0c;双击&#xff0c;拖拽等功能是无法制作的 或者想让Image和Text&#xff0c;RawImage三大基础控件能够响应玩家输入也是无法制作的 而事件接口就是用来处理类似问题 让所有控件都…

【MySQL系列】使用 ALTER TABLE 语句修改表结构的方法

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

图的应用试题

01&#xff0e;任何一个无向连通图的最小生成树( )。 A.有一棵或多棵 B.只有一棵 C.一定有多棵 D.可能不存在 02.用Prim算法和Kruskal算法构造图的最小生成树&#xff0c;…

2024/4/2 IOday4

使用文件IO 实现父进程向子进程发送信息&#xff0c;并总结中间可能出现的各种问题 #include <stdio.h> #include <string.h> #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd…