有符号浮点运算的基本步骤:以双线性插值为例

参考:韩彬的图像处理书、无双软件学院方法。

步骤一:无损定点化

浮点数在硬件计算中首先需要做的便是定点化,一般是左移一定位宽,可以是2048或4096;

这个过程要注意保障无损;

步骤二:运算和位宽匹配;

要确定所有参与计算的数小数位位宽是匹配的,否则无法进行任何层次的计算;

需要特别注意很多小数在计算的时候也需要定点化,例如:

always@(posedge clk)
    if(rst)    
        src_xf0 <= 'd0;
    else if(dst_de==1'b1)
        src_xf0 <= {dst_hcnt,2'd0} + 2;
    else
        src_xf0 <= 'd0;

这里做的计算是修改后的双线性插值中的中心对齐操作;

0.5左移两位变成了2;

步骤三:相乘后的截位处理

发生了相乘操作以后,整数和小数位宽都会发生变化,注意匹配;

此处小数位位宽为12,0.5左移12位后为2048;

//fix16_2 * fix16_12  = fix32_14        
always@(posedge clk)
    if(rst)    
        src_xf1 <= 'd0;
    else
        src_xf1 <= src_xf0*sx;
//fix26_12 - fix12_12  = fix26_12 可能为负数
always@(posedge clk)
    if(rst)    
        src_xf2 <= 'd0;
    else
        src_xf2 <= src_xf1[27:2] - 2048;

步骤四:加减处理后的正负判断;

目前为止的公式:src_x = (dst_x + 0.5) * scale_x - 0.5

always@(posedge clk)
    if(rst)    
        src_xf3 <= 'd0;
    else
        src_xf3 <= src_xf2;        

always@(posedge clk)
    if(rst)    
        src_x0 <= 'd0;
    else if(src_xf2[25]==1'b1)
        src_x0 <= 'd0;        
    else
        src_x0 <= src_xf2[25:12];

在这里的运算中,相减可能出现负数,这是显而易见的,但是此处xf2指的是坐标;(当然,相加如果坐标大于图像尺寸也会做匹配处理)

坐标不能有负数,最小是0;

在sobel里我也做了类似的操作;

always@(posedge clk)
    if(rst)    
        region_type <= 0;
    else if(src_x0>=SRC_IW-1&&src_y0>=SRC_IH-1&&src_xy_de==1'b1)
        region_type <= 1;
    else if(src_y0>=SRC_IH-1&&src_xy_de==1'b1)
        region_type <= 2;
    else if(src_x0>=SRC_IW-1&&src_xy_de==1'b1)    
        region_type <= 3;
    else
        region_type <= 4;

步骤五:符号化:

这里计算的就不是坐标,而是实际的像素值了;

此外,正数的有符号化需要在最高位手动填0。

实际的像素值也没有负值,但是这里计算出的数据可以用来后续对像素的增减,重要性判断,所以有正有负;

//fix26_12 - fix26_12 = fix26_12
always@(posedge clk)
    if(rst)    
        v <= 'd0;
    else
        v <= $signed(src_xf3) - $signed({src_x0,12'd0});    

后面没有太多指的说的,只需要记住实际使用的时候取出整数位数据;

还有就是小数位第一位是1代表了0.5,如果希望做四舍五入的话需要在整数位+1处理;

//fix25_12
always@(posedge clk)
    if(rst)
        cast_data <= 'd0;
    else if(line_data[24]==1'b1)
        cast_data <= 0;    
    else if(line_data[22:12]>=255)
        cast_data <= 255;
    else
        cast_data <= line_data[11] ? line_data[19:12] + 1'b1 : line_data[19:12];

 

posted @ 2024-08-16 18:23  NoNounknow  阅读(24)  评论(0编辑  收藏  举报