对于初学者来说,图像处理行业,最佳仿真方式:FPGA+OPENCV,因为OPENCV适合商业化,适合自己写算法。
1)中间交互数据介质——txt文档
2)fpga写txt文档
reg clk = 0;
initial begin
forever #5 clk = ~clk;
end
reg RamWea = 0;
reg Rden = 0;
initial begin
#102; RamWea=1;
#2560;RamWea=0;
#1000; Rden = 1;
#655360;Rden = 0;
end
reg [7:0] RamAddra=0;
always @ ( posedge clk )
begin
if( RamWea ) RamAddra <= RamAddra + 1'b1;
else RamAddra <= 8'b0;
end
wire [7:0] RamDina = RamAddra;
reg [7 : 0] RdAddrb = 0;
always @ ( posedge clk )
begin
if( Rden ) RdAddrb <= RdAddrb + 1'b1;
else RdAddrb <= 8'b0;
end
wire [7 : 0] RdDoutb;
blkram_8x256 blkram_8x256 (
.clka (clk), // input wire clka
.wea (RamWea), // input wire [0 : 0] wea
.addra (RamAddra), // input wire [7 : 0] addra
.dina (RamDina), // input wire [7 : 0] dina
.clkb (clk), // input wire clkb
.addrb (RdAddrb), // input wire [7 : 0] addrb
.doutb (RdDoutb) // output wire [7 : 0] doutb
);
integer file_out;
initial
begin
file_out = $fopen("E:\\CANNY\\CANNY\\CANNY.sim\\out_file0.txt");
if (!file_out)
begin
$finish;
end
end
reg RdenD1 = 0;
reg RdenD2 = 0;
always @ (posedge clk)
begin
RdenD1 <= Rden;
RdenD2 <= RdenD1;
end
always @ (posedge clk)
begin
if( RdenD1 )
$fwrite(file_out," %d",RdDoutb) ;//写入文件,在%d前加入一个空格,效果就是,个位数前有3个空格,两位数前两个空格,三位数前1个空格
end
always @ (posedge clk)
begin
if( ~RdenD1 & RdenD2 )
$fclose(file_out);
end
3)FPGA读取txt文档
reg clk = 0;
initial begin
forever #5 clk = ~clk;
end
reg [7:0] din;
reg [7:0]data_sin[160:0];
integer i;
initial
begin
i=0;
begin
$readmemh("E:\\CANNY\\CANNY\\CANNY.sim\\out_file0.txt",data_sin,0,160); //0为起始地址,160为中止地址,readmemh为以十六进制读取,必须保证文本中是十六进制
//存在一行每个用空格隔开,跟分行存,输出结果是一样的
end
forever
begin
@(posedge clk)
begin
i <= i+1;
din <= data_sin[i];
end
end
end
4)OPENCV读txt
FPGA以十进制%d写入的数据“1”,OPENCV读取时,使用fgets读取,读取的数据个数是以字符为形式读取,包括空格也算一个字符,“1”读取后,以%d显示的话,显示的是“1”的ASC码值,以%c显示才显示为“1”.
函数原型:char *fgets(char *str, int n, FILE *stream); 其从指定的流 stream 读取一行,并把它存储在 str 所指向的字符串内。当读取 (n-1) 个字符时,或者读取到换行符时,或者到达文件末尾时,它会停止,遇到空格不停止;
// for filelisting
#include <stdio.h>
#include <io.h>
// for fileoutput
#include <string>
#include <fstream>
#include <sstream>
#include<iostream>
using namespace std;
#define IMAGE_SIZE 256*256
#define IMAGE_WIDTH 256
#define IMAGE_HEIGHT 256
#define MAX_LINE 4*IMAGE_SIZE+1 //+1是因为最后一个字符不会读取
int main()
{
char buf[MAX_LINE]; /*缓冲区*/
FILE *fp; /*文件指针*/
int len; /*行字符个数*/
if ((fp = fopen("E:\\CANNY\\CANNY\\CANNY.sim\\out_file0.txt", "r")) == NULL)
{
perror("fail to read");
exit(1);
}
if (fgets(buf, MAX_LINE, fp) != NULL)
{
len = strlen(buf); /*从指定的流 stream 读取一行,并把它存储在str所指向的字符串内。当读取(n - 1)个字符时,或者读取到换行符时,或者到达文件末尾时,它会停止*/
printf(":::::::%d\n", len);
/*for (int i = 0; i < len; i++)
{
printf("%c\n", buf[i]);
}*/
}
int image[IMAGE_SIZE];
int CombData;
for (int i = 0; i < len; i++)
{
int j = i % 4;
int k = i / 4;
int hundred, ten, unit;
if (j == 1)
{
if (buf[i] == 32) hundred = 0;//空格
else hundred = buf[i] - 48;
//printf("hundred:%d\n", hundred);
}
else if (j == 2)
{
if (buf[i] == 32) ten = 0;
else ten = buf[i] - 48;
//printf("ten:%d\n", ten);
}
else if (j == 3)
{
unit = buf[i] - 48;
//printf("unit:%d\n", unit);
CombData = hundred * 100 + ten * 10 + unit;
image[k] = CombData;
}
}
//for (int i = 0; i < 10; i++)
//{
// printf("%d\n", image[i]);
//}
#define IMAGE_WIDTH 256
#define IMAGE_HEIGHT 256
Mat ImageToShow = Mat(IMAGE_HEIGHT, IMAGE_WIDTH, CV_8UC1);
for(int i=0;i<IMAGE_HEIGHT;i++)
for (int j = 0; j < IMAGE_WIDTH; j++)
{
ImageToShow.at<uchar>(i, j) = image[i*IMAGE_WIDTH + j];
}
imshow("原始图", ImageToShow);
imwrite("E:\\CANNY\\CANNY\\CANNY.sim\\output.bmp", ImageToShow);
waitKey();
}
5)OPENCV写txt
char buf[MAX_LINE]; /*缓冲区*/
FILE *fp; /*文件指针*/
int len; /*行字符个数*/
if ((fp = fopen("E:\\CANNY\\CANNY\\CANNY.sim\\out_file0.txt", "w")) == NULL)
{
perror("fail to read");
exit(1);
}
char name[10] = { 'n1' ,'n2' , 'n3' , 'n4' , 'n5' , 'n6' , 'n7' , 'n8' , 'n9' , '\0'};
fputs(name, fp);
return 0;
写入的也是以单个字符形式。