HLS第三十八课(xfopencv,H文件和HPP文件的使用)

常用的几个xfopencv的H文件和HPP文件的分析与使用。
常用的可综合的通用H文件。
xf_common.h。
common/xf_infra.h

common/xf_structs.h
common/xf_video_core.h
common/xf_video_mem.h

常用的只用于仿真的文件。
common/xf_axi.h
common/xf_sw_utils.h

常用的特定图像处理算法的HPP文件
imgproc/xf_demosaicing.hpp
imgproc/xf_channel_combine.hpp
imgproc/xf_channel_extract.hpp
imgproc/xf_crop.hpp
imgproc/xf_duplicateimage.hpp
imgproc/xf_paintmask.hpp
imgproc/xf_reduce.hpp
imgproc/xf_resize.hpp
imgproc/xf_histogram.hpp
imgproc/xf_hist_equalize.hpp

++++++++++++++++++++++++++++++++++++++
common/xf_infra.h

#include "hls_stream.h"
#include "xf_types.h"
#include "xf_axi_sdata.h"
#include "common/xf_axi_io.h"

它里面包含了如上的多个头文件,所以,由了xf_infra,就不用再包含这些文件了。
hls_stream是用来做axivideo的。
xf_types包含了常用的各种type。
xf_axi_sdata包含了ap_axiu模板类。
common/xf_axi_io包含了各种位操作需要的模板函数。

template<int W,int T,int ROWS, int COLS,int NPC>
int AXIvideo2xfMat(hls::stream< ap_axiu<W,1,1,1> >& AXI_video_strm, xf::Mat<T,ROWS, COLS, NPC>& img)

template<int W, int T, int ROWS, int COLS,int NPC>
int xfMat2AXIvideo(xf::Mat<T,ROWS, COLS,NPC>& img,hls::stream<ap_axiu<W,1,1,1> >& AXI_video_strm)

实现axivideo和xfmat之间的转换。

++++++++++++++++++++++++++++++++++++++++++
common/xf_infra.h----xf_types.h

#include "ap_int.h"
#include "xf_params.h"

包含了ap_int,所以可以使用任意精度整数。
包含了xf_params,所以可以使用枚举常量,类似XF_8UC3,XF_8UP,XF_NPPC1等。

在HLSC++中,扩展了模板结构体的作用,除了可以定义成员变量,还可以定义成员类型。
结构体此时相当于是一个作用域的标识符。
结构体模板中,只能存在成员类型和静态成员常量。

结构体模板没有传入模板形参,而是指定了枚举常量,这是最严格的匹配,只有套用模板时,指定的枚举常量完全匹配,才能套用这个模板。

template<> 
struct DataType <XF_8UC3,  XF_NPPC1>  { 
	typedef ap_uint<24>  name; 
	typedef ap_uint<24> uname; 
	typedef ap_uint<8>  cname;  
	typedef unsigned char      sname; 
	typedef unsigned int           wname; 
	
	static const int bitdepth = 8;  
	static const int pixelwidth = 24; 
	static const int pixeldepth = XF_24UP; 
	static const int wordwidth = XF_24UW;  
	static const int channel = 3; 
};

如果要使用结构体的静态成员常量,则使用域限定操作符。
如果要使用结构体的成员类型,则使用域限定操作符。

#define XF_TNAME(flags,npc)\
    typename DataType<flags,npc>::name

定义了一个宏拟类型声明语句,实现类型声明的转换。

#define XF_CHANNELS(flags,npc)\
     DataType<flags,npc>::channel

定义了一个宏拟函数,获取静态成员常量的值。

template<> 
struct PixelType<XF_8UP>   { 
	typedef ap_uint<8>  name; 
	typedef ap_uint<8>   uname; 
	typedef unsigned char name2; 

	static const int bitdepth =  8; };

如果要使用结构体的静态成员常量,则使用域限定操作符。
如果要使用结构体的成员类型,则使用域限定操作符。

#define XF_PTNAME(flags)\
    typename PixelType<flags>::name

定义了一个宏拟类型声明语句,实现类型声明的转换。

+++++++++++++++++++++++++++++++++++++
common/xf_infra.h----xf_axi_sdata.h

template<int D,int U,int TI,int TD>
  struct ap_axiu{
    ap_uint<D>       data;
    ap_uint<(D+7)/8> keep;
    ap_uint<(D+7)/8> strb;
    ap_uint<U>       user;
    ap_uint<1>       last;
    ap_uint<TI>      id;
    ap_uint<TD>      dest;
  };

定义了AXIS总线的一次bite,用一个结构体来描述总线的一次bite。

++++++++++++++++++++++++++++++++++++++++++
common/xf_infra.h----common/xf_axi_io.h

由于HLSC++扩展了()操作符,
所以,在HLSC++中,可以用()操作符,做截位操作,类似于verilog的截位。
截位操作符,实现的是一个for循环,在循环中逐位赋值。

template<int W, typename T>
void AXIGetBitFields(ap_uint<W> pix, int start, int w, T& val) {
#pragma HLS inline
    assert(start >= 0 && start+w <= W);
    val = (T)pix(start+w-1, start);
}

从一个ap_uint整数中,截取一个位向量,这个位向量,也是需要的宽度的ap_uint。

template<int W, typename T>
void AXISetBitFields(ap_uint<W>& pix, int start, int w, T val) {
#pragma HLS inline
    assert(start >= 0 && start+w <= W);
    pix(start+w-1, start) = val;
}

从一个ap_uint整数中,截取一个位向量并写入,这个位向量,也是需要的宽度的ap_uint。

template<int W, typename T>
void AXIGetBitFields(ap_axiu<W,1,1,1> axi, int start, int w, T& val) {
#pragma HLS inline
    AXIGetBitFields(axi.data, start, w, val);
}

从一个AXIS总线的一次bite中,截取一个位向量,这个位向量,也是需要的宽度的ap_uint。

template<int W, typename T>
void AXISetBitFields(ap_axiu<W,1,1,1>& axi, int start, int w, T val) {
#pragma HLS inline
    AXISetBitFields(axi.data, start, w, val);
}

从一个AXIS总线的一次bite中,截取一个位向量并写入,这个位向量,也是需要的宽度的ap_uint。

++++++++++++++++++++++++++++++++++++++++++++++++
xf_common.h----common/xf_structs.h

定义了常用的结构体。

template<typename T>
class Point_ {
  public:
    Point_();
    Point_(T _x, T _y);
    Point_(const Point_& pt);
    ~Point_();

    T x, y;
};

typedef Point_<int> Point;

定义了Point类。它是模板类point_的具象类型。
如果我们需要定义任意精度,我们需要自己具象化point_,并typedef成我们需要的类型。

template<typename T>
class Size_ {
  public:
    Size_();
    Size_(T _width, T _height);
    Size_(const Size_<T>& sz);
    Size_(const Point_<T>& pt);
    T area();
    ~Size_();

    T width, height;
};
typedef Size_<int> Size;

Size类似于Point的具象化。

template<typename T>
class Rect_ {
  public:
    Rect_();
    Rect_(T _x, T _y, T _width, T _height);
    Rect_(const Rect_& rect);
    Rect_(const Point_<T>& pt, const Size_<T>& sz);
    T area();
    Size_<T> size();
    Point_<T> tl(); // top-left point(inside);
    Point_<T> tr(); // top-right point(outside);
    Point_<T> bl(); // bottom-left point(outside);
    Point_<T> br(); // bottom-right point(outside);
    bool bContains(const Point_<T>& pt);
    ~Rect_();

    T x, y, width, height;
};
typedef Rect_<int> Rect;

Rect类似于Point的具象化。

template<int N, typename T>
class Scalar {
public:
    ...

	void operator =(T value);
	Scalar<N, T> operator +(T value);
    Scalar<N, T> operator +(Scalar<N, T> s);
    Scalar<N, T> operator -(T value);
    Scalar<N, T> operator -(Scalar<N, T> s);
    Scalar<N, T> operator *(T value);
    Scalar<N, T> operator *(Scalar<N, T> s);
    Scalar<N, T> operator /(T value);
    Scalar<N, T> operator /(Scalar<N, T> s);
    
    T val[N];
};

定义了模板类Scalar,它的成员是一个一维数组,支持重载的加减乘除运算。

template<int T, int ROWS, int COLS, int NPC>
class Mat {

  public:
    int rows, cols, size;                   // actual image size
    DATATYPE *data ;

    Mat(int _rows, int _cols);
    Mat(const Mat&);                        // copy constructor
    
    Mat& operator= (const Mat&);            // Assignment operator

    XF_TNAME(T,NPC) read(int index);
    void write(int index, XF_TNAME(T,NPC) val);

    const int channels() const;
};

+++++++++++++++++++++++++++++++++++++++++++++
common/xf_video_core.h

typedef struct{
  unsigned char R;
  unsigned char G;
  unsigned char B;
}rgb_8;

typedef struct{
  unsigned char Y;
  char U;
  char V;
}yuv444_8;

typedef struct{
  unsigned char Y;
  char UV;
}yuv422_8;

typedef struct{
  unsigned char CMY;
}bayer_8;

定义了各种视频格式下的一个像素的结构体。

template<typename T>
yuv422_8 Scalar_to_yuv422_8(Scalar<2, T> scl) {
#pragma HLS inline
    yuv422_8 pix;
    pix.Y = (unsigned char)scl.val[0];
    pix.UV = (char)scl.val[1];
    return pix;
}

template<typename T>
Scalar<2, T> yuv422_8_to_Scalar(yuv422_8 pix) {
#pragma HLS inline
    Scalar<2, T> scl;
    scl.val[0] = (T)pix.Y;
    scl.val[1] = (T)pix.UV;
    return scl;
}

定义了YUV422和scalar之间的转换。

template<typename T>
rgb_8 Scalar_to_rgb_8(Scalar<3, T> scl) {
#pragma HLS inline
    rgb_8 pix;
    pix.R = (unsigned char)scl.val[0];
    pix.G = (unsigned char)scl.val[1];
    pix.B = (unsigned char)scl.val[2];
    return pix;
}
template<typename T>
Scalar<3, T> rgb_8_to_Scalar(rgb_8 pix) {
#pragma HLS inline
    Scalar<3, T> scl;
    scl.val[0] = (T)pix.R;
    scl.val[1] = (T)pix.G;
    scl.val[2] = (T)pix.B;
    return scl;
}

定义了RGB444和scalar之间的转换。

注意,这里使用了内联约束,该函数会被HLS在综合时内联处理。

++++++++++++++++++++++++++++++++++++++++++++
common/xf_video_mem.h

template<int ROWS, int COLS, typename T>
class Window {
public:
    T& getval(int row, int col);
    T& operator ()(int row, int col);

    void shift_right();
    void insert_right(T value[ROWS]);
   

    T val[ROWS][COLS];
};

定义了window模板类。

template<int ROWS, int COLS, typename T, XF_ramtype_e MEM_TYPE=RAM_S2P_BRAM, int RESHAPE_FACTOR=1>
class LineBuffer {
public:

    T& getval(int row, int col);
    T& operator ()(int row, int col);

    void shift_down(int col);
    void insert_bottom(T value, int col);
   
    T val[ROWS][COLS];
};

定义了linebuffer的模板类。

+++++++++++++++++++++++++++++++++++++++++++
common/xf_axi.h
这些函数用于CSIM。

template<int W,int NPC>
void IplImage2AXIvideoxf(IplImage* img, hls::stream<ap_axiu<W,1,1,1> >& AXI_video_strm) 

template<int W,int NPC>
void AXIvideo2IplImagexf(hls::stream<ap_axiu<W,1,1,1> >& AXI_video_strm, IplImage* img) 

实现axivideo和IplImage之间的转换。

template<int W,int NPC>
void cvMat2AXIvideoxf(cv::Mat& cv_mat, hls::stream<ap_axiu<W,1,1,1> >& AXI_video_strm);

template<int W>
void AXIvideo2cvMatxf(hls::stream<ap_axiu<W,1,1,1> >& AXI_video_strm, cv::Mat& cv_mat);

实现axivideo和cvmat之间的转换。

template<int NPC,int W>
void AXIvideo2cvMatxf(hls::stream<ap_axiu<W,1,1,1> >& AXI_video_strm, cv::Mat& cv_mat) {
	IplImage img = cv_mat;
    AXIvideo2IplImagexf<W,NPC>(AXI_video_strm, &img);
}

template<int NPC,int W>
void cvMat2AXIvideoxf(cv::Mat& cv_mat, hls::stream<ap_axiu<W,1,1,1> >& AXI_video_strm) {
	 IplImage img = cv_mat;
    IplImage2AXIvideoxf<W,NPC>(&img, AXI_video_strm);
}

实际上我们可以看出,本质上,还是axivideo和IplImage之间完成的转换,
然后,简单的通过对象赋值,使得cvmat和IplImage,关联同一个实例图像。

++++++++++++++++++++++++++++++++++++++++++++++
common/xf_sw_utils.h
这些函数用于CSIM。

template <int _PTYPE, int _ROWS, int _COLS, int _NPC>
	xf::Mat<_PTYPE, _ROWS, _COLS, _NPC> imread(char *img,  int type)

用于从FILE中读取图像,存为xfmat对象。

type为0,表示是8bit gray模式,只读取原图的channel1的数据。
type为1,表示是color模式,不管原图是否是彩色,将原图颜色读取后,转存为彩色图像。

type为4,表示是any color模式。不管原图是什么颜色,转换成4通道彩色图像。
type为2,表示是any depth模式,原图的深度可以不是8,可以是10或者12。
type为-1,表示8bit normal模式,原图是什么颜色,就保持什么颜色。

实质是调用了cvimread函数。

template <int _PTYPE, int _ROWS, int _COLS, int _NPC>
	void imwrite(const char *str, xf::Mat<_PTYPE, _ROWS, _COLS, _NPC> &output)

用于将一个xfmat对象存为FILE。实质上是调用了cvimwrite函数。

template <int _PTYPE, int _ROWS, int _COLS, int _NPC>
	void absDiff(cv::Mat &cv_img, xf::Mat<_PTYPE, _ROWS, _COLS, _NPC>& xf_img, cv::Mat &diff_img )
	
void analyzeDiff(cv::Mat &diff_img, int err_thresh, float &err_per)

用于求出xfmat和cvmat之间的差异,并分析误差程度。

++++++++++++++++++++++++++++++++++++++++++++++++++

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值