上一节中 我们通过LineBuffer得到来对齐的三行像素的输出
本节 我们利用这个输出结果 计算图像的sobel
一、计算sobel
//============================================== 计算sobel =========================================================//
//无符号数
wire [10:0]dataX;
wire [10:0]dataY;
wire [10:0]data;
//第一位为符号位
wire [11:0]tempX;
wire [11:0]tempY;
assign tempX = {1'b0,pix_13} + {1'b0,pix_23<<1} + {1'b0,pix_33} + {1'b1,(~pix_11+1'b1)} + {1'b1,(~pix_21+1'b1)} + {1'b1,(~pix_21+1'b1)} + {1'b1,(~pix_31+1'b1)};
assign tempY = {1'b0,pix_11} + {1'b0,pix_12<<1} + {1'b0,pix_13} + {1'b1,(~pix_31+1'b1)} + {1'b1,(~pix_32+1'b1)} + {1'b1,(~pix_32+1'b1)} + {1'b1,(~pix_33+1'b1)};
assign dataX = tempX[11] ? (~tempX[10:0]+1'b1) : tempX[10:0];
assign dataY = tempY[11] ? (~tempY[10:0]+1'b1) : tempY[10:0];
二 计算行列坐标
//======================= 生成输出的 行 列坐标 =====================//
reg [31:0] l_real;
reg [31:0] r_real;
reg [1:0]state;
always @(posedge clkin)
if(!rst_n)
state<= 1'b0;
else
begin
case(state)
0:
begin
l_real <= cnt_l2;
r_real <= cnt_r2 - 1'b1;
if( r_real == (H-1'b1)) //添加最后一行的横纵坐标
begin
l_real <= l_real + 1'b1;
if(l_real == (W-1'b1))
state <= 1'b1;
end
end
1:
state <= 1'b1;
endcase
end
三、判断是否出边界
//============================================ 判断是否是边界 输出0 ==================================================//
assign dataOut = ((l_real == 1'b0) || (l_real == (W-1'b1)) || (r_real == 1'b0) || (r_real == (H-1'b1))) ? 0 : (dataX > dataY) ? dataX : dataY ;
//============================================== 判断数据有效 =======================================================//
assign dataOutValid = ((l_real >= 1'b0) && (l_real <= (W-1'b1)) && (r_real >= 1'b0) && (r_real <= (H-1'b1))) ? 1'b1:1'b0 ;
由于sobel边上的两行无法计算sobel的值 因此给它赋值0
四、仿真测试
仿真测试中 读取一张图片 输出sobel之后的图片 该过程在testbench中完成
4.1 读取图片
always @(posedge clkin or negedge rst_n)
if(!rst_n)
begin
state <= 6'd0;
fp_r = $fopen("E:\\FPGA_project\\Sobel2\\In.bmp", "rb");
cnt_r <= 32'd0;
$fseek(fp_r,1078,0);
end
else
begin
case(state)
//======================= dataIn ===========================//
0:
begin
$fread(dataIn,fp_r,,1);
cnt_r <= cnt_r + 32'd1 ;
dataInValid <= 1'b1;
if(cnt_r == 32'd388800) //
begin
state <= 6'd1;
dataInValid <= 1'b0;
//$fclose(fp_r);
cnt_r <= 1'b0;
end
else
state <= 6'd0;
end
1:
begin
state <= 6'd1;
end
endcase
end
$fseek(fp_r,1078,0);代表跳过图片头部1078个字节 1078之后均为实际的有效数据
4.2 sobel图像输出
//======================= dataOut ===========================//
always @(posedge clkin or negedge rst_n)
if(!rst_n)
begin
i <= 6'd0;
fp_w = $fopen("E:\\FPGA_project\\Sobel2\\Out.bmp", "rb+");
cnt_w <= 32'd0;
$fseek(fp_w,54,0);
end
else
begin
case(i)
0:
if(dataOutValid==1'b1)
begin
$fwrite(fp_w, "%u", dataBMP);
cnt_w <= cnt_w + 32'd1 ;
if(cnt_w == 32'd388800 -1'b1) //64*64*5:h5000 640*480:h177000 720*540:d388800
begin
i <= 6'd1;
$fclose(fp_w);
end
else
i <= 6'd0;
end
1:
i <= 6'd1;
endcase
end
$fseek(fp_r,54,0);代表跳过图片头部54个字节 1078之后均为实际的有效数据
为什么输入位1078 输出位54呢 就是因为bmp灰度图像和彩色图像的区别