基于FPGA的数字图像处理【3.0】

5.2.4 MFC程序设计

        主机端的MFC程序需要完成图像的读取与数据生成,FPGA处理后数据的读取与处理后图像的显示,以及软件算法处理结果与FPGA处理结果的校对等。
        以下的方法展示了如何通过图像写txt文件供FPGA读取

void CImageToTextDlg::WriteTxt_FromBmp(LPCTSTR
bmp_file_path,LPCTSTR txt_file_path,DWORD dwWidth,DWORD
dwHeight,WORD flag)
{
CZXDib *p_dib =new CZXDib;BYTE *p_Bitmap = NULL;
if(flag==8)p_Bitmap = new BYTE[dwWidth*dwHeight];
else if (flag == 24)p_Bitmap = new
BYTE[dwWidth*dwHeight*3];
CString file_path = bmp_file_path;
p_dib-
>LoadVectorFromBMPFile(file_path,p_Bitmap,dwHeight,
dwWidth,flag);
file_path = txt_file_path;
FILE *p_file;
p_file = fopen(txt_file_path,"a+");
if (!p_file)
{
AfxMessageBox("文件不存在或被占用!");
return;
}
fclose(p_file);
p_file = fopen(file_path,"r+");
int cnt = 0;
if (flag == 8)
{
for (int i = 0; i<dwHeight*dwWidth; i++)
{
fseek(p_file,cnt,0);
fprintf(p_file,"%02x\n ",p_Bitmap[i]);
cnt = cnt + 4;
}/*写命令行 一共一行*/
for (int j = 0; j<dwWidth; j++)
{
fseek(p_file,cnt,0);
fprintf(p_file,"%02x\n",j);
cnt = cnt + 4;
}
}
if (flag == 24)
{
for (int i = 0; i<dwHeight*dwWidth*3; i=i+3)
{
fseek(p_file,cnt,0);
fprintf(p_file,"%02x\n%02x\n%02x\n",p_Bitmap[i],p
_Bitmap
[i+1],p_Bitmap[i+2]);
cnt = cnt + 12;
}
/*写命令行 一共一行*/
for (int j = 0; j<dwWidth; j++)
{
fseek(p_file,cnt,0);
fprintf(p_file,"%02x\n%02x\n%02x\n",j % 16,j %
16,j %
16,j % 16);
cnt = cnt + 12;
}}
fclose(p_file);
delete []p_Bitmap;
delete p_dib;
}

读取FPGA处理后的数据文件并将其显示为上述过程的逆过程,实例代码如下:
 

void CImageToTextDlg::WriteBmp_FromTxt(LPCTSTR
bmp_file_path,LPCTSTR txt_file_path,DWORD dwWidth,DWORD
dwHeight,WORD flag)
{
DWORD buf=0;
if (flag == 8)
{
WriteBmp_FromTxt(bmp_file_path,txt_file_path,dwWidt
h,dwHeight);
return;
}
BYTE *p_Bitmap = new BYTE[dwWidth*dwHeight*3];
memset(p_Bitmap,0,dwWidth*dwHeight*3);
DWORD dWidth = dwWidth;
DWORD dHeight = dwHeight;
CString file_name = "";
FILE *p_file = NULL;
p_file = fopen(txt_file_path,"a+");
if (!p_file)
{AfxMessageBox("文件不存在或被占用!");
return;
}
fclose(p_file);
p_file = fopen(txt_file_path,"r");
for (int k = 0; k<dwWidth*dwHeight*3; k=k+3)
{
fscanf(p_file,"%06x\n",&buf);
p_Bitmap[k]= buf & 0xff;
p_Bitmap[k+1]= (buf>>8) & 0xff;
p_Bitmap[k+2]= (buf>>16) & 0xff;
}
fclose(p_file);
file_name = bmp_file_path;
m_dib.WriteBMPFileFromVector(file_name,p_Bitmap,dHeight
,dWidth,flag);
ShowImage(p_Bitmap,dwHeight,dwWidth,24);
delete[]p_Bitmap;
p_Bitmap = NULL;
}

可以把上一节的处理结果通过本MFC平台进行测试,将FPGA处理后的结果写入文件,再通过MFC读出解析文件并显示,结果如图5-31所示。

        图中左侧为原始图像,右侧为经过FPGA捕获后的输出图像,当然也可以是经过FPGA做算法处理后的图像(由于打印纸质的关系,读者可能看不到RGB彩色信息)。接下来的章节中都会以这个仿真测试平台进行测试。

5.2.5 通用testbench

        仿真平台的最终目的也包括建立一个通用的testbench,本书中给出的通用testbench结构如图5-32所示。

        testbench从文件读取图像数据,并接入img_src模拟视频源模块生成视频流,之后经过video_cap模块采集视频并转换成本地逻辑。本地逻辑产生的数据流经过算法处理后输出。
以下为一个算法处理的示例。

以下为通用testbench的实例代码:
 

module img_process_tb;
/*image para*/
parameter iw = 640; //image width
parameter ih = 512; //image height
parameter trig_value= 250;
/*video parameter*/
parameter h_total = 2000;
parameter v_total = 600;
parameter sync_b = 5;
parameter sync_e = 55;
parameter vld_b = 65;
parameter clk_freq = 72;
/*data width*/
parameter dvd_dw = 8 ; //image source data width
parameter dvd_chn = 3 ;
//channel of the dvd data : when 3 it's rgb
parameter local_dw = dvd_dw*dvd_chn ;
//local algorithm process data width
parameter cmd_dw = dvd_dw*dvd_chn ;
//local algorithm process data width
parameter hist_dw = 32 ; //hist statistics data width/*test module enable*/
parameter cap_en = 1;
parameter morph_1d_en = 0;
parameter morph_2d_en = 0;
parameter tophat_en = 0;
parameter hist_en = 0;
parameter segment_en = 0;
parameter mean_1d_en = 0;
parameter mean_2d_en = 0;
parameter sum_1d_en = 0;
parameter sum_2d_en = 0;
parameter sort_1d_en = 0;
parameter sort_2d_en = 0;
parameter sobel_en = 0;
parameter sobel_ex_en = 0;
parameter gauss_en = 0;
parameter cordic_en = 0;
parameter win_buf_en = 0;
parameter add_tree_en = 0;
parameter gauss_sobel_en= 0;
parameter canny_en = 0;
parameter histogram_en = 0;
parameter hist_equalized_en = 0;
parameter display_transform_en = 0;
/*ksz definition:must be odd number*/
parameter ksz_morph = 3 ;
parameter ksz_tophat = 7 ; //can be 3,5,7,9,11...parameter ksz_segment = 15; //must be 15
parameter ksz_mean = 3 ; //can be 3,5,7,9,11,13,15
parameter ksz_sobel = 3 ; //must be 3
parameter ksz_sort = 3 ; //can be 3 or 5
parameter ksz_gauss = 5 ; //must be 5
/*signal group*/
reg clk=1'b0;
reg reset_l;
reg [3:0] src_sel;
wire [dvd_dw-1:0]test_data;
wire test_dvalid;
wire test_vsync;
/*input dv group*/
wire dv_clk;
wire dvsyn;
wire dhsyn;
wire [dvd_dw-1:0]dvd;
/*dvd sorce data generated for simulation */
image_src #
(iw*dvd_chn,ih+1,dvd_dw,h_total,v_total,sync_b,sync_e,
vld_b)
img_src_ins(
.clk(clk),
.reset_l(reset_l),
.src_sel(src_sel),
.test_data(dvd),
.test_dvalid(dhsyn),.test_vsync(dvsyn),
.clk_out(dv_clk)
);
/*data captured*/
wire cap_dvalid;
wire [local_dw - 1:0]cap_data;
wire cap_vsync;
/*command line */
wire cmd_rdy;
wire [cmd_dw-1:0]cmd_rdat;
reg cmd_rdreq;
/*local clk :also clk of all local modules*/
reg cap_clk;
/*img enable*/
wire img_en;
/* video capture:capture image src and transfer it
into local timing*/
video_cap //#(trig_value,iw,ih)/*default trig value
250*/
video_new(
.reset_l(reset_l),
.DVD(dvd),
.DVSYN(dvsyn),
.DHSYN(dhsyn),
.DVCLK(dv_clk),
.cap_dat(cap_data),
.cap_dvalid(cap_dvalid),.cap_vsync(cap_vsync),
.cap_clk (cap_clk),
.img_en(img_en),
.cmd_rdy(cmd_rdy),
.cmd_rdat(cmd_rdat),
.cmd_rdreq(cmd_rdreq)
);
defparam video_new.DW_DVD = dvd_dw;
defparam video_new.DW_LOCAL = local_dw;
defparam video_new.DW_CMD = cmd_dw;
defparam video_new.DVD_CHN = dvd_chn;
defparam video_new.TRIG_VALUE = trig_value;
defparam video_new.IW = iw;
defparam video_new.IH = ih;
initial
begin: init
reset_l <= 1'b0;
src_sel <= 4'b0000;
#(50000); //reset the sysytem
reset_l <= 1'b1; //release the system
for(i=0;i<16;i=i+1)
begin
@(posedge test_vsync); //wait for the next frame
src_sel <= src_sel + 4'b0001;
end
$display("END OF SIMULATION");
end//dvclk generate
always @(reset_l or clk)
begin
if ((~(reset_l)) == 1'b1)
clk <= 1'b0;
else
begin
if(clk_freq == 48) //48MHz
clk <= #10417 (~(clk));
else if(clk_freq == 51.84) //51.84MHz
clk <= #9645 (~(clk));
else if(clk_freq == 72) //72MHz
clk <= #6944 (~(clk));
end
end
//cap_clk generate : 25MHz
always @(reset_l or cap_clk)
begin
if ((~(reset_l)) == 1'b1)
cap_clk <= 1'b0;
else
cap_clk <= #20000 (~(cap_clk));
end

在此通用模块的基础上,加上不同的处理算法模块即可实现不同的算法处理结果。以下以一个高斯滤波模块为例来说明:
 

/*gauss operation module*/
generateif(gauss_en != 0)begin :gauss_operation
/*gauss data*/
wire gauss_dvalid;
wire [local_dw - 1:0]gauss_data;
wire gauss_vsync;
/*gauss data input*/
wire gauss_dvalid_in;
wire [local_dw - 1:0]gauss_data_in;
wire gauss_vsync_in;
integer fp_gauss,cnt_gauss=0;
Gauss_2D#(local_dw,ksz_gauss,ih,iw)
gauss_2D_ins (
.rst_n (reset_l),
.clk (cap_clk),
.din (gauss_data_in),
.din_valid (gauss_dvalid_in),
.dout_valid (gauss_dvalid),
.vsync(gauss_vsync_in),
.vsync_out(gauss_vsync),
.dout (gauss_data)
);
assign gauss_data_in = cap_data;
assign gauss_vsync_in = cap_vsync;
assign gauss_dvalid_in = cap_dvalid;
always @(posedge cap_clk or posedge gauss_vsync )
if (((~(gauss_vsync))) == 1'b0)
cnt_gauss=0;else
begin
if (gauss_dvalid == 1'b1)
begin
fp_gauss = $fopen("txt_out/gauss.txt","r+");
$fseek(fp_gauss,cnt_gauss,0);
$fdisplay(fp_gauss,"%04x\n",gauss_data);
$fclose(fp_gauss);
cnt_gauss<=cnt_gauss+6;
end
end
end
endgenerate
  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

BinaryStarXin

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值