FPGA简单图像处理

这个小项目读取一张bmp格式的图像文件,做灰度化,二值化或者色彩调整并输出

工程为验证性仿真工程,无需上板,含有不可综合代码,也不能上板

首先,需要借助MATLAB将bmp格式图像文件转化为hex格式

imdata = imread('kodim23.bmp'); % 24-bit BMP image RGB888 

tmp=1:768*512*3;
m = 1;
for i=1:512
    for j=1:768
        for k = 1:3
            tmp(m)=imdata(i,j,k);
            m = m+1;
        end
    end
end

fid = fopen('kodim23.hex', 'wt');
fprintf(fid, '%x\n', tmp);
fclose(fid);

disp('Text file write done');
disp(' ');

Verilog代码部分包含一个图像读取模块,该模块有图像处理的部分,和一个图像写模块,还有一个参数文件用于选择对图像进行那种处理

在读模块中,定义一个位宽为8,深度为数据长度的二维数组用于存储图像数据

    reg    [7:0]    total_memory[0:DATA_SIZE-1];

    initial begin
        $readmemh(INFILE, total_memory, 0, DATA_SIZE-1);
    end

然后通过一段不可综合代码将其中的R, G, B数据分开存储

    always @(start) begin
        if(start) begin
            for(i=0;i<DATA_SIZE;i=i+1) begin
                temp_bmp[i] = total_memory[i][7:0];
            end
            for(i=0;i<HEIGHT;i=i+1) begin
                for(j=0;j<WIDTH;j=j+1) begin
                    temp_r[WIDTH*i+j] = temp_bmp[(WIDTH*i+j)*3+0];
                    temp_g[WIDTH*i+j] = temp_bmp[(WIDTH*i+j)*3+1];
                    temp_b[WIDTH*i+j] = temp_bmp[(WIDTH*i+j)*3+2];
                end
            end
        end
    end

参照视频数据流帧格式,输出行场同步信号,通过一个状态机做流程控制,在数据处理时,对图像进行如下处理

    always @* begin
        if(state_c == S_DATA) begin
            `ifdef BRIGHTNESS_OPERATION
                if(SIGN == 1) begin
                    DATA_R0 = (temp_r[WIDTH*cnt_row+cnt_col]+VALUE>255) ? 255 : temp_r[WIDTH*cnt_row+cnt_col]+VALUE;
                    DATA_R1 = (temp_r[WIDTH*cnt_row+cnt_col+1]+VALUE>255) ? 255 : temp_r[WIDTH*cnt_row+cnt_col+1]+VALUE;
                    DATA_G0 = (temp_g[WIDTH*cnt_row+cnt_col]+VALUE>255) ? 255 : temp_g[WIDTH*cnt_row+cnt_col]+VALUE;
                    DATA_G1 = (temp_g[WIDTH*cnt_row+cnt_col+1]+VALUE>255) ? 255 : temp_g[WIDTH*cnt_row+cnt_col+1]+VALUE;
                    DATA_B0 = (temp_b[WIDTH*cnt_row+cnt_col]+VALUE>255) ? 255 : temp_b[WIDTH*cnt_row+cnt_col]+VALUE;
                    DATA_B1 = (temp_b[WIDTH*cnt_row+cnt_col+1]+VALUE>255) ? 255 : temp_b[WIDTH*cnt_row+cnt_col+1]+VALUE;
                end
                else begin
                    DATA_R0 = (temp_r[WIDTH*cnt_row+cnt_col]-VALUE<0) ? 0 : temp_r[WIDTH*cnt_row+cnt_col]-VALUE;
                    DATA_R1 = (temp_r[WIDTH*cnt_row+cnt_col+1]-VALUE<0) ? 0 : temp_r[WIDTH*cnt_row+cnt_col+1]-VALUE;
                    DATA_G0 = (temp_g[WIDTH*cnt_row+cnt_col]-VALUE<0) ? 0 : temp_g[WIDTH*cnt_row+cnt_col]-VALUE;
                    DATA_G1 = (temp_g[WIDTH*cnt_row+cnt_col+1]-VALUE<0) ? 0 : temp_g[WIDTH*cnt_row+cnt_col+1]-VALUE;
                    DATA_B0 = (temp_b[WIDTH*cnt_row+cnt_col]-VALUE<0) ? 0 : temp_b[WIDTH*cnt_row+cnt_col]-VALUE;
                    DATA_B1 = (temp_b[WIDTH*cnt_row+cnt_col+1]-VALUE<0) ? 0 : temp_b[WIDTH*cnt_row+cnt_col+1]-VALUE;                
                end
            `else
                `ifdef INVERT_OPERATION
                    DATA_R0 = 255-((temp_r[WIDTH*cnt_row+cnt_col]+temp_g[WIDTH*cnt_row+cnt_col]+temp_b[WIDTH*cnt_row+cnt_col])/3);
                    DATA_G0 = 255-((temp_r[WIDTH*cnt_row+cnt_col]+temp_g[WIDTH*cnt_row+cnt_col]+temp_b[WIDTH*cnt_row+cnt_col])/3);
                    DATA_B0 = 255-((temp_r[WIDTH*cnt_row+cnt_col]+temp_g[WIDTH*cnt_row+cnt_col]+temp_b[WIDTH*cnt_row+cnt_col])/3);
                    DATA_R1 = 255-((temp_r[WIDTH*cnt_row+cnt_col+1]+temp_g[WIDTH*cnt_row+cnt_col+1]+temp_b[WIDTH*cnt_row+cnt_col]+1)/3);
                    DATA_G1 = 255-((temp_r[WIDTH*cnt_row+cnt_col+1]+temp_g[WIDTH*cnt_row+cnt_col+1]+temp_b[WIDTH*cnt_row+cnt_col]+1)/3);
                    DATA_B1 = 255-((temp_r[WIDTH*cnt_row+cnt_col+1]+temp_g[WIDTH*cnt_row+cnt_col+1]+temp_b[WIDTH*cnt_row+cnt_col]+1)/3);
                `else
                    `ifdef THRESHOLD_OPERATION
                        DATA_R0 = ((temp_r[WIDTH*cnt_row+cnt_col]+temp_g[WIDTH*cnt_row+cnt_col]+temp_b[WIDTH*cnt_row+cnt_col])/3>THRESHOLD) ? 255 : 0;
                        DATA_G0 = ((temp_r[WIDTH*cnt_row+cnt_col]+temp_g[WIDTH*cnt_row+cnt_col]+temp_b[WIDTH*cnt_row+cnt_col])/3>THRESHOLD) ? 255 : 0;
                        DATA_B0 = ((temp_r[WIDTH*cnt_row+cnt_col]+temp_g[WIDTH*cnt_row+cnt_col]+temp_b[WIDTH*cnt_row+cnt_col])/3>THRESHOLD) ? 255 : 0;
                        DATA_R1 = ((temp_r[WIDTH*cnt_row+cnt_col+1]+temp_g[WIDTH*cnt_row+cnt_col+1]+temp_b[WIDTH*cnt_row+cnt_col+1])/3>THRESHOLD) ? 255 : 0;
                        DATA_G1 = ((temp_r[WIDTH*cnt_row+cnt_col+1]+temp_g[WIDTH*cnt_row+cnt_col+1]+temp_b[WIDTH*cnt_row+cnt_col+1])/3>THRESHOLD) ? 255 : 0;
                        DATA_B1 = ((temp_r[WIDTH*cnt_row+cnt_col+1]+temp_g[WIDTH*cnt_row+cnt_col+1]+temp_b[WIDTH*cnt_row+cnt_col+1])/3>THRESHOLD) ? 255 : 0;
                    `else
                        DATA_R0 = temp_r[WIDTH*cnt_row+cnt_col];
                        DATA_R1 = temp_r[WIDTH*cnt_row+cnt_col+1];
                        DATA_G0 = temp_g[WIDTH*cnt_row+cnt_col];
                        DATA_G1 = temp_g[WIDTH*cnt_row+cnt_col+1];
                        DATA_B0 = temp_b[WIDTH*cnt_row+cnt_col];
                        DATA_B1 = temp_b[WIDTH*cnt_row+cnt_col+1];
                    `endif
                `endif
            `endif
        end
        else begin
            DATA_R0 = 0;
            DATA_R1 = 0;
            DATA_G0 = 0;
            DATA_G1 = 0;
            DATA_B0 = 0;
            DATA_B1 = 0;
        end    
    end

写模块将读模块输出的数据写入到bmp格式文件中,重点需要注意的是

!!!bmp存储数据是从最后一行开时,依次往上,即以一个数据是图像左下的的像素的数据,且每个像素的数据是以B, G, R的顺序依次存储

bmp格式头请参考 http://www.fastgraph.com/help/bmp_header_format.html

原始图片如下

亮度减弱后的效果如下

 

本项目参考网上一个教程,教程地址https://www.fpga4student.com/2016/11/image-processing-on-fpga-verilog.html

posted @ 2018-11-02 15:47  自由的青  阅读(7303)  评论(0编辑  收藏  举报