文章目录

  • 前言
  • 一、软件安装
  • 二、算法实现
    • 1.图片数据读入
    • 2.数据处理
      • 1.Matlab仿真
      • 2.利用Matlab Coder将Matlab代码转为C代码
      • 3.利用Vitis HLS将C代码转为Verilog代码
    • 3.图像显示
  • 3.完整FPGA工程代码:

这里是引用

前言

近年来,青岛附近海域的藻华现象越来越严重,针对这一问题,我们暑期实践选择了对藻华图像的处理,利用FPGA识别出图像中的浒苔。

一、软件安装

我们选用的板卡是xilinx中的ZYNQ-z7-20,软件需要使用VIVADO,同时使用vitis HLS将阈值计算部分的C代码转为Verilog代码。VIVADO和HLS的安装步骤网上有很详细的步骤,下面是我安装时参考的博客。
参考博客–最详细的Vivado安装教程

二、算法实现

1.图片数据读入

我们选择将图片数据由Matlab转化为coe文件后导入FPGA的rom中,在后续的数据处理中读取rom中的图片数据。

Matlab将PNG文件转为coe文件代码如下:

%读入的图片是灰度图,如果是RGB格式需要先转换为灰度图。
src = imread('19.png');
[m,n] = size( src );%
N = m*n;
word_len = 8;
data = reshape(src, 1, N);fid=fopen('19.coe', 'wt');%打开文件
fprintf(fid, 'MEMORY_INITIALIZATION_RADIX=16;\n');
fprintf(fid, 'MEMORY_INITIALIZATION_VECTOR=\n');
for i = 1 : N-1fprintf(fid, '%x,\n', data(i));%使用%x表示十六进制数
end
fprintf(fid, '%x;\n', data(N));
fclose(fid);

FPGA中ROM的使用可以借助IP核,ROM核的使用教程可以参考以下博客:
片内ROM读写测试实验

FPGA中ROM的使用部分代码如下:

wire [7:0] rom_data;
reg  [17:0] rom_addr;    rom_ip rom_ip_inst
(.clka   (pixclk),      //inoput clka.addra  (rom_addr),      //input [4:0] addra.douta  (rom_data)       //output [7:0] douta
);
always@(posedge pixclk)
beginif((x_cnt >= 740) && (x_cnt < 1240) && (y_cnt >= 164) && (y_cnt < 828 - 164)) rom_addr     <= rom_addr +1'b1;else if(rom_addr == 18'd250000)//图片为500x500格式,若图片尺寸不同,这一行和上一行需要根据图片的尺寸进行修改。rom_addr        <=18'b0; elserom_addr        <=rom_addr;
end

2.数据处理

根据图片中浒苔的灰度值更高这一特点,我们选择利用阈值算法对导入的数据进行二值化,将图片中的浒苔识别出来。由于某些图片中存在大气干扰、浒苔数量过多、过少等区别,一个固定的阈值并不能满足所有数据的需要,识别效果很差。因此我们在对图像数据进行预处理后,利用OTSU这一阈值算法进行阈值计算。
OTSU部分我们先用Matlab仿真,无误后利用Matlab中的app将Matlab代码转为C代码,之后利用Vitis HLS将C代码转为Verilog代码,封装成一个IP核导入到工程中进行使用。

1.Matlab仿真

Matlab中OTSU的代码如下:

im=imread("19.png");
m=500;n=500;
num=zeros(1,256);
sum=0;
start=1;
End=256;
for i = 1:mfor j = 1:nk=im(i,j);k=k+1;num(k)=num(k)+1;sum=sum+1;end
end
p=zeros(1,256);
for i = 1:256p(i)=num(i)/(m*n);
end
M=zeros(1,256);
pa=zeros(1,256);
pb=zeros(1,256);
ma=zeros(1,256);
mb=zeros(1,256);
for k = 1:256for i = 1:kpa(k)=pa(k)+p(i);M(k)=M(k)+(i-1)*p(i);end
end
for k = 1:256ma(k)=M(k)/pa(k);mb(k)=(M(256)-M(k))/(pa(256)-pa(k));
end
max_variance=0;
for k = 1:256variance=pa(k)*(pa(256)-pa(k))*(ma(k)-mb(k))^2;%variance=pa(k)*(ma(k)-M(255))^2+pb(k)*(mb(k)-M(255))^2;if(max_variance<variance)max_variance=variance;threshold=k-1;end
end
threshold

2.利用Matlab Coder将Matlab代码转为C代码

转化后代码如下:

/** File: otsu.c** MATLAB Coder version            : 5.2* C/C++ source code generated on  : 29-Jun-2022 15:57:35*//* Include Files */
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "otsu.h"
/* Function Definitions */
/** Arguments    : const unsigned char im[250000]* Return Type  : double*/unsigned int finish;
unsigned int pix_num;
double num[255];int otsu(unsigned int im,int threshold)
{#pragma HLS INTERFACE mode=ap_hs port=threshold
#pragma HLS INTERFACE mode=ap_hs port=im
#pragma HLS INTERFACE mode=ap_ctrl_hs port=returnpix_num=pix_num+1;if(pix_num!=250000){if(im<120) im = 120U;num[im-1]=num[im-1]+1;return 0;}double M[255];double pa[255];double pb[255];double resum[255];double max_variance;double variance;int b_i;int b_k;int i;int j;int start;unsigned char k;memset(&resum[0], 0, 255U * sizeof(double));start = 0;for (i = 0; i < 254; i++) {resum[253 - i] = resum[254 - i] + num[253 - i];}if (resum[120] - resum[169] > 10000.0) {start = 169;}for (i = 0; i < 255; i++) {resum[i] = num[i] / 250000.0;M[i] = 0.0;pa[i] = 0.0;pb[i] = 0.0;}for (b_k = 0; b_k < 255; b_k++) {for (i = 0; i <= b_k; i++) {variance = resum[i];pa[b_k] += variance;M[b_k] += ((double)i + 1.0) * variance;}b_i = 253 - b_k;for (i = 0; i <= b_i; i++) {pb[b_k] += resum[(b_k + i) + 1];}}for (b_k = 0; b_k < 255; b_k++) {resum[b_k] = M[b_k] / pa[b_k];num[b_k] = (M[254] - M[b_k]) / pb[b_k];}max_variance = 0.0;threshold = 200.0;b_i = 254 - start;for (b_k = 0; b_k <= b_i; b_k++) {j = start + b_k;variance = resum[j] - num[j];variance = pa[j] * pb[j] * (variance * variance);/* variance=pa(k)*(ma(k)-M(255))^2+pb(k)*(mb(k)-M(255))^2; */if (max_variance < variance) {max_variance = variance;threshold = j + 1.0;}}return threshold;
}/** File trailer for otsu.c** [EOF]*/

3.利用Vitis HLS将C代码转为Verilog代码

Vitis具体的使用步骤可以参考以下博客:
Vitis HLS 构建项目并生成IP核

FPGA中生成的OTSU例化部分代码如下:

otsu_0 otsu_cal
(.im_ap_vld            (1'b1),.im_ap_ack            (im_ap_ack),.threshold_ap_vld     (1'b1),.threshold_ap_ack     (threshold_ap_ack),.ap_clk               (pixclk),.ap_rst               (1'b0),.ap_start             (1'b1),.ap_done              (done),.ap_idle              (idle),.ap_ready             (ready),.ap_return            (threshold_otsu),.im                   (rom_data),.threshold            (threshold_start)
);

3.图像显示

zynq板卡上有HDMI输出接口,使用一根HDMI连接线,将板卡连接到显示器上,板卡发送数据即可显示。显示部分使用HDMI的IP核。

FPGA中HDMI例化代码如下:

HDMI_FPGA_ML_0 u_HDMI
(.PXLCLK_I           (pixclk),.PXLCLK_5X_I        (serclk),.LOCKED_I           (lock),.RST_N              (1'b1),.VGA_HS             (HS),.VGA_VS             (VS),.VGA_DE             (DE),.VGA_RGB            (RGB),.HDMI_CLK_P         (HDMI_CLK_P),.HDMI_CLK_N         (HDMI_CLK_N),.HDMI_D2_P          (HDMI_D2_P),.HDMI_D2_N          (HDMI_D2_N),.HDMI_D1_P          (HDMI_D1_P),.HDMI_D1_N          (HDMI_D1_N),.HDMI_D0_P          (HDMI_D0_P),.HDMI_D0_N          (HDMI_D0_N)
);

FPGA中HDMI显示代码如下:

`timescale 1ns / 1ps
module hdmi_data_gen(input              pix_clk,input               turn_mode,input  wire[7:0]     data,input  wire[11:0]    x_cnt,input  wire[11:0]    y_cnt,input  wire[7:0]    threshold,output      reg[3:0]led,output [7:0]        VGA_R,output [7:0]      VGA_G,output [7:0]      VGA_B,output                VGA_HS,output               VGA_VS,output               VGA_DE);parameter H_Total       =  1680; //e
parameter H_Sync        =  136;  //a
parameter H_Back        =  200; //b
parameter H_Active      =  1280;          //c
parameter H_Front       =  64;      //d
parameter H_Start       =  336;
parameter H_End     =  1616;parameter V_Total      =  828;
parameter V_Sync        =  3;
parameter V_Back        =  24;
parameter V_Active      =  800;
parameter V_Front       =  1;
parameter V_Start       =  27;
parameter V_End         =  827;reg[11:0]   x_cnt;
reg[7:0]    pix_data;
reg[7:0]    pix_data_two;
reg[23:0]   color_bar;
always @(posedge pix_clk )
beginif(threshold>8'd160)led[0]<=1'b1;
endalways @(posedge pix_clk)
beginif(threshold<9'd180)led[1]<=1'b1;
endreg [7:0]threshold_cal;
always@(posedge pix_clk)
beginif(threshold>threshold_cal)threshold_cal<=threshold;end
always@(posedge pix_clk)
beginif((x_cnt >= 740) && (x_cnt < 1240) && (y_cnt >= 164) && (y_cnt < 828 - 164)) beginpix_data <= data;endelse pix_data    <= 24'hffffff;end
always@(posedge pix_clk)
beginif((x_cnt >= 740) && (x_cnt < 1240) && (y_cnt >= 164) && (y_cnt < 828 - 164)) beginif(data>threshold_cal) beginpix_data_two<= 24'hffffff;endelse beginpix_data_two<=2'b0;endendelsepix_data_two <= 24'hffffff;end
reg[3:0]    dis_mode=0;
always @(posedge turn_mode)beginif(dis_mode<2'b11)dis_mode<= dis_mode + 1'b1;elsedis_mode<=1'b0;endreg[7:0] VGA_R_reg;
reg[7:0]    VGA_G_reg;
reg[7:0]    VGA_B_reg;
always @(posedge pix_clk)
begin  if(1'b0) begin VGA_R_reg<=0; VGA_G_reg<=0;VGA_B_reg<=0;      endelsecase(dis_mode)4'd0:beginVGA_R_reg<=0;            //LCD显示全黑VGA_G_reg<=0;VGA_B_reg<=0;end4'd1:beginVGA_R_reg<=pix_data;                //LCD显示原图VGA_G_reg<=pix_data;VGA_B_reg<=pix_data;end4'd2:beginVGA_R_reg<=pix_data_two;                //LCD显示结果图VGA_G_reg<=pix_data_two;VGA_B_reg<=pix_data_two;  end             default:beginVGA_R_reg<=8'hff;                //LCD显示全白VGA_G_reg<=8'hff;VGA_B_reg<=8'hff;end                     endcase
endwire  hs_de = (x_cnt<H_Start)? 0:(x_cnt<=H_End)?1:0;
wire  vs_de = (y_cnt<V_Start)? 0:(y_cnt<=V_End)?1:0;
reg [7:0] grid_data;assign VGA_HS = (x_cnt==1'b0)? 1:(x_cnt<H_Sync)?0:1;
assign VGA_VS = (y_cnt==1'b0)? 1:(y_cnt<V_Sync)?0:1;assign VGA_DE    =  hs_de & vs_de;
assign VGA_R    =  (hs_de & vs_de)?VGA_R_reg:8'h0;
assign VGA_G    =  (hs_de & vs_de)?VGA_G_reg:8'h0;
assign VGA_B    =  (hs_de & vs_de)?VGA_B_reg:8'h0;
endmodule

3.完整FPGA工程代码:

OTSU阈值算法进行图像二值化

利用OTSU阈值算法在ZYNQ上实现浒苔识别相关推荐

  1. TF之LSTM:利用多层LSTM算法对MNIST手写数字识别数据集进行多分类

    TF之LSTM:利用多层LSTM算法对MNIST手写数字识别数据集进行多分类 目录 设计思路 实现代码 设计思路 更新-- 实现代码 # -*- coding:utf-8 -*- import ten ...

  2. OpenCV —— 阈值分割(直方图技术法,熵算法,Otsu,自适应阈值算法)

    阈值分割 1. 全局阈值分割 直方图技术法 熵算法 Otsu算法 2. 局部阈值分割 自适应阈值 阈值的分割的核心就是如何选取阈值,选取正确的阈值时分割成功的关键.可以使用手动设置阈值,也可以采用直方 ...

  3. 【图像分割】利用粒子群算法与遗传算法实现图像的自适应多阈值的快速分割

    文章目录 前言 一.自适应多阈值分割 1.最大类间差方法 2.最大熵方法 二.代码部分(以粒子群算法与遗传算法优化自适应双阈值分割为例) 1. 利用粒子群算法优化最大类间差双阈值分割 1.1 概述 1 ...

  4. python实现Otsu双阈值算法

    最近在做双阈值的对比实验需要用到Otsu,发现网上没有python的实现,所以写下来记录一下. Otsu双阈值算法的思想与单阈值的思想类似,单阈值的思想为: g = w0(u0-u)^2+w1(u1- ...

  5. 【MATLAB教程案例23】基于MATLAB图像分割算法仿真——阈值分割法、Otsu阈值分割法、K均值聚类分割法等

    FPGA教程目录 MATLAB教程目录 目录 1.软件版本 2.通过二值图实现图像分割 3.通过Otsu阈值分割实现图像分割

  6. 基于MATLAB改进Otsu阈值分割的车道线检测

    基于MATLAB改进Otsu阈值分割的车道线检测 摘要:在判断车道偏离以防止车辆碰撞等危害时,车道标线检测需要通过图像处理来进行,检测方法是否适用于各种背景环境条件以及检测的及时性至关重要传统的Ots ...

  7. C#,图像二值化(24)——局部阈值算法的NiBlack算法及源程序

    1.局部阈值算法的NiBlack算法 摘要-医学图像的处理最为复杂人和计算机.磁性捐赠的脑组织共振成像(MRI)在许多领域是非常重要的问题例如手术和治疗.最常见的分割图像的最简单方法是使用阈值.在这项 ...

  8. OTSU图像分割算法(python实现)

    OTSU图像分割算法使用[最大类间方差]作为标准,利用图像直方图的分布信息,计算出一个阈值,根据像素是否超过阈值将图像分为前景与背景. (而实际上只是分割亮部与暗部而已,这种简单粗暴的单阈值分割无法真 ...

  9. win10+Python3.7.3+OpenCV3.4.1入门学习(十二 图像轮廓)————12.7 利用形状场景算法比较轮廓

    Python版本是Python3.7.3,OpenCV版本OpenCV3.4.1,开发环境为PyCharm 文章目录 12.7 利用形状场景算法比较轮廓 12.7.1 计算形状场景距离 12.7.2 ...

最新文章

  1. 新晋技术Leader每天996,CTO却给他绩效打C,留下一句话...
  2. Kraken:使用精确比对的超快速宏基因组序列分类软件
  3. 2018年人工智能将赋能所有行业,未来市场将超过400亿美元
  4. 【Android 安装包优化】资源混淆 ( resources.arsc 资源映射表混淆 | resources.arsc 资源映射表二进制格式分析 | 混淆全局字符串池和资源名称字符串池 )
  5. mysql的调试与分析_mysql日志管理分析调试实例_MySQL
  6. MySQL5.7升级到8.0 之后,配合ubantu18.04遇到的常规问题以及非常规问题的解决方案
  7. 做web前端的小伙伴注意了,未来这些发展方向可以试试!
  8. django-rest-framework二--权限(转载)
  9. jboss linux环境部署,linux下部署jboss
  10. App主界面交互框架(其中包括标签式、跳板式、列表式、旋转木马、抽屉式、点聚式、陈列馆式、瀑布流)
  11. 【Unity】插件TextAnimator 新手使用说明
  12. Docker直接删除elasticsearch报错:Failed to obtain node locks
  13. 保存numpy数组到excel
  14. 如何开展系统安全测试
  15. ITUNES更改备份保存路径(不放C盘,不占C盘)
  16. 网络世界的罪与罚:黑帽子是没有天堂的
  17. 51自学网php视频教程全集,51自学网免费PhotoShop视频教程全集
  18. 微信公众平台-微信发送朋友、分享到QQ、分享QQ空间、分享腾讯微博-JSSDk接口
  19. android组件化单独运行
  20. JavaScript注释语句

热门文章

  1. python 管理windows客户端_scrapyd的Windows管理客户端|python基础教程|python入门|python教程...
  2. 【linux】mdadm-raid1管理
  3. 【硅谷课堂】腾讯云点播WEB上传方式代码(第二种方式)
  4. 多行文字cad提取数据_CAD中使用多行文字标尺的技巧
  5. html隐藏窗口栏,electron程序,如何隐藏窗体顶部菜单?
  6. 数据如水,网络为渠 | 康普打好网络“地基”
  7. 乐视电视生死局:曾压得小米喘不过气,现在销量触底 线下渠道溃散!| 聚焦
  8. IDoc是个什么玩意儿
  9. 介质天线的设计原理_等离子体天线原理与设计.PDF
  10. idea配置sliksvn解决无法配置1.8 format 问题