移植EMCV到DM6467(4)——video_copy例程的xDM算法封装

2024-05-15 07:48

本文主要是介绍移植EMCV到DM6467(4)——video_copy例程的xDM算法封装,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

要移植EMCV(EmbeddedComputer Vision,OpenCV的嵌入式版本)到DM6467是一件挺繁杂的工作,要修改很多代码以及配置文件。以下将对整个移植过程进行简单介绍。注意:以下内容只是移植工作的主要部分,有很多小地方就忽略了。

整个移植的思路是:首先对EMCV源文件进行裁剪,将未用到的函数都去掉,以降低代码复杂度,同时也减小程序出错的可能性;然后,通过对Codec Engine中videnc_copy这个codec的修改来实现将EMCV封装成一个符合xDM算法标准的codec,这部分是移植的重点;接下来,通过修改Codec Engine中的video_copy应用程序来调用新的videnc_copy,实现对单幅图像的处理,图像以文件形式读入;最后,通过修改encodedecode demo以集成含有EMCV源码的videnc_copy,实现视频采集、处理和显示的功能。

 

1        编译example

按照移植思路,我们首先要将EMCV封装到videnc_copy这个codec中,videnc_copy所在路径为codec_engine_2_25_05_16/examples/ti/sdo/ce/examples/codecs/videnc_copy。在封装之前,需要保证examples能够正确编译,也即确保各编译路径是正确的。要编译examples,需按照examples目录下build_instructions.html中的步骤进行。

1.1  修改xdcpath.mak

xdcpath.mak是与编译相关的一个文件,examples中的所有Makefile都要调用它。用户需要修改xdcpath.mak来指定各组件的安装路径,例如DSPLINK、LINUXUTIL等。用户也可以修改xdcpath.mak来指定编译的目标平台,以缩短编译时间。

对于xdxpath.mak,用户需要修改的包括:DEVICES,GPPOS,PROGRAMS和各种组件的安装路径。修改过后的各变量如下所示。

 

 

DEVICES  := DM6467

 

GPPOS := LINUX_GCC

 

PROGRAMS := APP_CLIENT DSP_SERVER

 

CE_INSTALL_DIR        := /opt/dvsdk/dvsdk_3_10_00_19/codec_engine_2_25_05_16

XDC_INSTALL_DIR       := /opt/dvsdk/dvsdk_3_10_00_19/xdctools_3_16_01_27

BIOS_INSTALL_DIR      := /opt/dvsdk/dvsdk_3_10_00_19/bios_5_41_00_06

DSPLINK_INSTALL_DIR   := /opt/dvsdk/dvsdk_3_10_00_19/dsplink_linux_1_64

 

USE_CETOOLS_IF_EXISTS := 1

XDAIS_INSTALL_DIR     := /opt/dvsdk/dvsdk_3_10_00_19/xdais_6_25_02_11

FC_INSTALL_DIR      := /opt/dvsdk/dvsdk_3_10_00_19/framework_components_2_25_02_06

CMEM_INSTALL_DIR      := /opt/dvsdk/dvsdk_3_10_00_19/linuxutils_2_25_04_10

WINCEUTILS_INSTALL_DIR:= _your_WINCEUTILS_installation_directory/winceutils_1_00_03_13

BIOSUTILS_INSTALL_DIR := /opt/dvsdk/dvsdk_3_10_00_19/biosutils_1_02_02

EDMA3_LLD_INSTALL_DIR := /opt/dvsdk/dvsdk_3_10_00_19/edma3_lld_01_11_00_03

LPM_INSTALL_DIR   := _your_LPM_installation_directory/local_power_manager_1_24_02_09

 

CGTOOLS_V5T := /opt/arm-2009q1

CC_V5T := bin/arm-none-linux-gnueabi-gcc

CGTARGET := gnu.targets.arm.GCArmv5T

 

CGTOOLS_C64P := /opt/ti/C6000CGT7.3.5

CC_C64P      := bin/cl6x

 

 

1.2  编译codec,server和app

修改好xdcpath.mak之后就可以进行编译了。编译必须按照codec->server->app的顺序进行,因为只有codec编译好之后server才能将codec集成到一起,也只有server编译好之后app才能创建codecengine。编译步骤如下所示(假设当前目录为examples)。

 

 

cd ./ti/sdo/ce/examples/codecs

make clean

make

 

cd ../servers

make clean

make

 

cd ../apps

make clean

make

 

 

1.3  运行程序

编译完成之后,需要确认程序是否能够正常运行。这里对video_copy程序进行测试。要运行该应用程序,需要将以下文件复制到目标路径。

 

文件名

用途

dsplink.ko

dsplink的linux驱动,双核通信

cmem.ko

cmem的linux驱动,分配连续内存

loadmodule.sh

用于加载dsplink和cmem模块

servers/all_codecs/bin/ti_paltforms_evmDM6467/all.x64p

Codec Server

apps/video_copy/bin/ti_paltforms_evmDM6467/app.xv5t

应用程序

apps/video_copy/in.dat

应用程序的输入文件

 

将以上文件复制到开发板可以通过NFS访问的路径,然后在串口调试终端输入以下命令运行程序。

 

cd /opt/dvsdk/algorithm

./loadmodule.sh

./app_remote.xv5t

 

串口调试终端会输出以下程序运行信息。

 

    App-> Application started.

    CEapp-> Allocating contiguous buffer for 'input data' of size 1024...

    CEapp-> Contiguous buffer allocated OK (phys. addr=0x87fff000)

    CEapp-> Allocating contiguous buffer for 'encoded data' of size 1024...

    CEapp-> Contiguous buffer allocated OK (phys. addr=0x87ffe000)

    CEapp-> Allocating contiguous buffer for 'output data' of size 1024...

    CEapp-> Contiguous buffer allocated OK (phys. addr=0x87ffd000)

App-> Processing frame 0...

……

……

    App-> Finished encoding and decoding 128 frames

App-> Application finished successfully.

 

 

同时,在当前目录下会生成out.dat文件,大小应该是与in.dat文件一样。

 


 

2        修改videnc_copy

2.1  裁剪EMCV

为了减轻调试难度,我们可以先对EMCV进行裁剪,去掉没有用到的函数、宏定义和一些静态数组等代码。当前我们只使用EMCV进行很简单的功能,即在输入图像中间添加一个绿色矩形框。对于这个功能,所需要的函数不是很多,但最核心的一些基本数据结构还是用到了,包括IplImage,CvMat,CvSize,CvArray等。对于当前所需的功能,只需要使用cxarray.c,cxdatastructs.c,cxerror.c,cxdrawing.c,cxmisc.c,cxtables.c以及所有的头文件。对于需要使用的.c文件也要进行再次裁剪,将其中未用到的函数删掉,等以后需要使用某种功能时再将需要的函数添加进来。至于具体删减了哪些代码就不赘述了,请参考源文件。

在删减完无用代码之后,还需要对EMCV进行一定修改:xDAIS算法标准不允许算法分配内存,也即不允许算法使用malloc,alloc内存操作函数,而在EMCV中有不少地方使用了这些函数,所以需要修改。

修改的办法其实很简单:假如某个函数需要分配内存区域,则将所需的内存通过该函数的形参传递进去,最终的内存分配是通过framework component统一分配管理。例如对于cvCreateImage函数,其原始定义为:

 

IplImage * cvCreateImageHeader(CvSize size, int depth, int channels )

{

……

CV_CALL( img = (IplImage *)cvAlloc( sizeof( *img )));

……

}

 

修改之后的函数定义为:

 

void cvCreateImageHeader( IplImage *img, CvSize size, int depth, int channels )

{

……

// CV_CALL( img = (IplImage *)cvAlloc( sizeof( *img )));

……

}

 

EMCV中还有一些用到了cvAlloc的函数,也需要一一将其修改过来,否则最终的算法运行会出错(编译可能会通过)。另外,xDAIS算法不允许程序中使用static定义的临时变量,需要在代码中去掉static前缀。

2.2  xDM封装

当前我们需要实现封装一个包含EMCV的codec,能够对输入图像进行一定处理,鉴于之前已经在CCS中调试好了代码,并且已经符合xDAIS算法标准,现在要将其封装为xDM标准,这是非常容易的。

(1)修改头文件及函数定义

首先需要添加对EMCV头文件的引用,然后对于自定义的两个颜色空间转换函数也需要在头文件中添加声明,这只需要在videnc_copy_ti_priv.h中添加如下代码。

 

#include "cv.h"

 

extern Void YUV422_C_RGB( XDAS_UInt8* pYUV, XDAS_UInt8* pRGB, XDAS_Int32 height, XDAS_Int32 width);

extern Void RGB_C_YUV422( XDAS_UInt8* pRGB, XDAS_UInt8* pYUV, XDAS_Int32 height, XDAS_Int32 width);

 

(2)分配算法所需内存

由于xDAIS算法不允许算法自己分配内存资源,而EMCV里有内存需求,这可以通过xDAIS算法定义的的初始化函数initObj和内存分配函数alloc进行分配。

首先,需要修改VIDENCCOPY_TI_Obj的定义,添加所需的内存支持,也即在其中添加两个指针变量IplImage *img和XDAS_Uint8 *pRGB。

 

typedef struct VIDENCCOPY_TI_Obj {

    IALG_Obj    alg;            /* MUST be first field of all XDAS algs */

    IplImage    *img;

    XDAS_UInt8  *pRGB;

#ifdef USE_ACPY3

    IDMA3_Handle dmaHandle1D1D8B;  /* DMA logical channel for 1D to 1D xfers */

#endif

} VIDENCCOPY_TI_Obj;

 

然后,在VIDENCCOPY_TI_alloc中分配内存。由于img和pRGB所指向的内存区域都较大,所以都放在外部存储空间DDR2中(IALG_EXTERNAL)。同时,由于img和pRGB所指向的内存区域都是在算法激活之后才有效,所以属性都可以设置为IALG_SCRATCH。另外,需要注意alloc函数最后的返回值为分配的内存块数量,这里分配了VIDENCCOPY_TI_Obj,img和pRGB三块内存,所以返回的值是3。如果这里的参数设置错误就会内存分配错误,导致算法因没有可以使用的内存而运行失败。

 

Int VIDENCCOPY_TI_alloc(const IALG_Params *algParams,

    IALG_Fxns **pf, IALG_MemRec memTab[])

{

    memTab[0].size = sizeof(VIDENCCOPY_TI_Obj);

    memTab[0].alignment = 0;

    memTab[0].space = IALG_EXTERNAL;

    memTab[0].attrs = IALG_PERSIST;

 

    memTab[1].size = sizeof(IplImage);

    memTab[1].alignment = 0;

    memTab[1].space = IALG_EXTERNAL;

    memTab[1].attrs = IALG_PERSIST;

 

    memTab[2].size = 720 * 576 * 3* sizeof(XDAS_UInt8);

    memTab[2].alignment = 0;

    memTab[2].space = IALG_EXTERNAL;

memTab[2].attrs = IALG_SCRATCH;

  return (3);

}

 

接下来需要在算法初始化时将分配的内存赋给对应的指针变量。

 

Int VIDENCCOPY_TI_initObj(IALG_Handle handle,

    const IALG_MemRec memTab[], IALG_Handle p,

    const IALG_Params *algParams)

{

    VIDENCCOPY_TI_Obj *VIDENC_COPY = (Void *)handle;

 

    VIDENC_COPY->img  = memTab[1].base;

    VIDENC_COPY->pRGB = memTab[2].base;

 

    return (IALG_EOK);

}

 

最后,需要在free函数中修改相关内存配置参数。注意这里的返回值也是3。

 

Int VIDENCCOPY_TI_free(IALG_Handle handle, IALG_MemRec memTab[])

{

    VIDENCCOPY_TI_Obj *VIDENC_COPY = (Void *)handle;

    VIDENCCOPY_TI_alloc(NULL, NULL, memTab);

 

    memTab[0].base = handle;

    memTab[1].base = VIDENC_COPY->img;

    memTab[1].size = sizeof(IplImage);

    memTab[2].base = VIDENC_COPY->pRGB;

    memTab[2].size = 720 * 576 * 3 *sizeof(XDAS_UInt8);

    return (3);

}

 

(3)实现process函数

由于前期我们在CCS中创建xDAIS算法时就是用了process作为IALG的扩展算法,所以要移植到xDM定义的process中就很容易了,这里不详细讲解,只需要注意其中的以下代码。

 

 

VIDENCCOPY_TI_YUV422_C_RGB((XDAS_UInt8 *)inBufs->bufs[curBuf], VIDENC_COPY->pRGB, size.height, size.width);

 

VIDENCCOPY_TI_cvSetData(VIDENC_COPY->img, VIDENC_COPY->pRGB, size.width * 3);

 

VIDENCCOPY_TI_cvRectangle(VIDENC_COPY->img, point1, point2, color, CV_AA, 8, 0);

 

VIDENCCOPY_TI_RGB_C_YUV422((XDAS_UInt8 *)VIDENC_COPY->img->imageData, (XDAS_UInt8 *)outBufs->bufs[curBuf], size.height, size.width);

 

 

2.3  修改xdc配置文件

对于配置文件的修改非常简单,只需要将使用到的EMCV源文件添加进编译列表中就可以了,这是通过修改package.bld实现。

 

var SRCS = ["videnc_copy","cxarray","cxdatastructs","cxdrawing","cxtables"];

 

2.4  使用qualiTI检查是否符合xDAIS标准

由于编写的算法包是否符合算法标准是一件很难判别的事,为了解决这个问题,TI提供了qualiTI这个工具对算法进行静态检测,判断其是否符合xDAIS标准,至于是否符合xDM标准则不进行检查。但是由于xDM只是xDAIS标准的轻量级扩展,所以只要能够通过xDAIS标准检测那基本上就没问题了。

qualiTI这个工具位于DVSDK的XDAIS安装目录下,使用非常方便,只需要在终端中export XDC环境变量,然后再输入qualiTI的文件名运行脚本即可,如下图所示。

 

然后,可以看到qualiTI的界面,配置好相关选项之后点击run进行测试。

 

运行qualiTI之后,可以在videnc_copy的目录下看到生成的html网页版测试结果文件qualiti--VIDENCCOPY_TI_a64P--report.html。打开之后看到以下错误信息:

 

这是由于xDAIS算法标准要求所有由Vendor实现的非内部函数都需要在函数名前添加MODULE_VENDOR_前缀,对于我们这里前缀为VIDENCCOPY_TI_。对于EMCV中的函数,添加上相应前缀之后再用qualiTI进行测试就没有这个错误了。

 

在qualiTI测试通过之后,按照第1节叙述的步骤对codecs进行编译,根据错误进行修改,直到编译通过。

然后,对server(all_codecs)进行编译,将新的codec集成进sever中。


 

3        修改video_copy测试videnc_copy

在codec和server编译通过之后,需要编写应用程序对codec进行测试,这里选用apps中的video_copy程序进行测试。这里使用由TVP5150传递来的一帧原始YUV图像进行处理,分辨率为720 X 576,颜色空间为YCbCr 4:2:2 SemiPlanar.

3.1  修改app.c

由于我们只是修改了videnc_copy这个codec,所以对于应用程序的修改就很小了,配置部分不用修改,只需要修改app.c中的部分代码,确保传递给codec的数据格式正确。

首先,需要定义输入输出缓冲的大小。

#define IMAGESIZE   (720 * 576)

#define IFRAMESIZE  (IMAGESIZE * 2 * sizeof(Int8))  /* raw frame (input) */

#define EFRAMESIZE  (IMAGESIZE * 3 * sizeof(Int8))  /* encoded frame */

然后,去掉与未使用的viddec_copy相关的头文件引用、宏定义、缓冲区和变量等。接下来,注释掉使用DMA进行memcpy的部分代码。这是因为video_copy程序默认是使用DMA将输入缓冲区数据复制给输出,所以需要注释掉。其他还有一些小修改(例如修改encode函数的形参表)就不再一一赘述,详情请直接参考源文件。

3.2  程序运行结果

程序编译通过之后,按照第1节所述使其在开发板上运行,得到输出文件out.264,通过Matlab显示出来的结果如下所示,这证明程序运行成功。

 

这篇关于移植EMCV到DM6467(4)——video_copy例程的xDM算法封装的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/991238

相关文章

Python中的随机森林算法与实战

《Python中的随机森林算法与实战》本文详细介绍了随机森林算法,包括其原理、实现步骤、分类和回归案例,并讨论了其优点和缺点,通过面向对象编程实现了一个简单的随机森林模型,并应用于鸢尾花分类和波士顿房... 目录1、随机森林算法概述2、随机森林的原理3、实现步骤4、分类案例:使用随机森林预测鸢尾花品种4.1

不懂推荐算法也能设计推荐系统

本文以商业化应用推荐为例,告诉我们不懂推荐算法的产品,也能从产品侧出发, 设计出一款不错的推荐系统。 相信很多新手产品,看到算法二字,多是懵圈的。 什么排序算法、最短路径等都是相对传统的算法(注:传统是指科班出身的产品都会接触过)。但对于推荐算法,多数产品对着网上搜到的资源,都会无从下手。特别当某些推荐算法 和 “AI”扯上关系后,更是加大了理解的难度。 但,不了解推荐算法,就无法做推荐系

康拓展开(hash算法中会用到)

康拓展开是一个全排列到一个自然数的双射(也就是某个全排列与某个自然数一一对应) 公式: X=a[n]*(n-1)!+a[n-1]*(n-2)!+...+a[i]*(i-1)!+...+a[1]*0! 其中,a[i]为整数,并且0<=a[i]<i,1<=i<=n。(a[i]在不同应用中的含义不同); 典型应用: 计算当前排列在所有由小到大全排列中的顺序,也就是说求当前排列是第

csu 1446 Problem J Modified LCS (扩展欧几里得算法的简单应用)

这是一道扩展欧几里得算法的简单应用题,这题是在湖南多校训练赛中队友ac的一道题,在比赛之后请教了队友,然后自己把它a掉 这也是自己独自做扩展欧几里得算法的题目 题意:把题意转变下就变成了:求d1*x - d2*y = f2 - f1的解,很明显用exgcd来解 下面介绍一下exgcd的一些知识点:求ax + by = c的解 一、首先求ax + by = gcd(a,b)的解 这个

综合安防管理平台LntonAIServer视频监控汇聚抖动检测算法优势

LntonAIServer视频质量诊断功能中的抖动检测是一个专门针对视频稳定性进行分析的功能。抖动通常是指视频帧之间的不必要运动,这种运动可能是由于摄像机的移动、传输中的错误或编解码问题导致的。抖动检测对于确保视频内容的平滑性和观看体验至关重要。 优势 1. 提高图像质量 - 清晰度提升:减少抖动,提高图像的清晰度和细节表现力,使得监控画面更加真实可信。 - 细节增强:在低光条件下,抖

【数据结构】——原来排序算法搞懂这些就行,轻松拿捏

前言:快速排序的实现最重要的是找基准值,下面让我们来了解如何实现找基准值 基准值的注释:在快排的过程中,每一次我们要取一个元素作为枢纽值,以这个数字来将序列划分为两部分。 在此我们采用三数取中法,也就是取左端、中间、右端三个数,然后进行排序,将中间数作为枢纽值。 快速排序实现主框架: //快速排序 void QuickSort(int* arr, int left, int rig

poj 3974 and hdu 3068 最长回文串的O(n)解法(Manacher算法)

求一段字符串中的最长回文串。 因为数据量比较大,用原来的O(n^2)会爆。 小白上的O(n^2)解法代码:TLE啦~ #include<stdio.h>#include<string.h>const int Maxn = 1000000;char s[Maxn];int main(){char e[] = {"END"};while(scanf("%s", s) != EO

秋招最新大模型算法面试,熬夜都要肝完它

💥大家在面试大模型LLM这个板块的时候,不知道面试完会不会复盘、总结,做笔记的习惯,这份大模型算法岗面试八股笔记也帮助不少人拿到过offer ✨对于面试大模型算法工程师会有一定的帮助,都附有完整答案,熬夜也要看完,祝大家一臂之力 这份《大模型算法工程师面试题》已经上传CSDN,还有完整版的大模型 AI 学习资料,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费

dp算法练习题【8】

不同二叉搜索树 96. 不同的二叉搜索树 给你一个整数 n ,求恰由 n 个节点组成且节点值从 1 到 n 互不相同的 二叉搜索树 有多少种?返回满足题意的二叉搜索树的种数。 示例 1: 输入:n = 3输出:5 示例 2: 输入:n = 1输出:1 class Solution {public int numTrees(int n) {int[] dp = new int

Codeforces Round #240 (Div. 2) E分治算法探究1

Codeforces Round #240 (Div. 2) E  http://codeforces.com/contest/415/problem/E 2^n个数,每次操作将其分成2^q份,对于每一份内部的数进行翻转(逆序),每次操作完后输出操作后新序列的逆序对数。 图一:  划分子问题。 图二: 分而治之,=>  合并 。 图三: 回溯: