verilog图像算法实现与仿真(流程和实现)
Posted 嵌入式-老费
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了verilog图像算法实现与仿真(流程和实现)相关的知识,希望对你有一定的参考价值。
【声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】
前面我们谈到了fpga,谈到了用python+cv2实现图像算法,直到现在才算是慢慢进入了正题。毕竟用verilog实现图像算法,才是我们真正想要做的事情。而对图像的加速和实时处理,也只有verilog+fpga才能帮助我们完成。
目前网上能找到的verilog图像算法仿真的内容不多,要么就是需要安装matlab、modelsim这些商用软件,要么就是没有细节实现,不能完全复制作者的思路和操作过程。鉴于此,作者提出了全部利用开源软件来实现verilog图像算法仿真的思路。所以,直接利用开源软件iverilog+python+opencv来实现图像算法仿真,本文可能是目前全网唯一的一篇文章。希望这篇blog能给大家带来一些思索和帮助。
要做好verilog图像算法的处理和仿真,一般需要四个步骤。第一步,把图像变成数据文件;第二步,编写verilog算法代码;第三步,编写testbench文件,利用刚才的图像数据文件,并且生成新的图像数据文件;第四步,利用最新的图像数据文件,保存为图片,查看效果。
1、图像反转
为了说明如果采用这一流程是实现图像算法的仿真,我们不妨挑选一个简单的算法来做个演示。图像反转就是不错的一个例子。所谓图像反转,就是之前白色的地方变成黑的地方,黑的地方变成了白色的地方。大家如果对胶卷还有印象的话,胶卷本身就是图像反转一个很好的例子。因为在胶卷上面,人的面部是黑的,而头发却是白的。此外,这个流程如果需要写成算法的,也很简单,
def reverse_image(picture):
for i in range(picture.shape[0]):
for j in range(picture.shape[1]):
picture[i,j] = 255 - picture[i,j]
return picture
2、生成数据
之前网上很多的资料生成数据都是用matlab来实现的。殊不知,其实用python来做这一件事情也很简单。本身cv2库用起来也方便,还没有版权的烦恼。
import cv2
import numpy as np
'''
main entry
'''
def main():
picture = cv2.imread('./lena.bmp')
print(picture.shape[0])
print(picture.shape[1])
print(picture.shape[2])
color_img = np.copy(picture)
picture = cv2.cvtColor(picture, cv2.COLOR_BGR2GRAY)
f = open("data.txt", 'w')
for i in range(picture.shape[0]):
for j in range(picture.shape[1]):
f.write(hex(picture[i,j]) + "\\n")
f.close()
cv2.imshow('lena', picture)
cv2.waitKey(0)
cv2.destroyAllWindows()
if __name__ == '__main__':
main()
这段python+cv2的代码不复杂。首先把图片读取到picture变量,接着用cvtColor实现灰化。下面的几行语句就是我们需要关心的了,那就是生成data.txt。注意,data.txt当中是每一个像素一行数据,格式是16进制。等到所有像素的数据都输出来之后,主要的功能也就讲完了。
3、编写verilog代码
编写图像反转的verilog代码不复杂,主要就是对数据进行减操作就可以了,
module reverse_image(clk, rst, input_data, output_data);
input clk;
input rst;
input[7:0] input_data;
output[7:0] output_data;
wire clk;
wire rst;
wire[7:0] input_data;
wire[7:0] output_data;
assign output_data = 255 - input_data ;
endmodule
4、准备testbench文件
testbench是verilog测试的重要环节。它的主要工作有这么几块,第一,将之前的data.txt文件插入到image中;第二,调用reverse_image这个模块;第三,生成新的文件,即new_data.txt,同时还需要保证在testbench结束之前,所有的像素点都处理完毕。
`timescale 1ns/1ps
module tb;
reg clock;
reg rst;
reg [7:0] image [(512*512-1):0];
reg[18:0] cnt;
integer file_id;
wire[7:0] input_data;
wire[7:0] output_data;
initial begin
clock = 1'b0;
forever #10 clock = ~clock;
end
initial begin
cnt = 19'b0;
$readmemh("./data.txt", image);
file_id = $fopen("./new_data.txt", "w");
end
initial begin
rst = 1'b1;
#195 rst = 1'b0;
#20000000 $stop;
$fclose(file_id);
end
assign input_data = image[cnt[17:0]];
always @(posedge clock or posedge rst)
if (rst) begin
cnt <= 19'b0;
end
else if(cnt[18] == 1'b0)
begin
$fwrite(file_id, "0x%x\\n", output_data);
cnt <= cnt + 1'b1;
end
initial
begin
$dumpfile("hello.vcd");
$dumpvars(0, tb);
end
reverse_image reverse_image0(
.clk(clock),
.rst(rst),
.input_data(input_data),
.output_data(output_data)
);
endmodule
代码中有几个内容需要注意下。比如读取图像数据的指令是readmemh,写入图像数据的指令是fwrite,为了确保数据处理完,等待2000万个clock之后,仿真才结束。
因为没有使用modelsim,这部分可以使用开源软件iverilog+vvp代替,使用方法也非常简单,
C:\\iverilog\\bin\\iverilog.exe -o tb *.v
C:\\iverilog\\bin\\vvp -n tb -lxt2
执行完这两步,如果没有什么问题的话,就可以看到new_data.txt,这为我们后续的进一步处理打下了基础。
5、恢复bmp文件
前面我们获得了像素文件,下面就可以利用它转变为bmp文件,这一步也同样是使用python+cv2来实现的,
import cv2
import numpy as np
'''
main entry
'''
def main():
picture = cv2.imread('./lena.bmp')
picture = cv2.cvtColor(picture, cv2.COLOR_BGR2GRAY)
for i in range(512):
for j in range(512):
picture[i,j] = 255
f = open("./new_data.txt", 'r')
for i in range(512*512):
line = f.readline()
picture[int(i/512), int(i%512)] = int(line, 16)
f.close()
cv2.imwrite('./new_lena.bmp', picture)
cv2.waitKey(0)
cv2.destroyAllWindows()
if __name__ == '__main__':
main()
读取new_data.txt之后,经过python脚本转换,没有问题的话,就可以生成new_lena.bmp文件。打开后,可以检测一下效果,
图片效果虽然有点吓人,但是至少说明我们的操作是成功,这个方法是可行的。
6、总结
目前网上对verilog图像仿真讲的不多,细节部分就更少,希望今天讲的iverilog+python+opencv的方法能够为大家带来新的思考、新的启迪。如果能够切实将这个方法用到平时的开发中,那就最好不过了。
以上是关于verilog图像算法实现与仿真(流程和实现)的主要内容,如果未能解决你的问题,请参考以下文章
FPGA纯verilog代码实现图像缩放,两种插值算法任意尺寸缩放,提供3套工程源码