FPGA双线性插值图像缩放详细讲解,上板验证稳定通过,提供两套工程源码

news2024/9/21 16:17:00

开局直接放大招:提供源码及工程;
重点讲解双线性插值图像缩放;
此功能模块使用HLS实现,并已封装导出IP,可在工程中添加并使用,可提供HLS工程源码;
若是用verilog实现双线性插值图像缩放,是一项及其复杂的事情,且不能做到任意比例,网上也有源码,不信你可以去下载并验证,肯定做不到任意比例缩放;这样一来,HLS则成为了更好的选项,偷偷告诉你,HLS几行代码就搞定了;关于这个ip可以看我前面的文章HLS实现双线性插值图像缩放
前面文章里的IP适用于zynq系列机器,这里讲的这个IP适用于7系列机器;
前面废话太多了,直接上工程:
工程1:1080P缩小至720P;
开发板:Xilinx Kintex7 开发板;
开发环境:vivado2019.1;
输入:HDMI-1080P;
输出:HDMI-720P;
工程架构如下:
在这里插入图片描述
用电脑输出1080P视频模拟输入;
输入HDMI视频经IT6802解码为VGA格式的RGB视频流,关于IT6802的芯片解读和寄存器配置,请参考我前面的文章IT6802的芯片解读和寄存器配置
然后用Xilinx官方IP将VGA格式的RGB视频流转为AXIS视频流;
经自定义双线性插值图像缩放IP VIDEO SCALER将原视频缩小至720P;
后面就是Xilinx的图像处理套路了,什么VDMA之类的,这里就不多说了;
BD工程如下:
在这里插入图片描述
代码架构如下:
在这里插入图片描述
SDK软件文件如下:
在这里插入图片描述
VDMA配置c代码如下:

#include "xil_io.h"
#include "xparameters.h"
#include "helai_vdma.h"

#define VDMA_BASEADDR	XPAR_AXI_VDMA_0_BASEADDR
#define VIDEO_BASEADDR0 0x80000000
#define VIDEO_BASEADDR1 0x81000000
#define VIDEO_BASEADDR2 0x82000000

#define H_ACTIVE	1920
#define V_ACTIVE	1080
#define H_STRIDE	1920

u32 i=0;
#define SUM   H_ACTIVE*V_ACTIVE*4 //color back 1920*1080*4

void helai_vdma(){
	//set color back to black
	for(i=0;i<SUM;i++){
		Xil_Out16((VIDEO_BASEADDR0 + i), 0x00);
		Xil_Out16((VIDEO_BASEADDR1 + i), 0x00);
		Xil_Out16((VIDEO_BASEADDR2 + i), 0x00);
	}
	//VDMA_WRITE
	Xil_Out32((VDMA_BASEADDR + 0x030), 0x108B);// enable circular mode
	Xil_Out32((VDMA_BASEADDR + 0x0AC), VIDEO_BASEADDR0);	// start address
	Xil_Out32((VDMA_BASEADDR + 0x0B0), VIDEO_BASEADDR1);	// start address
	Xil_Out32((VDMA_BASEADDR + 0x0B4), VIDEO_BASEADDR2);	// start address
	Xil_Out32((VDMA_BASEADDR + 0x0A8), (H_STRIDE*3));		// h offset (H_STRIDE* 3) bytes
	Xil_Out32((VDMA_BASEADDR + 0x0A4), (H_ACTIVE*3));		// h size (H_ACTIVE * 3) bytes
	Xil_Out32((VDMA_BASEADDR + 0x0A0), V_ACTIVE);			// v size (V_ACTIVE)
	//VDMA_READ
	Xil_Out32((VDMA_BASEADDR + 0x000), 0x8B); 		// enable circular mode
	Xil_Out32((VDMA_BASEADDR + 0x05c), VIDEO_BASEADDR0); 	// start address
	Xil_Out32((VDMA_BASEADDR + 0x060), VIDEO_BASEADDR1); 	// start address
	Xil_Out32((VDMA_BASEADDR + 0x064), VIDEO_BASEADDR2); 	// start address
	Xil_Out32((VDMA_BASEADDR + 0x058), (H_STRIDE*3)); 		// h offset (H_STRIDE * 3) bytes
	Xil_Out32((VDMA_BASEADDR + 0x054), (H_ACTIVE*3)); 		// h size (H_ACTIVE * 3) bytes
	Xil_Out32((VDMA_BASEADDR + 0x050), V_ACTIVE); 			// v size (V_ACTIVE)
}

主函数c代码如下:

#include <stdio.h>
#include "xgpio.h"
#include "oak_iic.h"
#include "unistd.h"
#include "helai_vdma.h"
#include "helai_color_back.h"
#include "xvideo_scaler.h"

XVideo_scaler K7_XVideo_scaler;
XGpio_Config *XGpioCfg;
XGpio led_gpio;
#define	AXI_GPIO_DEVICE_ID	XPAR_GPIO_0_DEVICE_ID

int main(){
	XGpioCfg = XGpio_LookupConfig(AXI_GPIO_DEVICE_ID);
	XGpio_CfgInitialize(&led_gpio, XGpioCfg, XGpioCfg->BaseAddress);
	XGpio_SetDataDirection(&led_gpio, 1, 0);	//output
	XGpio_DiscreteWrite(&led_gpio, 1, 0);
	oak_i2c_init(IT6802_IIC_BASEADDR, 100000, 0x90>>1, IIC_REG_LEN8, IIC_DATA_LEN8);
	IT6802_Init(IT6802_IIC_BASEADDR);
	XVideo_scaler_Initialize(&K7_XVideo_scaler, XPAR_VIDEO_SCALER_0_DEVICE_ID);
	XHls_video_scaler_setup(1080,1920,540,960);
	helai_vdma();
	while(1){
		usleep(500000);
		XGpio_DiscreteWrite(&led_gpio, 1, 1);
		usleep(500000);
		XGpio_DiscreteWrite(&led_gpio, 1, 0);
	}
}

工程2:1080P缩小至960x540并用video mixer二分屏显示;
开发板:Xilinx Kintex7 开发板;
开发环境:vivado2019.1;
输入:HDMI-1080P;
输出:HDMI-960x540二分屏显示;
工程架构如下:
在这里插入图片描述

用电脑输出1080P视频模拟输入;
输入HDMI视频经IT6802解码为VGA格式的RGB视频流,关于IT6802的芯片解读和寄存器配置,请参考我前面的文章IT6802的芯片解读和寄存器配置
然后调用两个Xilinx官方IP将VGA格式的RGB视频流转为两路AXIS视频流;
调用两个自定义双线性插值图像缩放IP VIDEO SCALER将原视频缩小至720P;
后面就是Xilinx的图像处理套路了,什么VDMA之类的,这里就不多说了;这里是两路视频,所以IP要用两个
BD工程如下:
在这里插入图片描述
代码架构如下:
在这里插入图片描述
SDK软件文件如下:
在这里插入图片描述
VDMA配置c代码如下:

#include "xil_io.h"
#include "xparameters.h"
#include "helai_vdma.h"

#define VDMA0_BASEADDR	XPAR_AXIVDMA_0_BASEADDR
#define VDMA1_BASEADDR	XPAR_AXIVDMA_1_BASEADDR

//1frame video = 960*540*3=0x17bb00
#define VIDEO0_BASEADDR0 0x80000000
#define VIDEO0_BASEADDR1 0x81000000
#define VIDEO0_BASEADDR2 0x82000000

#define VIDEO1_BASEADDR0 0x83000000
#define VIDEO1_BASEADDR1 0x84000000
#define VIDEO1_BASEADDR2 0x85000000

#define H_ACTIVE	960
#define V_ACTIVE	540
#define H_STRIDE	960

void helai_vdma(){
	//VDMA0
	//VDMA_WRITE
	Xil_Out32((VDMA0_BASEADDR + 0x030), 0x108B);// enable circular mode
	Xil_Out32((VDMA0_BASEADDR + 0x0AC), VIDEO0_BASEADDR0);	// start address
	Xil_Out32((VDMA0_BASEADDR + 0x0B0), VIDEO0_BASEADDR1);	// start address
	Xil_Out32((VDMA0_BASEADDR + 0x0B4), VIDEO0_BASEADDR2);	// start address
	Xil_Out32((VDMA0_BASEADDR + 0x0A8), (H_STRIDE*3));		// h offset (H_STRIDE* 3) bytes
	Xil_Out32((VDMA0_BASEADDR + 0x0A4), (H_ACTIVE*3));		// h size (H_ACTIVE * 3) bytes
	Xil_Out32((VDMA0_BASEADDR + 0x0A0), V_ACTIVE);			// v size (V_ACTIVE)
	//VDMA_READ
	Xil_Out32((VDMA0_BASEADDR + 0x000), 0x8B); 		// enable circular mode
	Xil_Out32((VDMA0_BASEADDR + 0x05c), VIDEO0_BASEADDR0); 	// start address
	Xil_Out32((VDMA0_BASEADDR + 0x060), VIDEO0_BASEADDR1); 	// start address
	Xil_Out32((VDMA0_BASEADDR + 0x064), VIDEO0_BASEADDR2); 	// start address
	Xil_Out32((VDMA0_BASEADDR + 0x058), (H_STRIDE*3)); 		// h offset (H_STRIDE * 3) bytes
	Xil_Out32((VDMA0_BASEADDR + 0x054), (H_ACTIVE*3)); 		// h size (H_ACTIVE * 3) bytes
	Xil_Out32((VDMA0_BASEADDR + 0x050), V_ACTIVE); 			// v size (V_ACTIVE)

	//VDMA1
	//VDMA_WRITE
	Xil_Out32((VDMA1_BASEADDR + 0x030), 0x108B);// enable circular mode
	Xil_Out32((VDMA1_BASEADDR + 0x0AC), VIDEO1_BASEADDR0);	// start address
	Xil_Out32((VDMA1_BASEADDR + 0x0B0), VIDEO1_BASEADDR1);	// start address
	Xil_Out32((VDMA1_BASEADDR + 0x0B4), VIDEO1_BASEADDR2);	// start address
	Xil_Out32((VDMA1_BASEADDR + 0x0A8), (H_STRIDE*3));		// h offset (H_STRIDE* 3) bytes
	Xil_Out32((VDMA1_BASEADDR + 0x0A4), (H_ACTIVE*3));		// h size (H_ACTIVE * 3) bytes
	Xil_Out32((VDMA1_BASEADDR + 0x0A0), V_ACTIVE);			// v size (V_ACTIVE)
	//VDMA_READ
	Xil_Out32((VDMA1_BASEADDR + 0x000), 0x8B); 		// enable circular mode
	Xil_Out32((VDMA1_BASEADDR + 0x05c), VIDEO1_BASEADDR0); 	// start address
	Xil_Out32((VDMA1_BASEADDR + 0x060), VIDEO1_BASEADDR1); 	// start address
	Xil_Out32((VDMA1_BASEADDR + 0x064), VIDEO1_BASEADDR2); 	// start address
	Xil_Out32((VDMA1_BASEADDR + 0x058), (H_STRIDE*3)); 		// h offset (H_STRIDE * 3) bytes
	Xil_Out32((VDMA1_BASEADDR + 0x054), (H_ACTIVE*3)); 		// h size (H_ACTIVE * 3) bytes
	Xil_Out32((VDMA1_BASEADDR + 0x050), V_ACTIVE); 			// v size (V_ACTIVE)
}

主函数c代码如下:

#include <stdio.h>
#include "xgpio.h"
#include "oak_iic.h"
#include "unistd.h"
#include "helai_vdma.h"
#include "helai_color_back.h"
#include "xvideo_scaler.h"
#include "helai_mixer.h"

XVideo_scaler K7_XVideo_scaler0,K7_XVideo_scaler1;
XGpio_Config *XGpioCfg;
XGpio led_gpio;
#define	AXI_GPIO_DEVICE_ID	XPAR_GPIO_0_DEVICE_ID

int main(){
	XGpioCfg = XGpio_LookupConfig(AXI_GPIO_DEVICE_ID);
	XGpio_CfgInitialize(&led_gpio, XGpioCfg, XGpioCfg->BaseAddress);
	XGpio_SetDataDirection(&led_gpio, 1, 0);	//output
	XGpio_DiscreteWrite(&led_gpio, 1, 0);
	oak_i2c_init(IT6802_IIC_BASEADDR, 100000, 0x90>>1, IIC_REG_LEN8, IIC_DATA_LEN8);
	IT6802_Init(IT6802_IIC_BASEADDR);

	XVideo_scaler_Initialize(&K7_XVideo_scaler0, XPAR_VIDEO_SCALER_0_DEVICE_ID);
	XHls_video_scaler_setup(&K7_XVideo_scaler0,1080,1920,540,960);
	XVideo_scaler_Initialize(&K7_XVideo_scaler1, XPAR_VIDEO_SCALER_1_DEVICE_ID);
	XHls_video_scaler_setup(&K7_XVideo_scaler1,1080,1920,540,960);
	helai_vdma();
	helai_mixer();
	while(1){
		usleep(500000);
		XGpio_DiscreteWrite(&led_gpio, 1, 1);
		usleep(500000);
		XGpio_DiscreteWrite(&led_gpio, 1, 0);
	}
}

上板调试:
给出工程2的调试输出视频:

hdmi_scaler_mixer2

福利:提供源码及工程;

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Java中23种面试常考的设计模式之组合模式(Composite)---结构型模式】

【Java中23种面试常考的设计模式之组合模式(Composite)—结构型模式】 知识回顾: 之前我们讲过的设计模式在这里呦: 【面试最常见的设计模式之单例模式】 【面试最常见的设计模式之工厂模式】 【Java中23种面试常考的设计模式之备忘录模式(Memento)—行为型模式】 【Java中23种…

【每日渗透笔记】后台弱口令+未授权尝试

目录 一、特点&#xff1a; 1.1、特征&#xff1a; 1.2、分析&#xff1a; 1.3、所处情景&#xff1a; 目前&#xff1a; 问题&#xff1a; 二、渗透 一、特点&#xff1a; 1.1、特征&#xff1a; 用户登陆页面 1.2、分析&#xff1a; 毋庸置疑&#xff0c;既然有用户登…

SpringBoot系列之动态生成cron表达式执行定时程序

业务场景 最近需要实现一个功能&#xff0c;根据页面选择的星期&#xff0c;默认是凌晨执行&#xff0c;生成cron表达式&#xff0c;然后定时执行定时程序 环境准备 开发环境 JDK 1.8SpringBoot2.2.1Maven 3.2 开发工具 IntelliJ IDEAsmartGitNavicat15 在IDEA里集成阿里的…

Pycharm 如何自动调整 Python 代码符合 pep8 编码规范

前言 学生时代&#xff0c;写的一手漂亮的好字&#xff0c;能给人留下好的印象。作为 IT 人&#xff0c;写的一手漂亮的代码也会给人留下美好的印象。 代码就是自己的脸面&#xff0c;不管写质量怎样&#xff0c;首先要写的漂亮。Python 有一套 pep8 编码规范标准。 什么是 p…

电感重要参数的理解

电感作为一种储能元件&#xff0c;广泛运用在硬件电路的各个模块。较为常见的有DCDC电路&#xff0c;滤波电路以及振荡电路等。对于电感的选取&#xff0c;大多数人往往只关心感值&#xff0c;感值越大&#xff0c;储能越强&#xff0c;纹波也就越小。然而除了感值以外&#xf…

用Python剪辑视频?太简单了

人生苦短&#xff0c;快学Python&#xff01; 最近我在网上下载一个视频&#xff0c;结果下载到本地是近百个视频片段&#xff0c;为了方便观看只能将这些片段合并为一个视频整体。 不过我并没有搜到能够处理类似情况的小工具&#xff0c;只是发现剪映等软件可以实现视频合并功…

Allegro DFM Ravel Rule丝印文字到测试点pad间距检查

Allegro DFM Ravel Rule丝印文字到测试点pad间距检查 下面介绍丝印到测试点pad间距检查 设置top层丝印文字到孔属性测试点间距,默认值是1mil,可以自己修改这个值 设置bottom层丝印文字到孔属性测试点间距 设置top层丝印文字到通孔pin属性测试点间距 设置bottom层丝印文字…

VAEGAN:理解 VAE 与 GAN【图像生成】

标准VAE(Variational Autoencoder)的原理&#xff1a; 在autoencoder模型中&#xff0c;我们加入一个编码器&#xff0c;它能帮我们把图片编码成向量。然后解码器能够把这些向量恢复成图片。 标准自编码器我们现在获得了一个有点实际用处的网络了。而且我们现在能训练任意多的…

mulesoft Module 4 quiz解析

mulesoft Module 4 quiz1. What is NOT part of a Mule 4 event?2. A Database connector is configured to select rows from a Mysql database.3. What is the minimue required configuration in a flow for a Mule application to compile?4. What is the purpose of the…

Qt读写Excel文件与QXlsx的使用

最近项目比较忙&#xff0c;许久没写博客了&#xff0c;想着还是需要定期整理下学到的和用到的新东西&#xff0c;才有沉淀。刚好最近使用Qt时需要读取excel文件的数据&#xff0c;于是在github找了一个开源库QXlsx&#xff0c;Star数还比较多&#xff0c;应该靠谱&#xff0c;…

【CV】第 2 章:使用本地二进制模式的内容识别

&#x1f50e;大家好&#xff0c;我是Sonhhxg_柒&#xff0c;希望你看完之后&#xff0c;能对你有所帮助&#xff0c;不足请指正&#xff01;共同学习交流&#x1f50e; &#x1f4dd;个人主页&#xff0d;Sonhhxg_柒的博客_CSDN博客 &#x1f4c3; &#x1f381;欢迎各位→点赞…

MPLS隧道——PE与CE之间运行不同路由协议的情况分析

目录 PE和CE之间运行OSPF路由协议 Ospf的Dmian ID&#xff08;还原属性&#xff09; Ospf的Sham Link属性 OSPF的DN置位与VPN Router Tag PE和CE之间运行BGP路由协议 AS号替换功能 BGP的SoO属性 PE和CE之间可以不同部署不同的路由协议&#xff0c;部署不同的路由协议会存…

量子笔记:多比特量子门

目录 0. 前言 2. 量子多重H门 3. 量子SWAP门 4. 量子CNOT门&#xff08;CX门&#xff09;&#xff1a;受控非门 5. 量子CY和CZ门 6. 量子C*门 6.1 受控S门 6.2 受控H门 6.3 受控Z旋转门 6.4 受控X旋转门 6.4 受控Y旋转门 7. 量子托佛利门(CCNOT门) 8. 量子弗雷德…

【Linux】Linux中的gcc/g++编译器的使用

&#x1f4ac;推荐一款模拟面试、刷题神器 、从基础到大厂面试题&#xff1a;&#x1f449;点击跳转刷题网站进行注册学习 目录 一、编译的过程 1、预处理阶段 1.1预处理的工作——头文件展开、去注释、宏替换、条件编译 1.2外部定义宏&#xff08;-D选项&#xff09; 1.…

记一次网络安全应急响应流程

0x01 事件分析 网站源码被篡改&#xff0c;攻击者一定获取到了权限&#xff0c;那么接下来的思路就是推测攻击者入侵手段&#xff0c;找到业务脆弱点&#xff0c;对服务器进行全方位排查&#xff0c;找到攻击者留下来的痕迹并进行分析处理。 2.1 信息收集 与客户简单沟通后&…

【C++】动态联编、delete/free【有无析构】的使用,虚析构

文章目录动态联编的条件&#xff1a;联编的概念&#xff1a;1. 动态联编&#xff1a;2. 静态联编&#xff1a;静态联编时确认了那些属性&#xff1a;结论&#xff1a;基类指针和派生类指针访问虚函数结论&#xff1a;delete和free的使用条件&#xff1a;1. 没有析构函数时&…

由一个按键程序引发的思考(上)

说起按键程序&#xff0c;只要会单片机的肯定都很熟悉。一般开始学习单片机的时候&#xff0c;入门程序基本都是LED灯和按键。那么这个按键程序有什么特别的吗&#xff0c;还需要专门去思考吗&#xff1f;如果我刚开始学单片机的时候也会这么想&#xff0c;但是随着项目的积累&…

微信早安消息推送(大升级版-企业微信)

微信早安消息推送&#xff08;企业微信&#xff09; 在微信公众号推送的基础上的一个升级 新增图文、疫情状况等 可以修改头像 、 昵称 效果展示 更多资讯 源代码获取 → 薇信公粽号“Cloud技术栈”&#xff0c;回复“企业微信推送” ———————————————————…

【贪心算法-LeetCode3:无重复字符的最长子串(Java实现)】

无重复字符的最长子串一、题目描述1.题目内容2.样例二、解决方案1.算法流程1&#xff09;分析2&#xff09;算法流程2.Java代码1&#xff09;核心代码2&#xff09;完整测试代码个人社区&#xff1a;https://bbs.csdn.net/forums/smile 个人主页&#xff1a;https://blog.csdn.…

STM32G070RBT6基于STM32CubeMX创建定时器中断控制LED闪烁

STM32G070RBT6基于STM32CubeMX创建定时器中断控制LED闪烁&#x1f4cd;相关篇《【硬件开源电路】STM32G070RBT6开发板》&#x1f33a;配置内容演示&#xff1a; &#x1f4da;功能介绍 &#x1f4d1;通过STM32CubeMX配置定时器1和定时器3分别作为两个led的定时闹钟。这里作为…