基于EBAZ4205矿板的图像处理:11阈值系数可调的图像局部阈值二值化

基于EBAZ4205矿板的图像处理:11阈值系数可调的图像局部阈值二值化

先看效果

还是一样拿我的pynq当模特,然后用usb——HDMI采集卡把输出图像采集到电脑上。在这里插入图片描述
注意看右边mobelxtem中的通过串口调节的参数
我这里是实现了阈值系数可调局部阈值二值化

局部阈值二值化系数binary_threshold = 128时的效果
在这里插入图片描述
局部阈值二值化系数binary_threshold =73时的效果,个人感觉这个时候效果最好
在这里插入图片描述
局部阈值二值化系数binary_threshold = 188时的效果
在这里插入图片描述
graph_threshold 不用管,那是为了后续的膨胀和腐蚀算法准备的。

算法讲解

图像局部阈值二值化,是一种能够自适应地提取图像局部二值化阈值的方法,他在图像明暗变化不一致的场景下,仍能获得很好的效果。
这种自适应地提取局部(即卷积的滑动窗口)阈值的提取方式有最大类间差,中值提取,均值提取等。
均值提取指的是当一个滑动窗口的中心点像素的像素值大于那个滑动窗口的均值时,将该像素点的像素值置为255,否则置为0。

然后,我在上面均值提取的基础上,在这个“均值”上加了一个调整系数,让一个像素点的最终二值化输出的结果既受到他周围的像素点的影响,也受到我的阈值系数的影响,以此我们就能动态调整图像的二值化效果

算法的FPGA部署

在这里插入图片描述

部署流程如上图所示,用两个ram缓存两行数据,然后和第三行实时数据一起通过打三拍地形式,以一种步长为1的滑动窗口的形式输出,将数据矩阵输入到局部阈值二值化模块中通过滑动窗口的均值和局部阈值系数,来对滑动窗口中心点像素进行判断,对滑动窗口中心点进行二值化处理。

项目讲解

block design跟上一篇有一个不同之处在于我添加了一个通过axi lite总线读写pl端reg的ip核,我在这个系列的第10篇博客里详细讲了怎么创建这个IP核。只需要按照那篇博客创建就可以了。

项目block design 如下
在这里插入图片描述
在这里插入图片描述
我的AXI Lite读写PLreg的模块,我把四个reg都引出了,方便以后开发。

项目代码

视频流处理模块

//作者:抢公主的大魔王
//日期:24.5.15
module video_processor((* X_INTERFACE_IGNORE = "true" *) input         frame_clk,    //cmos 像素时钟(* X_INTERFACE_IGNORE = "true" *) input         frame_rst_n,  //预处理图像(* X_INTERFACE_IGNORE = "true" *) input         pre_vsync, //预处理图像场同步信号(* X_INTERFACE_IGNORE = "true" *) input [23:0]  pre_data,  //预处理图像数据(* X_INTERFACE_IGNORE = "true" *) input         pre_href,  //预处理图像数据有效信号(* X_INTERFACE_IGNORE = "true" *) input         pre_frame_ce, //预处理图像时钟使能信号//阈值控制(* X_INTERFACE_IGNORE = "true" *) input [7:0 ]  loc_bin_thresh_coefficient, //来自PS端的局部二值化阈值系数//处理后图像(* X_INTERFACE_IGNORE = "true" *) output        pos_vsync, //处理后图像场同步信号(* X_INTERFACE_IGNORE = "true" *) output [23:0] pos_data,  //处理后图像数据(* X_INTERFACE_IGNORE = "true" *) output        pos_href, //处理后图像数据有效信号(* X_INTERFACE_IGNORE = "true" *) output        pos_frame_ce //处理后图像时钟使能信号  
);//wire define 
wire [7:0] gray_data ;
wire       gray_vsync;
wire       gray_frame_ce;
wire       gray_href;//*****************************************************
//**                    main code
//*****************************************************
//rgb转ycbcr模块
rgb2gray  u_rgb2gray(.cmos_frame_clk     (frame_clk      ),.cmos_rstn          (frame_rst_n    ),//同步复位.cmos_frame_vsync   (pre_vsync      ),.cmos_frame_data    (pre_data       ),.cmos_frame_href    (pre_href       ),.cmos_frame_ce      (pre_frame_ce   ),.dataout_frame_vsync(gray_vsync     ),.dataout_frame_data (gray_data      ),.dataout_frame_href (gray_href      ),.dataout_frame_ce   (gray_frame_ce  )
);
//wire define
wire        matrix_frame_vsync;
wire        matrix_frame_href;
wire        matrix_frame_ce;
wire [7:0]  matrix_p11; //3X3 矩阵数据
wire [7:0]  matrix_p12; 
wire [7:0]  matrix_p13;
wire [7:0]  matrix_p21; 
wire [7:0]  matrix_p22; 
wire [7:0]  matrix_p23;
wire [7:0]  matrix_p31; 
wire [7:0]  matrix_p32; 
wire [7:0]  matrix_p33;
// wire [7:0]  mid_value ;
// wire [7:0]  pos_img_Y;//*****************************************************
//**                    main code
//*****************************************************// assign pos_img_Y = pos_gray_href ? mid_value : 8'd0;
// assign pos_pixel_data = {pos_img_Y,pos_img_Y,pos_img_Y};VIP_matrix_generate_3x3_8bit u_VIP_matrix_generate_3x3_8bit(.clk                (frame_clk      ), .rst_n              (frame_rst_n    ),.per_frame_vsync    (gray_vsync     ),.per_frame_href     (gray_href      ), .per_frame_ce       (gray_frame_ce      ),.per_img_Y          (gray_data  ),//输出3x3矩阵.matrix_frame_vsync (matrix_frame_vsync ),.matrix_frame_href  (matrix_frame_href  ),.matrix_frame_ce    (matrix_frame_ce    ),.matrix_p11         (matrix_p11),    .matrix_p12         (matrix_p12),    .matrix_p13         (matrix_p13),.matrix_p21         (matrix_p21),    .matrix_p22         (matrix_p22),    .matrix_p23         (matrix_p23),.matrix_p31         (matrix_p31),    .matrix_p32         (matrix_p32),    .matrix_p33         (matrix_p33)
);
region_binary   u_region_binary(.clk                     (frame_clk             ),.rst_n                   (frame_rst_n           ),.matrix_img_vsync        (matrix_frame_vsync    ),.matrix_img_href         (matrix_frame_href     ),.matrix_frame_ce         (matrix_frame_ce       ),.loc_bin_thresh_coefficient           (loc_bin_thresh_coefficient         ),.matrix_p11              (matrix_p11            ),.matrix_p12              (matrix_p12            ),.matrix_p13              (matrix_p13            ),.matrix_p21              (matrix_p21            ),.matrix_p22              (matrix_p22            ),.matrix_p23              (matrix_p23            ),.matrix_p31              (matrix_p31            ),.matrix_p32              (matrix_p32            ),.matrix_p33              (matrix_p33            ),.dataout_vsync           (pos_vsync             ),       //  processed Image data vsync valid signal.dataout_href            (pos_href              ),       //  processed Image data href vaild  signal.dataout_gray            (pos_data              ),          //  processed Image brightness output.dataout_frame_ce        (pos_frame_ce          ));
endmodule 

rgb565转gray模块

`timescale 1ns / 1ps
//作者:抢公主的大魔王
module rgb2gray((* X_INTERFACE_IGNORE = "true" *)  input           cmos_frame_vsync,
(* X_INTERFACE_IGNORE = "true" *)  input [23:0]    cmos_frame_data,
(* X_INTERFACE_IGNORE = "true" *)  input           cmos_frame_href,(* X_INTERFACE_IGNORE = "true" *)  input           cmos_frame_clk,
(* X_INTERFACE_IGNORE = "true" *)  input           cmos_rstn,//同步复位
(* X_INTERFACE_IGNORE = "true" *)  input           cmos_frame_ce,(* X_INTERFACE_IGNORE = "true" *)  output          dataout_frame_vsync,
(* X_INTERFACE_IGNORE = "true" *)  output [7:0]    dataout_frame_data,
// (* X_INTERFACE_IGNORE = "true" *)  output [23:0]    dataout_frame_data,
(* X_INTERFACE_IGNORE = "true" *)  output          dataout_frame_href,
(* X_INTERFACE_IGNORE = "true" *)  output          dataout_frame_ce);// Y = 0.299R +0.587G + 0.114B// Y = (77 *R + 150*G + 29 *B)>>8reg [15:0] r_gray1;reg [15:0] g_gray1;reg [15:0] b_gray1;reg [15:0] y1;reg [7:0] y2;reg [2:0] dataout_frame_vsync_r;reg [2:0] dataout_frame_href_r;reg [2:0] dataout_frame_ce_r;always@(posedge cmos_frame_clk)beginif(!cmos_rstn)beginr_gray1 <= 8'h00;g_gray1 <= 8'h00;b_gray1 <= 8'h00;endelse beginr_gray1 <= cmos_frame_data[23:16]  * 8'd77 ;g_gray1 <= cmos_frame_data[15:8]   * 8'd150;b_gray1 <= cmos_frame_data[7:0]    * 8'd29 ;endendalways@(posedge cmos_frame_clk)beginif(!cmos_rstn)beginy1 <= 16'h0000;endelse beginy1 <= r_gray1 + g_gray1 + b_gray1;endendalways@(posedge cmos_frame_clk)beginif(!cmos_rstn)beginy2 <= 8'h0000;endelse beginy2 <= y1[15:8];endendalways@(posedge cmos_frame_clk)beginif(!cmos_rstn)begindataout_frame_ce_r      <= 3'b000;dataout_frame_vsync_r   <= 3'b000;dataout_frame_href_r    <= 3'b000;endelse begindataout_frame_ce_r      <= {dataout_frame_ce_r[1:0]     ,cmos_frame_ce};dataout_frame_vsync_r   <= {dataout_frame_vsync_r[1:0]  ,cmos_frame_vsync};dataout_frame_href_r    <= {dataout_frame_href_r[1:0]   ,cmos_frame_href};endend// assign dataout_frame_data = {y2,y2,y2};assign dataout_frame_data = y2;assign dataout_frame_ce = dataout_frame_ce_r[2];assign dataout_frame_vsync = dataout_frame_vsync_r[2];assign dataout_frame_href = dataout_frame_href_r[2];endmodule

卷积矩阵数据生成模块

这个模块和下面的行数据缓冲输出模块不是我写的,然后注意下面的行数据缓冲输出模块,有一个地方要改,我会说明。

//****************************************Copyright (c)***********************************//
//技术支持:www.openedv.com
//淘宝店铺:http://openedv.taobao.com 
//关注微信公众平台微信号:"正点原子",免费获取FPGA & STM32资料。
//版权所有,盗版必究。
//Copyright(C) 正点原子 2018-2028
//All rights reserved
//----------------------------------------------------------------------------------------
// File name:           VIP_matrix_generate_3x3_8bit
// Last modified Date:  2019/7/19 10:55:56
// Last Version:        V1.0
// Descriptions:        VIP_matrix_generate_3x3_8bit
//----------------------------------------------------------------------------------------
// Created by:          正点原子
// Created date:        2019/7/19 10:55:56
// Version:             V1.0
// Descriptions:        The original version
//----------------------------------------------------------------------------------------
//****************************************************************************************//module  VIP_matrix_generate_3x3_8bit
(input				clk,  		input				rst_n,				//准备要进行处理的图像数据input				per_frame_vsync,input				per_frame_href,input				per_frame_ce,//frame_ceinput        [7:0]  per_img_Y,//矩阵化后的图像数据和控制信号output				matrix_frame_vsync,output				matrix_frame_href,output				matrix_frame_ce,output	reg  [7:0]  matrix_p11, output	reg  [7:0]  matrix_p12,output	reg  [7:0]  matrix_p13,output	reg	 [7:0]  matrix_p21, output	reg  [7:0]  matrix_p22, output	reg  [7:0]  matrix_p23,output	reg	 [7:0]  matrix_p31, output	reg  [7:0]  matrix_p32, output	reg  [7:0]  matrix_p33
);//wire define
wire  [7:0]  row1_data;        //第一行数据
wire  [7:0]  row2_data;        //第二行数据
wire	     read_frame_href ;
wire	     read_frame_ce;//reg define
reg  [7:0]  row3_data;         //第三行数据,即当前正在接受的数据
reg  [1:0]  per_frame_vsync_r;
reg  [1:0]  per_frame_href_r;
reg  [1:0]  per_frame_ce_r;//*****************************************************
//**                    main code
//*****************************************************assign	read_frame_href    = per_frame_href_r[0] ;
assign	read_frame_ce   = per_frame_ce_r[0];
assign	matrix_frame_vsync = per_frame_vsync_r[1];//源数据打两拍输出,得到结果
assign	matrix_frame_href  = per_frame_href_r[1] ;//源数据打两拍输出,得到结果
assign	matrix_frame_ce    = per_frame_ce_r[1];//源数据打两拍输出,得到结果//打一拍时,第一行第一个点数据写入,且读出前一行和前前一行的数据,//第二排时数据稳定,将数据发完外部
//当前数据放在第3行
always@(posedge clk or negedge rst_n) beginif(!rst_n)row3_data <= 0;else begin		if(per_frame_ce)row3_data <= per_img_Y ;elserow3_data <= row3_data ;end
end//用于存储列数据的RAM
line_shift_RAM_8bit  u_Line_Shift_RAM_8Bit
(.clock		    (clk),.clken		    (per_frame_ce),.per_frame_href (per_frame_href),.shiftin	    (per_img_Y),   //当前行的数据.taps0x		    (row2_data),   //前一行的数据.taps1x		    (row1_data)    //前前一行的数据
);//将同步信号延迟两拍,用于同步化处理
always@(posedge clk or negedge rst_n) beginif(!rst_n) begin		per_frame_vsync_r <= 0;per_frame_href_r  <= 0;per_frame_ce_r <= 0;endelse begin		per_frame_vsync_r <= { per_frame_vsync_r[0], per_frame_vsync };per_frame_href_r  <= { per_frame_href_r[0],  per_frame_href  };per_frame_ce_r <= { per_frame_ce_r[0], per_frame_ce };end
end//在同步处理后的控制信号下,输出图像矩阵
always@(posedge clk or negedge rst_n) beginif(!rst_n) begin		{matrix_p11, matrix_p12, matrix_p13} <= 24'h0;{matrix_p21, matrix_p22, matrix_p23} <= 24'h0;{matrix_p31, matrix_p32, matrix_p33} <= 24'h0;endelse if(read_frame_href) beginif(read_frame_ce) begin			{matrix_p11, matrix_p12, matrix_p13} <= {matrix_p12, matrix_p13, row1_data};{matrix_p21, matrix_p22, matrix_p23} <= {matrix_p22, matrix_p23, row2_data};{matrix_p31, matrix_p32, matrix_p33} <= {matrix_p32, matrix_p33, row3_data};endelse begin			{matrix_p11, matrix_p12, matrix_p13} <= {matrix_p11, matrix_p12, matrix_p13};{matrix_p21, matrix_p22, matrix_p23} <= {matrix_p21, matrix_p22, matrix_p23};{matrix_p31, matrix_p32, matrix_p33} <= {matrix_p31, matrix_p32, matrix_p33};end	endelse begin		{matrix_p11, matrix_p12, matrix_p13} <= 24'h0;{matrix_p21, matrix_p22, matrix_p23} <= 24'h0;{matrix_p31, matrix_p32, matrix_p33} <= 24'h0;end
endendmodule

行数据缓冲输出模块

一定要注意正点原子的开源代码和免费教程里,例化的1024x8bit,如果你向我一样视频流的宽度大于1024就不行了,要改长度。我这里例化的就是2048x8bit的ram。

//****************************************Copyright (c)***********************************//
//技术支持:www.openedv.com
//淘宝店铺:http://openedv.taobao.com 
//关注微信公众平台微信号:"正点原子",免费获取FPGA & STM32资料。
//版权所有,盗版必究。
//Copyright(C) 正点原子 2018-2028
//All rights reserved
//----------------------------------------------------------------------------------------
// File name:           line_shift_RAM_8bit
// Last modified Date:  2019/7/19 10:55:56
// Last Version:        V1.0
// Descriptions:        line_shift_RAM_8bit
//----------------------------------------------------------------------------------------
// Created by:          正点原子
// Created date:        2019/7/19 10:55:56
// Version:             V1.0
// Descriptions:        The original version
//		两个伪双端口RAM用于存储 旧两行的数据。
//		在新一行的数据到来时,在延迟打拍的时序下,
//		先将RAM中的旧一行数据读出,再将新一行数据写入到RAM。
//----------------------------------------------------------------------------------------
//****************************************************************************************//module line_shift_RAM_8bit(input clock,input          clken,input          per_frame_href,input   [7:0]  shiftin,  //当前行的数据output  [7:0]  taps0x,   //前一行的数据output  [7:0]  taps1x    //前前一行的数据
);//reg define
reg  [2:0]  clken_dly;
reg  [10:0]  ram_rd_addr;
reg  [10:0]  ram_rd_addr_d0;
reg  [10:0]  ram_rd_addr_d1;
reg  [7:0]  shiftin_d0;
reg  [7:0]  shiftin_d1;
reg  [7:0]  shiftin_d2;
reg  [7:0]  taps0x_d0;//*****************************************************
//**                    main code
//*****************************************************//在数据到来时,RAM的读地址累加
always@(posedge clock)beginif(per_frame_href)if(clken)ram_rd_addr <= ram_rd_addr + 1 ;elseram_rd_addr <= ram_rd_addr ;elseram_rd_addr <= 0 ;
end//对时钟延迟3拍
always@(posedge clock) beginclken_dly <= { clken_dly[1:0] , clken };
end//将RAM地址延迟2拍
always@(posedge clock ) beginram_rd_addr_d0 <= ram_rd_addr;ram_rd_addr_d1 <= ram_rd_addr_d0;
end//输入数据延迟3拍送入RAM
always@(posedge clock)beginshiftin_d0 <= shiftin;shiftin_d1 <= shiftin_d0;shiftin_d2 <= shiftin_d1;
end//用于存储前一行图像的RAM
blk_mem_gen_0  u_ram_2048x8_0(.clka   (clock),.wea    (clken_dly[2]),.addra  (ram_rd_addr_d1),     //在延迟的第三个时钟周期,当前行的数据写入RAM0.dina   (shiftin_d2),.clkb   (clock),.addrb  (ram_rd_addr),    .doutb  (taps0x)              //延迟一个时钟周期,输出RAM0中前一行图像的数据
);//寄存前一行图像的数据
always@(posedge clock)begintaps0x_d0  <= taps0x;
end//用于存储前前一行图像的RAM
blk_mem_gen_0  u_ram_2048x8_1(.clka   (clock),.wea    (clken_dly[1]),.addra  (ram_rd_addr_d0),.dina   (taps0x_d0),       //在延迟的第二个时钟周期,将前一行图像的数据写入RAM1.clkb   (clock),.addrb  (ram_rd_addr),.doutb  (taps1x)           //延迟一个时钟周期,输出RAM1中前前一行图像的数据
);endmodule

局部阈值二值化模块

`timescale 1ns / 1ps
//作者:抢公主的大魔王
//日期:24.5.15module region_binary((* X_INTERFACE_IGNORE = "true" *) input   wire                     clk             ,(* X_INTERFACE_IGNORE = "true" *) input   wire                     rst_n           ,(* X_INTERFACE_IGNORE = "true" *) input   wire                     matrix_img_vsync,(* X_INTERFACE_IGNORE = "true" *) input   wire                     matrix_img_href,(* X_INTERFACE_IGNORE = "true" *) input   wire    [7:0]            loc_bin_thresh_coefficient, //来自PS端的阈值控制(* X_INTERFACE_IGNORE = "true" *) input   wire    [7:0]            matrix_p11,(* X_INTERFACE_IGNORE = "true" *) input   wire    [7:0]            matrix_p12,(* X_INTERFACE_IGNORE = "true" *) input   wire    [7:0]            matrix_p13,(* X_INTERFACE_IGNORE = "true" *) input   wire    [7:0]            matrix_p21,(* X_INTERFACE_IGNORE = "true" *) input   wire    [7:0]            matrix_p22,(* X_INTERFACE_IGNORE = "true" *) input   wire    [7:0]            matrix_p23,(* X_INTERFACE_IGNORE = "true" *) input   wire    [7:0]            matrix_p31,(* X_INTERFACE_IGNORE = "true" *) input   wire    [7:0]            matrix_p32,(* X_INTERFACE_IGNORE = "true" *) input   wire    [7:0]            matrix_p33,(* X_INTERFACE_IGNORE = "true" *) input   wire                     matrix_frame_ce,(* X_INTERFACE_IGNORE = "true" *) output reg                       dataout_vsync  ,       //  processed Image data vsync valid signal(* X_INTERFACE_IGNORE = "true" *) output reg                       dataout_href   ,       //  processed Image data href vaild  signal(* X_INTERFACE_IGNORE = "true" *) output reg      [23:0]           dataout_gray ,          //  processed Image brightness output(* X_INTERFACE_IGNORE = "true" *) output reg                       dataout_frame_ce);  
reg             [10:0]          data_sum1;
reg             [10:0]          data_sum2;
reg             [10:0]          data_sum3;always @(posedge clk)
begindata_sum1 <= matrix_p11 + matrix_p12 + matrix_p13;data_sum2 <= matrix_p21 + matrix_p22 + matrix_p23;data_sum3 <= matrix_p31 + matrix_p32 + matrix_p33;endreg             [12:0]          data_sum;always @(posedge clk)
begindata_sum <= data_sum1 + data_sum2 + data_sum3;
end//----------------------------------------------------------------------
//  thresh = floor(sum/9 *0.9) ==> floor(sum*603980 >> 24)
// 1677722/16777216;
// sum *9 /90
// sum /10
reg             [31:0]          mult_result;
reg             [24:0]          loc_bin_thresh_mult_coefficient;//0~16777216
always @(posedge clk)
beginloc_bin_thresh_mult_coefficient <= {loc_bin_thresh_coefficient,16'd0}; //1.8
endalways @(posedge clk)
begin// mult_result <= data_sum*21'd1677722;mult_result <= data_sum*loc_bin_thresh_mult_coefficient; //1.8
endwire            [7:0]          thresh;
assign thresh = mult_result[31:24];//----------------------------------------------------------------------
//  lag 3 clocks signal sync
reg             [2:0]           matrix_img_vsync_r;
reg             [2:0]           matrix_img_href_r;
reg             [2:0]           dataout_frame_ce_r;always @(posedge clk or negedge rst_n)
beginif(!rst_n)beginmatrix_img_vsync_r <= 3'b0;matrix_img_href_r  <= 3'b0;dataout_frame_ce_r <= 3'b0;endelsebeginmatrix_img_vsync_r <= {matrix_img_vsync_r[1:0],matrix_img_vsync};matrix_img_href_r  <= {matrix_img_href_r[1:0],matrix_img_href};dataout_frame_ce_r <= {dataout_frame_ce_r[1:0],matrix_frame_ce};end
endreg             [7:0]           matrix_p22_r    [0:2];always @(posedge clk)
beginmatrix_p22_r[0] <= matrix_p22;matrix_p22_r[1] <= matrix_p22_r[0];matrix_p22_r[2] <= matrix_p22_r[1];
end//----------------------------------------------------------------------
//  result output
always @(posedge clk or negedge rst_n)
beginif(!rst_n)dataout_gray <= {8'd255,8'd255,8'd255};else if(matrix_p22_r[2] < thresh)dataout_gray <= 24'd0;elsedataout_gray <= {8'd255,8'd255,8'd255};
endalways @(posedge clk or negedge rst_n)
beginif(!rst_n)begindataout_vsync <= 1'b0;dataout_href  <= 1'b0;dataout_frame_ce <= 1'b0; endelsebegindataout_vsync <= matrix_img_vsync_r[2];dataout_href  <= matrix_img_href_r[2];dataout_frame_ce  <= dataout_frame_ce_r[2];end
endendmodule

vitis代码

//作者:抢公主的大魔王
//功能:局部阈值二值化系数可调的图像二值化
//日期:24.5.15
//版本:1v0
//联系方式:2376635586@qq.com
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "xil_types.h"
#include "xil_cache.h"
#include "xparameters.h"
#include "xgpiops.h"
#include "xscugic.h"
#include "xil_exception.h"
#include "xplatform_info.h"
#include "xaxivdma.h"
#include "xaxivdma_i.h"
#include "display_ctrl_hdmi/display_ctrl.h"
#include "vdma_api/vdma_api.h"
#include "emio_sccb_cfg/emio_sccb_cfg.h"
#include "ov5640/ov5640_init.h"
#include "sleep.h"
#include "xuartps.h"
#include "string.h"//宏定义
#define DYNCLK_BASEADDR  	XPAR_AXI_DYNCLK_0_BASEADDR  //动态时钟基地址
#define VDMA_ID          	XPAR_AXIVDMA_0_DEVICE_ID    //VDMA器件ID
#define DISP_VTC_ID      	XPAR_VTC_0_DEVICE_ID        //VTC器件ID
#define UART_DEVICE_ID     XPAR_PS7_UART_0_DEVICE_ID    //串口设备ID
#define UART_INT_IRQ_ID    XPAR_XUARTPS_0_INTR          //串口中断ID
#define THRESHOLD_BASEADDR 	XPAR_AXICTRLTHRESHOLD_0_S00_AXI_BASEADDR#define EMIO_SCL_NUM 54
#define EMIO_SDA_NUM 55
#define KEY1 56 //T19
#define KEY2 57 //P19
#define KEY3 58 //U20
#define KEY4 59 //U19
#define KEY5 60 //V20
#define LED1 61 //H18
#define LED2 62 //K17
#define LED3 63 //E19#define GPIO_DEVICE_ID  	XPAR_XGPIOPS_0_DEVICE_ID
XGpioPs Gpio;
#define GPIO_BANK	XGPIOPS_BANK0  /* Bank 0 of the GPIO Device */
#define INTC_DEVICE_ID		XPAR_SCUGIC_SINGLE_DEVICE_ID
#define GPIO_INTERRUPT_ID	XPAR_XGPIOPS_0_INTR//全局变量
//frame buffer的起始地址
unsigned int const frame_buffer_addr = (XPAR_PS7_DDR_0_S_AXI_BASEADDR+ 0x1000000);
u8 binary_threshold = 128;
u8 graph_threshold = 8;XAxiVdma     vdma;
DisplayCtrl  dispCtrl;
VideoMode    vd_mode;static XScuGic Intc; //中断控制器驱动程序实例
static XUartPs Uart_Ps;           //串口驱动程序实例#define Uart0_Rec_Len  			128  	//定义USART1最大接收字节数
u8 Uart0_Rx_Buf[Uart0_Rec_Len];     //接收缓冲,最大USART_REC_LEN个字节.
//接收状态
//bit15,	接收完成标志
//bit14,	接收到0x0d
//bit13~0,	接收到的有效字节数目
u16 Uart0_Rx_Sta=0;       //接收状态标记//UART初始化函数
int uart_init(XUartPs* uart_ps)
{int status;XUartPs_Config *uart_cfg;uart_cfg = XUartPs_LookupConfig(UART_DEVICE_ID);if (NULL == uart_cfg)return XST_FAILURE;status = XUartPs_CfgInitialize(uart_ps, uart_cfg, uart_cfg->BaseAddress);if (status != XST_SUCCESS)return XST_FAILURE;//UART设备自检status = XUartPs_SelfTest(uart_ps);if (status != XST_SUCCESS)return XST_FAILURE;//设置工作模式:正常模式XUartPs_SetOperMode(uart_ps, XUARTPS_OPER_MODE_NORMAL);//设置波特率:115200XUartPs_SetBaudRate(uart_ps,115200);//设置RxFIFO的中断触发等级XUartPs_SetFifoThreshold(uart_ps, 1);return XST_SUCCESS;
}void uart_intr_handler(void *call_back_ref)
{XUartPs *uart_instance_ptr = (XUartPs *) call_back_ref;u32 rec_data = 0 ;u32 isr_status ;                           //中断状态标志//读取中断ID寄存器,判断触发的是哪种中断isr_status = XUartPs_ReadReg(uart_instance_ptr->Config.BaseAddress,XUARTPS_IMR_OFFSET);isr_status &= XUartPs_ReadReg(uart_instance_ptr->Config.BaseAddress,XUARTPS_ISR_OFFSET);//判断中断标志位RxFIFO是否触发if (isr_status & (u32)XUARTPS_IXR_RXOVR){rec_data = XUartPs_RecvByte(XPAR_PS7_UART_0_BASEADDR);//清除中断标志XUartPs_WriteReg(uart_instance_ptr->Config.BaseAddress,XUARTPS_ISR_OFFSET, XUARTPS_IXR_RXOVR) ;}XUartPs_SendByte(XPAR_PS7_UART_0_BASEADDR,rec_data);if((Uart0_Rx_Sta&0x8000)==0)//接收未完成{if(Uart0_Rx_Sta&0x4000)//接收到了0x0d{if(rec_data!=0x0a)Uart0_Rx_Sta=0;//接收错误,重新开始else Uart0_Rx_Sta|=0x8000;	//接收完成了}else//还没收到0X0D{if(rec_data==0x0d)Uart0_Rx_Sta|=0x4000;else{Uart0_Rx_Buf[Uart0_Rx_Sta&0X3FFF]=rec_data ; //将收到的数据放入数组Uart0_Rx_Sta++;	//数据长度计数加1if(Uart0_Rx_Sta>(Uart0_Rec_Len-1))Uart0_Rx_Sta=0;//接收数据错误,重新开始接收}}}}static void IntrHandler(void *CallBackRef, u32 Bank, u32 Status)
{XGpioPs *Gpio_cb = (XGpioPs *)CallBackRef;if (XGpioPs_IntrGetStatusPin(Gpio_cb, KEY1)){//binary_threshold++;//Xil_Out32(THRESHOLD_BASEADDR, binary_threshold);//xil_printf("The threshold has been changed\n\rThe threshold now is %d\n\r",binary_threshold);XGpioPs_IntrClearPin(Gpio_cb, KEY1);}else if (XGpioPs_IntrGetStatusPin(Gpio_cb, KEY4)){//binary_threshold--;//Xil_Out32(THRESHOLD_BASEADDR, binary_threshold);//xil_printf("The threshold has been changed\n\rThe threshold now is %d\n\r",binary_threshold);XGpioPs_IntrClearPin(Gpio_cb, KEY4);}else if (XGpioPs_IntrGetStatusPin(Gpio_cb, KEY2)){//binary_threshold = binary_threshold+10;//Xil_Out32(THRESHOLD_BASEADDR, binary_threshold);//xil_printf("The threshold has been changed\n\rThe threshold now is %d\n\r",binary_threshold);XGpioPs_IntrClearPin(Gpio_cb, KEY2);}else if (XGpioPs_IntrGetStatusPin(Gpio_cb, KEY5)){//binary_threshold = binary_threshold-10;//Xil_Out32(THRESHOLD_BASEADDR, binary_threshold);//xil_printf("The threshold has been changed\n\rThe threshold now is %d\n\r",binary_threshold);XGpioPs_IntrClearPin(Gpio_cb, KEY5);}else if (XGpioPs_IntrGetStatusPin(Gpio_cb, KEY3)){//binary_threshold = 128;//Xil_Out32(THRESHOLD_BASEADDR, binary_threshold);//xil_printf("The threshold has been reset\n\rThe threshold now is %d\n\r",binary_threshold);XGpioPs_IntrClearPin(Gpio_cb, KEY3);}XGpioPs_WritePin(&Gpio, LED1, !XGpioPs_ReadPin(&Gpio, LED1));
}//串口中断初始化void SetupInterruptSystem(XScuGic *GicInstancePtr, XGpioPs *Gpio,u16 GpioIntrId, XUartPs *uart_ps){XScuGic_Config *IntcConfig;IntcConfig = XScuGic_LookupConfig(INTC_DEVICE_ID);//初始化中断控制器XScuGic_CfgInitialize(GicInstancePtr, IntcConfig,IntcConfig->CpuBaseAddress);Xil_ExceptionInit();//设置并打开中断异常处理功能Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,(Xil_ExceptionHandler)XScuGic_InterruptHandler,GicInstancePtr);Xil_ExceptionEnable();//同Xil_ExceptionEnableMask(XIL_EXCEPTION_IRQ);XScuGic_Connect(GicInstancePtr, UART_INT_IRQ_ID,(Xil_ExceptionHandler) uart_intr_handler,(void *) uart_ps);//为中断设置中断处理函数XUartPs_SetInterruptMask(uart_ps, XUARTPS_IXR_RXOVR); //设置UART的中断触发方式XScuGic_Enable(GicInstancePtr, UART_INT_IRQ_ID);//使能GIC中的串口中断XScuGic_Connect(GicInstancePtr, GpioIntrId,(Xil_ExceptionHandler)IntrHandler,(void *)Gpio);//为按键中断设置中断处理函数XGpioPs_SetIntrTypePin(Gpio, KEY1,  XGPIOPS_IRQ_TYPE_EDGE_FALLING);XGpioPs_SetIntrTypePin(Gpio, KEY2,  XGPIOPS_IRQ_TYPE_EDGE_FALLING);//设置按键的中断方式XGpioPs_SetIntrTypePin(Gpio, KEY3,  XGPIOPS_IRQ_TYPE_EDGE_FALLING);XGpioPs_SetIntrTypePin(Gpio, KEY4,  XGPIOPS_IRQ_TYPE_EDGE_FALLING);XGpioPs_SetIntrTypePin(Gpio, KEY5,  XGPIOPS_IRQ_TYPE_EDGE_FALLING);XGpioPs_IntrEnablePin(Gpio, KEY1);XGpioPs_IntrEnablePin(Gpio, KEY2);XGpioPs_IntrEnablePin(Gpio, KEY3);XGpioPs_IntrEnablePin(Gpio, KEY4);XGpioPs_IntrEnablePin(Gpio, KEY5);XScuGic_Enable(GicInstancePtr, GpioIntrId);//使能按键中断
}void Gpio_Init(void){XGpioPs_Config *ConfigPtr;ConfigPtr = XGpioPs_LookupConfig(GPIO_DEVICE_ID);XGpioPs_CfgInitialize(&Gpio, ConfigPtr,ConfigPtr->BaseAddr);XGpioPs_SetDirectionPin(&Gpio, LED1, 1);XGpioPs_SetOutputEnablePin(&Gpio, LED1, 1);XGpioPs_WritePin(&Gpio, LED1, 0);XGpioPs_SetDirectionPin(&Gpio, LED2, 1);XGpioPs_SetOutputEnablePin(&Gpio, LED2, 1);XGpioPs_WritePin(&Gpio, LED2, 0);XGpioPs_SetDirectionPin(&Gpio, LED3, 1);XGpioPs_SetOutputEnablePin(&Gpio, LED3, 1);XGpioPs_WritePin(&Gpio, LED3, 0);XGpioPs_SetDirectionPin(&Gpio, KEY1, 0);XGpioPs_SetDirectionPin(&Gpio, KEY2, 0);XGpioPs_SetDirectionPin(&Gpio, KEY3, 0);XGpioPs_SetDirectionPin(&Gpio, KEY4, 0);XGpioPs_SetDirectionPin(&Gpio, KEY5, 0);}int main(void)
{u32 status;u16 cmos_h_pixel;                    //ov5640 DVP 输出水平像素点数u16 cmos_v_pixel;                    //ov5640 DVP 输出垂直像素点数u16 total_h_pixel;                   //ov5640 水平总像素大小u16 total_v_pixel;                   //ov5640 垂直总像素大小cmos_h_pixel = 1280;cmos_v_pixel = 720;total_h_pixel = 2570;total_v_pixel = 980;emio_init();//控制hdmi的emio初始化//xil_printf("Uart and Key is init successful! \r\n");//xil_printf("ov5640 is initing! \r\n");status = ov5640_init( cmos_h_pixel,  //初始化ov5640cmos_v_pixel,total_h_pixel,total_v_pixel);//设置OV5640输出分辨率为1280*720  PCLK = 72Mhzif(status == 0);//xil_printf("OV5640 init successful!\r\n");elsexil_printf("OV5640 detected failed!\r\n");xil_printf("Uart and OV5640 is init successful! \r\nInput any to run!\r\n");sleep(1);vd_mode = VMODE_1280x720;//配置VDMArun_vdma_frame_buffer(&vdma, VDMA_ID, vd_mode.width, vd_mode.height,frame_buffer_addr,0,0,BOTH);//初始化Display controllerDisplayInitialize(&dispCtrl, DISP_VTC_ID, DYNCLK_BASEADDR);//设置VideoModeDisplaySetMode(&dispCtrl, &vd_mode);DisplayStart(&dispCtrl);Gpio_Init();//按键和led的初始化uart_init(&Uart_Ps);   //串口初始化SetupInterruptSystem(&Intc, &Gpio, GPIO_INTERRUPT_ID,&Uart_Ps);while(1){if(Uart0_Rx_Sta&0xC000){ //如果标志位是0xC000表示收到数据串完成,可以处理。if((Uart0_Rx_Sta&0x3FFF)==0){ //单独的回车键再显示一次欢迎词printf("1y--add binary threshold      1n--sub binary threshold \r\n");printf("2y--add graph threshold       2n--sub graph threshold  \r\n");printf("3s--show all the threshold \r\n");printf("please input cmd \r\n");}else if((Uart0_Rx_Sta&0x3FFF)==2 && Uart0_Rx_Buf[0]=='1' && Uart0_Rx_Buf[1]=='y'){ //判断数据是不是2个,第一个数据是不是“1”,第二个是不是“y”binary_threshold = binary_threshold + 5;Xil_Out32(THRESHOLD_BASEADDR, binary_threshold);printf("1y -- add binary threshold to %d\r\n",binary_threshold);}else if((Uart0_Rx_Sta&0x3FFF)==2 && Uart0_Rx_Buf[0]=='1' && Uart0_Rx_Buf[1]=='n'){binary_threshold = binary_threshold - 5;Xil_Out32(THRESHOLD_BASEADDR, binary_threshold);printf("1n -- sub binary threshold to %d\r\n",binary_threshold);}else if((Uart0_Rx_Sta&0x3FFF)==2 && Uart0_Rx_Buf[0]=='2' && Uart0_Rx_Buf[1]=='y'){graph_threshold = graph_threshold + 1;Xil_Out32(THRESHOLD_BASEADDR+4, graph_threshold);printf("2y -- add graph threshold to %d\r\n",graph_threshold);}else if((Uart0_Rx_Sta&0x3FFF)==2 && Uart0_Rx_Buf[0]=='2' && Uart0_Rx_Buf[1]=='n'){graph_threshold = graph_threshold - 1;Xil_Out32(THRESHOLD_BASEADDR+4, graph_threshold);printf("2n -- sub graph threshold to %d\r\n",graph_threshold);}else if((Uart0_Rx_Sta&0x3FFF)==2 && Uart0_Rx_Buf[0]=='3' && Uart0_Rx_Buf[1]=='s'){printf("3s--show all the threshold\r\nbinary threshold is %d \r\ngraph threshold is %d \r\n",binary_threshold,graph_threshold);}else{ //如果以上都不是,即是错误的指令。printf("cmd error\r\n");}Uart0_Rx_Sta=0; //将串口数据标志位清0}}return 0;
}

代码中使用UART接受中断,接受用户通过串口发送的数据,用户可以通过串口动态调整局部阈值二值化系数。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/12611.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

利用CAD绘制角度斜线的简易指南---模大狮模型网

在CAD设计中&#xff0c;绘制角度斜线是常见的需求&#xff0c;尤其在工程、建筑等领域中。正确绘制角度斜线不仅可以提高图纸的清晰度和美观度&#xff0c;还有助于准确表达设计意图。本文将介绍如何利用CAD软件进行角度斜线的绘制&#xff0c;为您提供简明易懂的操作指南。 一…

安全设备篇——抗DDOS设备

写在前面&#xff1a;up初研究这个设备的时候以为很容易&#xff0c;毕竟ddos嘛大家都懂&#xff0c;但是实际去找资料和研究的时候发现资料少的可怜&#xff0c;再加上大家知道ddos但大多没见过&#xff0c;万幸up的老东家某普有这类设备&#xff0c;和之前的同事沟通了一下还…

网络完全精通版

一、目录结构 1.1目的的特点 windows和linux windows中C、D、E盘&#xff0c;每个都是一个根系统【多跟系统】 linux中只有一个根【单根系统】 1.2各个目录存储的内容 /root&#xff1a;linux中挂管理员用户的家目录 /home&#xff1a;linux中挂存储普通用户的家目录的目…

Unity射击游戏开发教程:(17)添加推进器推进和推进器推进动画

添加推进器打开功能 我们可以添加一个推进器栏,用于跟踪玩家使用推进器增强(按住左 Shift 键)的时间。当未使用推力时,将会有一段延迟,直到推力条开始再生。当棒再生时,可以使用推进器,但再生过程将重新开始。 我们将使用 Unity 的 UI Slider 组件,因此我们将其添加到已…

银河麒麟V10操作系统编译LLVM18踩坑记录

1、简述 要在银河麒麟V10操作系统上编译一个LLVM18&#xff0c;这个系统之前确实也没有用过&#xff0c;所以开始了一系列的摸排工作&#xff0c;进行一下记录。 首先肯定是要搞一个系统&#xff0c;所以去到银河麒麟的网站&#xff0c;填写了一个申请 产品试用申请国产操作系…

数据结构--链表的基本操作

1. 链表的概念及结构 概念&#xff1a;链表是⼀种物理存储结构上⾮连续、⾮顺序的存储结构&#xff0c;数据元素的逻辑顺序是通过链表 中的指针链接次序实现的 。 链表也是线性表的一种。 链表的结构跟⽕⻋⻋厢相似&#xff0c;淡季时⻋次的⻋厢会相应减少&#xff0c;旺季时…

嵌入式—STC芯片开发板点亮第一盏灯

&#x1f3ac; 秋野酱&#xff1a;《个人主页》 &#x1f525; 个人专栏:《Java专栏》《Python专栏》 ⛺️心若有所向往,何惧道阻且长 文章目录 一&#xff1a; 原理图二&#xff1a; 需求实现三&#xff1a;编码实现四&#xff1a;代码实现五&#xff1a;编译烧录运行 一&…

HTML哆啦A梦

目录 写在前面 HTML简介 完整代码 代码分析 系列推荐 写在最后 写在前面 谁不想拥有一只可爱的叮当猫呢&#xff1f;本期小编给大家带来了一个萌萌的哆啦A梦。 HTML简介 HTML&#xff0c;即超文本标记语言&#xff0c;是构建网页的基础技术之一&#xff0c;它是一种标…

JavaEE初阶-多线程进阶2

文章目录 前言一、CAS1.1 CAS的概念1.2 原子类1.3 CAS的ABA问题 二、JUC中常用类2.1 Callable接口2.2 ReentrantLock&#xff08;可重入&#xff09;2.3 Semaphore信号量2.4 CountDownLatch类2.5 CopyOnWriteArrayList类2.6 ConcurrentHashMap 前言 对于多线程进阶的部分&…

C语言例题43、打印倒立金字塔

#include <stdio.h>void main() {int i, j;for (i 5; i > 0; i--) {for (j 5; j > i; j--) {//输出空格printf(" ");}for (j 2 * i; j > 1; j--) {//输出星号printf("* ");}printf("\n");} }运行结果&#xff1a; 本章C语言…

用好 explain 妈妈再也不用担心我的 SQL 慢了

大家好&#xff0c;我是聪&#xff0c;一个乐于分享的小小程序员。在不久之前我写了一个慢 SQL 分析工具&#xff0c;可以用来分析 Java Mybatis 项目的 SQL 执行情况&#xff0c;其中刚好涉及到了 explain 的使用。感兴趣的可以了解一下。 Github 地址⭐&#xff1a;https://…

【C#】学习获取程序执行路径,Gemini 帮助分析

一、前言&#xff1a; 在Delphi中&#xff0c;如果想要获取当前执行程序的目录&#xff0c;程序代码如下&#xff1a; ExtractFilePath(ParamStr(0)); 今天在分析一个别人做的C#程序时看到了一段C#代码&#xff0c;意思是获取执行程序所在的文件目录&#xff1a; public stat…

基于区块链的Web 3.0关键技术研讨会顺利召开

基于区块链的Web3.0关键技术研讨会 2024年4月23日&#xff0c;由国家区块链技术创新中心主办的“基于区块链的web3.0关键技术研讨会”召开。Web3.0被用来描述一个运行在“区块链”技术之上的“去中心化”的互联网&#xff0c;该网络上的主体掌握自己数据所有权和使用权&#xf…

【回眸】git VS repo 区别

git VS repo 区别 1. git&#xff1a;Git是一个开源的分布式版本控制系统&#xff0c;用以有效、高速的处理从很小到非常大的项目版本管理。 2. Repo: Repo是谷歌用Python脚本写的调用git的一个脚本,Repo实现管理多个git库。 Git 常用命令 1. git init&#xff1a;在当前目…

【原创】java+springboot+mysql企业邮件管理系统设计与实现

个人主页&#xff1a;程序猿小小杨 个人简介&#xff1a;从事开发多年&#xff0c;Java、Php、Python、前端开发均有涉猎 博客内容&#xff1a;Java项目实战、项目演示、技术分享 文末有作者名片&#xff0c;希望和大家一起共同进步&#xff0c;你只管努力&#xff0c;剩下的交…

Vue的学习 —— <vue组件>

目录 前言 正文 一、选项式API与组合式API 二、生命周期函数 1、onBeforeMount() 2、onMounted() 3、onBeforeUpdate() 4、onUpdated() 5、onBeforeUnmount() 6、onUnmounted() 三、组件之间的样式冲突 四、父组件向子组件传递数据 1、定义props 2、静态绑定props…

C++青少年简明教程:赋值语句

C青少年简明教程&#xff1a;赋值语句 赋值语句是编程中最基本也是最常用的概念之一&#xff0c;它用于将一个值分配给一个变量。 使用等号&#xff08; 称为赋值运算符&#xff09;来给变量赋值&#xff0c;赋值语句的左边是要赋值的变量&#xff0c;右边是要赋给变量的值。C…

Docker 使用 CentOS 镜像

使用 docker run 直接运行 CentOS 7 镜像&#xff0c;并登录 bash。 C:\Users\yhu>docker run -it centos:centos7 bash Unable to find image centos:centos7 locally centos7: Pulling from library/centos 2d473b07cdd5: Pull complete Digest: sha256:be65f488b7764ad36…

GPT-4o:全面深入了解 OpenAI 的 GPT-4o

GPT-4o&#xff1a;全面深入了解 OpenAI 的 GPT-4o 关于 GPT-4o 的所有信息ChatGPT 增强的用户体验改进的多语言和音频功能GPT-4o 优于 Whisper-v3M3Exam 基准测试中的表现 GPT-4o 的起源追踪语言模型的演变GPT 谱系&#xff1a;人工智能语言的开拓者多模式飞跃&#xff1a;超越…