FPGA----图像sobel运算

上一节中 我们通过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灰度图像和彩色图像的区别

五、测试结果

这里写图片描述

这里写图片描述

源码下载地址:https://download.csdn.net/download/yunge812/10301478

猜你喜欢

转载自blog.csdn.net/yunge812/article/details/79649970
今日推荐