IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> FPGA实现灰度直方图统计 -> 正文阅读

[嵌入式]FPGA实现灰度直方图统计

实现思想:图像的灰度值0-255,那么就把灰度值当成RAM的地址,这样就把统计转成了对RAM的读写。
根据网上的资料再结合自己的思想,我用了两种方法来实现了对灰度数据的统计,第一种是倍频的方法(不适用于实际),只使用了1个RAM,另一种是使用多个RAM错位实现。
方法一:读数据2CLK,写数据CLK,即读取数据的时钟频率是写入的两倍,板子上跑的时候跑不到时钟的两倍,这个方法仅仅适用在仿真,没有太大实用价值,所以稍微提下。
为了方便对每个流程的控制,使用了状态机,如图:
在这里插入图片描述
状态转换:空闲时接收到图像开始信号后跳转到清楚状态,该状态是将上张图片的数据清除,清除完毕后跳转到统计状态,在统计状态下对图像的灰度值进行统计,当图像结束信号来到后,就可以读取灰度统计数据,读取完成后跳转到空闲状态等待下一张图片。
图像中相邻的像素点有可能是相同的,如果采用来个像素就对该地址上的数值+1,当两个相邻像素点相同时就会导致数据丢失,因为写入数据到稳定(能够被读出来)需要1个CLK,多个灰度值相同时就会出现数据还没写进去就开始读数据,读出来的数据就是0,所以我用2倍频的时钟用于读,就能够避免冲突。
先对相邻的数据进行对比,只有当相邻数据不同时才将统计数据写入到RAM,同时计数值回到1。如图:
在这里插入图片描述
读取的数据需要和写入的地址、写入的统计数据一一对齐。使用的RAM是没有输出寄存器的,也就是从开始读取到输出数据需要1个CLK,中间计算需要1个CLK,那么写入地址(相对于读取数据)就需要延迟2个CLK。
方法二:使用4个 RAM,用类似乒乓操作的来实现。
状态机是一样的,但与方法一相比的状态机跳转条件有些变动:
在这里插入图片描述

/************************状态机**********************/
always @(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        STATE <= 4'b0001;//空闲状态
    end
    else begin
        case (STATE)
            IDEL  : begin
                if(clear_ram_flag) begin//开始清空RAM
                    STATE <= CLEAR;
                end
                else begin
                    STATE <= IDEL;
                end
            end
            CLEAR :begin
                if(clear_addr_add==255)begin//清空完成
                    STATE <= STATISTICS;
                end
                else begin
                    STATE <= CLEAR;
                end
            end
            STATISTICS: begin
                if(avalon_streaming_source_endofpacket_wait2clk) begin//图片数据统计结束
                    STATE <= GET_RESULT;
                end
                else begin
                    STATE <= STATISTICS;
                end
            end
            GET_RESULT: begin
                if(get_statistics_addr>257)begin//255读完RAM的数,257数据才输出完成
                    STATE <= IDEL;
                end
                else begin
                    STATE <= GET_RESULT;
                end
            end
            default : begin
                    STATE <= IDEL;
                end
        endcase
    end
end

状态跳转:空闲情况下一上电或者图片传输完成标志就跳转到清除状态,这跟方法一有些不同,主要考虑到了清除RAM中的数据只需要256个CLK,板子实际晶振是125MHz,也就是说清除RAM需要的时间只需2us左右,而使用的工业相机每张图片传输的时间间隔远远大于2us ,这样同时也解决了方法一需要使用一个RAM先缓存开始清除时错过的256个数据。如图:
在这里插入图片描述
清除完毕后跳转到统计状态,在统计状态下接收到图像传输开始标志位后对图像的灰度值进行统计,当图像结束信号来到后,就可以读取灰度统计数据。
统计的方法也不同,由于我用了4个RAM做类似乒乓操作,所以不用担心存在读写冲突,来一个灰度值就在对应地址的数据上+1。如图:
在这里插入图片描述

/*********************写状态更变*********************/
always @(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        {wr_en0,wr_en1,wr_en2,wr_en3} <= 4'b0000;
        wr_addr <= 8'd0;
        wr_data <= 32'd0;
    end
    else if(STATE==CLEAR)begin
        {wr_en0,wr_en1,wr_en2,wr_en3} <= 4'b1111;
        wr_addr <= clear_addr_add;
        wr_data <= 32'd0;
    end
    else if(STATE==STATISTICS && avalon_streaming_source_valid_wait4clk)begin
        wr_addr <= avalon_streaming_source_data_wait3clk;
        wr_data <= histo_data + 1'b1;
        case (ram_switch_wait4clk)
            3'd0 :begin
                {wr_en0,wr_en1,wr_en2,wr_en3} <= 4'b1000;
            end
            3'd1 :begin
                {wr_en0,wr_en1,wr_en2,wr_en3} <= 4'b0100;
            end
            3'd2 :begin
                {wr_en0,wr_en1,wr_en2,wr_en3} <= 4'b0010;
            end
            3'd3 :begin
                {wr_en0,wr_en1,wr_en2,wr_en3} <= 4'b0001;
            end
            default : {wr_en0,wr_en1,wr_en2,wr_en3} <= 4'b0000;          
        endcase
    end
    else begin
        {wr_en0,wr_en1,wr_en2,wr_en3} <= 4'b0000;
        wr_addr <= 8'd0;
        wr_data <= 32'd0;
    end
end

/***************************************************/
/*********************读状态更变*********************/
always @(posedge clk or negedge rst_n) begin
     if(!rst_n) begin
        rd_en <= 1'b0;
        rd_addr <= 8'd0;
    end
    else if(STATE==STATISTICS  && avalon_streaming_source_valid)begin
        rd_en <= 1'b1;
        rd_addr <= avalon_streaming_source_data;//
         case (ram_switch)
            3'd0 : begin
                histo_data <= q1;
            end
            3'd1 : begin
                histo_data <= q2;
            end
            3'd2 : begin  
                histo_data <= q3;
            end
            3'd3 : begin
                histo_data <= q0;
            end    
            default : histo_data <= 32'd0;       
        endcase
    end
    else if(STATE==GET_RESULT&&get_statistics_addr<=255)begin
        rd_en <= 1'b1;
        rd_addr <= get_statistics_addr;
    end
    else begin
        rd_en <= 1'b0;
        rd_addr <= 8'd0;
        histo_data <= 32'd0; 
              
    end
end
/***************************************************/

用一张1920*1024的图片来验证,在Matlab得到一张相机原图的灰度直方图,然后与仿真得到的结果对比,从大体上看是没什么问题的,,具体统计出来的数据有点小偏差,但是找了前面几帧没发现统计出错的问题,后面继续深究这个问题,或许又想到另一种更简单又准确的方法。
在这里插入图片描述
在这里插入图片描述

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2021-09-06 11:19:00  更:2021-09-06 11:20:37 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 1:30:29-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码