• 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
    ', 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

  • 相关阅读:
    求职简历撰写要点和模板分享
    find命令
    MD5Init-MD5Update-MD5Final
    Linux find命令详解
    Linux进程KILL不掉的原因
    Linux操作系统的内存使用方法详细解析
    Lsof命令详解
    为什么ps中CPU占用率会有超出%100的现象?
    第12课 经典问题解析一
    第11课 新型的类型转换
  • 原文地址:https://www.cnblogs.com/qingkai/p/9896652.html
Copyright © 2020-2023  润新知