第三届FPGA创新大赛-加速视觉处理小组
参考资料: HLS 视频开发流程
图像处理,像素值/255
电脑端运行 1.92s
卷积核大小 5*5
有 6 个卷积核
卷积输入层数 1 层
卷积输出层数 6 层
第一层操作顺序:卷积-激活
池化大小 2*2
池化输入层数 6 层
池化输出层数 6 层
第二层操作顺序:平均池化
卷积核大小 5*5
卷积输入层数 6 层
卷积输出层数 12 层
第一层操作顺序:卷积-激活
池化大小 2*2
池化输入层数 6 层
池化输出层数 6 层
第四层操作顺序:平均池化
第五层操作顺序:全连接-激活
使用 Matlab 的 rgb2gray 函数进行灰度处理: rgb2gray 通过计算 R、G 和 B 分量的加权和,将 RGB 值转换为灰度值,一下是 MATLAB 文件中的说明:
0.2989 * R + 0.5870 * G + 0.1140 * B
这些权重与 rgb2ntsc 函数用于计算 Y 分量的权重相同。
在舍入到小数点后 3 位之后,rgb2gray 中用来计算灰度值的系数与 Rec.ITU-R BT.601-7 中用来计算亮度 (E'y) 的系数相同。
以下是对比效果:
原图片 灰度处理后图片-加权平均 灰度处理后图片-平均值该 IP 核的功能为
- 将颜色空间为 RGB888 流格式的图像转换成灰度图像
- 将灰度图像转化成存储矩阵方便读取
针对 RGB888 颜色空间
一、基础 对于彩色转灰度,有一个很著名的心理学公式: Gray = R0.299 + G0.587 + B0.114 二、整数算法 而实际应用时,希望避免低速的浮点运算,所以需要整数算法。 注意到系数都是 3 位精度的没有,我们可以将它们缩放 1000 倍来实现整数运算算法: Gray = (R299 + G587 + B114 + 500) / 1000 RGB 一般是 8 位精度,现在缩放 1000 倍,所以上面的运算是 32 位整型的运算。注意后面那个除法是整数除法,所以需要加上 500 来实现四舍五入。 就是由于该算法需要 32 位运算,所以该公式的另一个变种很流行: Gray = (R30 + G59 + B11 + 50) / 100 但是,虽说上一个公式是 32 位整数运算,但是根据 80x86 体系的整数乘除指令的特点,是可以用 16 位整数乘除指令来运算的。而且现在 32 位早普及了(AMD64 都出来了),所以推荐使用上一个公式。 三、整数移位算法 上面的整数算法已经很快了,但是有一点仍制约速度,就是最后的那个除法。移位比除法快多了,所以可以将系数缩放成 2 的整数幂。 习惯上使用 16 位精度,2 的 16 次幂是 65536,所以这样计算系数: 0.299 * 65536 = 19595.264 ≈ 19595 0.587 _ 65536 + (0.264) = 38469.632 + 0.264 = 38469.896 ≈ 38469 0.114 _ 65536 + (0.896) = 7471.104 + 0.896 = 7472 可能很多人看见了,使用的舍入方式不是四舍五入。四舍五入会有较大的误差,应该将以前的计算结果的误差一起计算进去,舍入方式是去尾法: 写成表达式是: Gray = (R19595 + G38469 + B7472) >> 16 2 至 20 位精度的系数: Gray = (R1 + G2 + B1) >> 2 Gray = (R2 + G5 + B1) >> 3 Gray = (R4 + G10 + B2) >> 4 Gray = (R9 + G19 + B4) >> 5 Gray = (R19 + G37 + B8) >> 6 Gray = (R38 + G75 + B15) >> 7 Gray = (R76 + G150 + B30) >> 8 Gray = (R153 + G300 + B59) >> 9 Gray = (R306 + G601 + B117) >> 10 Gray = (R612 + G1202 + B234) >> 11 Gray = (R1224 + G2405 + B467) >> 12 Gray = (R2449 + G4809 + B934) >> 13 Gray = (R4898 + G9618 + B1868) >> 14 Gray = (R9797 + G19235 + B3736) >> 15 Gray = (R19595 + G38469 + B7472) >> 16 Gray = (R39190 + G76939 + B14943) >> 17 Gray = (R78381 + G153878 + B29885) >> 18 Gray = (R156762 + G307757 + B59769) >> 19 Gray = (R313524 + G615514 + B119538) >> 20 仔细观察上面的表格,这些精度实际上是一样的:3 与 4、7 与 8、10 与 11、13 与 14、19 与 20 所以 16 位运算下最好的计算公式是使用 7 位精度,比先前那个系数缩放 100 倍的精度高,而且速度快: Gray = (R38 + G*75 + B*15) >> 7 其实最有意思的还是那个 2 位精度的,完全可以移位优化: Gray = (R + (WORD)G<<1 + B) >> 2 由于误差很大,所以做图像处理绝不用该公式(最常用的是 16 位精度)。但对于游戏编程,场景经常变化,用户一般不可能观察到颜色的细微差别,所以最常用的是 2 位精度。
先将 RGB 分割到 24 位(8 位原数据+16 拓展乘法位)的 wire 类型的变量上,然后乘法运算
//转换模块
module Image2GayArray(
iData,//放图像数据24位RGB888颜色空间
clk,//时钟信号
rst_n,//复位信号
ogray,//输出结果8位
start,//数据准备信号
Done//输出结果信号
);
enmodule
//图像地址调用模块
module counter_ctrl(
CLK,//时钟信号
RSTn,//复位信号
start,//开始信号
oAddr,//地址信号
oDone//输出结果信号
);
endmodule
//rgb2gray模块
module rgb2gray(
CLK,//时钟信号
RSTn,//复位信号
Start,//开始信号
Gray,//结果
addra,//地址信号
Done,//完成信号
aDone,//单像素点完成转换信号
iData//数据信号
);
endmodule
注意事项: 一、数据类型的表示 typedef ap_ufixed<12,8,AP_RND,AP_SAT> IMAGE_DATA_TYPE; 注意 W ,I 的范围选择
三种模式的 RAM:单口 RAM、伪双口 RAM(简单单口 RAM)和真双口 RAM,以及单双口 ROM
一、使用 IP 核,确定数据位宽和深度:(超出地址范围将返回无效数据,在对超出地址范围的数据进行操作的时候,不能够 set 或者 reset)
二、设置操作模式:(写优先,读优先,不改变)
这里的写优先的意思就是你写入的数据,会出现在输出端口,不管你给的地址是什么。这种好处就是保证了你读出的数据是最新的。
读优先指的就是:不管你写入的数据,是先把你要读的数据读出。
不改变模式就是正常的模式,该读的时候读,改写的时候写:(一般没有特殊要求就是选这个)
卷积核分类:平均值滤波、高斯平滑、图像锐化、梯度 Prewitt、Soble 边缘检测、梯度 Laplacian
卷积神经网路拟采用图像锐化的卷积核,卷积核如下(采用了后一种):
#C++ Opencv代码:
Mat kern = (Mat_<char>(3, 3) << 0, -1, 0,
-1, 5, -1,
0, -1, 0);//采用图像锐化的方式卷积图片
此时采用的是 Opencv 的 filter2D 函数进行卷积
卷积效果图:
卷积处理后图片-图像锐化hls::Sobel<1,0,3>(img_0, img_1);
(xorder=1, yorder=0, aperture_size=3)
模块定义代码说明
首先是卷积核的构建参考
**/