參考:韓彬的影像處理書、無雙軟體學院方法。
步驟一:無損定點化
浮點數在硬體計算中首先需要做的便是定點化,一般是左移一定位寬,可以是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;
步驟五:符號化:
這裡計算的就不是座標,而是實際的畫素值了;
實際的畫素值也沒有負值,但是這裡計算出的資料可以用來後續對畫素的增減,重要性判斷,所以有正有負;
//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];