基于FPGA的图像边缘检测

2023-05-16

基于FPGA的图像边缘检测

      • 一、图像处理算法
        • 1.灰度转换
        • 2.高斯滤波
        • 3.二值化
        • 4.Sobel
      • 二、项目框架
        • 1.摄像头配置模块
        • 2.图像处理模块
        • 3.数据缓存模块
        • 4.其它模块
      • 三、部分代码
        • 1.数据采集模块
        • 2.读写控制模块
      • 四、参考
      • 五、源码

简介:基于FPGA,摄像头实时采集图像数据,经过图像处理、乒乓缓存,通过vga显示

工具:Quartus 18.1

开发板:AIGO_C4MB_V11(CycloneIV-EP4CE6F17C8)

摄像头:OV5640

一、图像处理算法

1.灰度转换

RGB颜色模型是由红(Red)、绿(Green)、蓝(Blue)三种基色以不同的比例叠加而成;而且每个像素分量(R、G、B)的值分布在0—255范围内,三种基色以不同的比例混合,能够显示出2563种颜色。 在这个项目中ov5640采集的数据是16位rgb565的数据,首先扩展为rgb888,然后进行加权求和
在这里插入图片描述
如图所示,灰度转换的公式
在灰度转换过程中,可能会因为取整操作引入噪声,所以接下来使用高斯滤波算法来去除灰度转化过程中引入的噪声

2.高斯滤波

高斯滤波本质上是一种线性平滑滤波,即对整幅图像进行加权平均的过程,每一个像素点的值都是由其本身和邻域内的其他像素点加权平均后得到
高斯滤波的具体操作是使用一个N*N卷积模板对整幅图像扫描,用模板确定的邻域内的像素加权平均值代替模板中心像素点的值
在这里插入图片描述

其中,I(x,y)表示原图像中坐标为(x,y)的像素值;G(x,y)表示高斯滤波之后的值

3.二值化

二值化的作用是把灰度图像的像素值设置为0或者255,即纯黑或者纯白。通过二值图像,能更好地分析物体的形状和轮廓,有利于后续使用Sobel算子检测图像的边缘
二值化有多种方法,其中最常用的就是采用阈值法进行二值化

4.Sobel

Sobel算子主要用于检测图像边缘,在物体的边缘通常都有像素的变化,反映了物体与背景之间的差异,或者两个物体之间的差异。它是一个离散差分算子,用来计算像素点上下、左右领域内像素点的加权差,根据在边缘处达到极值来检测边缘
Sobel算子在水平方向和垂直方向各采用一个模板,检测各方向上的边缘,其优点是计算简单,速度快;但是对于纹理较为复杂的图像,检测效果不理想。水平方向模板Sx和垂直方向模板Sy如下
在这里插入图片描述

将两个算子与图像做平面卷积,即可得到水平方向与垂直方向的梯度值;若以I表示图像矩阵,Gx表示水平方向图像梯度值,Gy表示垂直方向的梯度值,则Gx与Gy可以表示如下:
在这里插入图片描述

二、项目框架

整个项目主要分为:
摄像头配置模块、图像处理模块、数据缓存模块、vga显示模块以及时钟管理模块
在这里插入图片描述

1.摄像头配置模块

摄像头配置模块负责配置摄像头各个参数,在摄像头上电后需要等待20ms。然后再通过I2C发送设备ID、写地址和数据,其中地址先发送高8位再发送低8位。这里包含摄像头时钟、图像大小、帧率以及其他和图像相关的参数,按照配置表中的参数,将摄像头配置为分辨率为1280*720像素点、RGB565数据格式、VGA时序输出;然后通过I2C协议将参数配置给摄像头的每个寄存器

2.图像处理模块

该模块完成图像数据的采集与处理;图像采集模块(capture)对摄像头输出的像素数据进行串并转换,然后给到后续的图像处理模块,依次进行灰度转换(rgb565_gray)、高斯滤(gs_filter)、二值化处理(gray_bin)、Sobel边缘检测(sobel)

3.数据缓存模块

通过乒乓缓存操作向SDRAM中读写图像数据,接口通过调用IP,主要是SDRAM读写控制逻辑(rw_control),使用两个异步FIFO跨时钟域数据处理,使用读写仲裁机制产生读写传输请求、地址等
为什么要用pp(乒乓)缓存?
如果不采用乒乓缓存,OV5640 帧率 30fps,VGA 帧率 60fps,如果摄像头输入的数据和VGA输出的数据都是连续不断的,那么刚好可以写一帧读两帧。但是一帧图像实际情况是一行行的生成和读取的,所以会出现 VGA 从SDRAM处读的上半帧是新帧,而由于SDRAM缓存的下半帧还没有被 OV5640写完,VGA 从SDRAM处读的下半帧还是旧帧,会出现错帧现象。采用乒乓缓存机制时,使用两个缓存区,写缓存区 1 时读缓存区 2,写缓存区 2 时读缓存区 1,每个缓存区存储完整的数据帧,读写隔离并且读写交替则不会出现错帧现象
为什么要读写仲裁?
仲裁:在FPGA中,当多个操作同时发出请求,容易导致操作冲突,因此我们需要根据相应的优先级来响应哪一个操作,这个过程就叫仲裁。在SDRAM中,初始化完成后,主要的功能就是突发写、突发读和自动刷新。如果同时发起写、读和刷新请求,就会出现操作冲突,从而导致SDRAM工作出错,因此这里就需要引入仲裁机制。为了简化设计,考虑将刷新与读写请求的仲裁分开考虑。由于刷新的优先级一定高于读写,因此,在底层接口中,只对读/写请求与刷新请求进行仲裁,即刷新请求的优先级一定高于读/写请求。在控制逻辑中,对读/写请求进行仲裁,保证底层接口不会同时收到读请求与写请求,从而避免底层接口中出现复杂控制

4.其它模块

vga模块就是通过vga协议将图像显示,这个非常简单,我之前的博客也写过关于vga的操作,这里就不在过多赘述
时钟管理模块则是通过pll生成时钟供SDRAM、vga、ov5640使用也没什么技术含量

三、部分代码

1.数据采集模块

`include "param.v"
module capture(
    input           clk     ,//像素时钟 摄像头输出的pclk
    input           rst_n   ,

    input           enable  ,//采集使能 配置完成
    input           vsync   ,//摄像头场同步信号
    input           href    ,//摄像头行参考信号
    input   [7:0]   din     ,//摄像头像素字节

    output  [15:0]  dout    ,//像素数据
    output          dout_sop,//包文头 一帧图像第一个像素点
    output          dout_eop,//包文尾 一帧图像最后一个像素点
    output          dout_vld //像素数据有效
);

//信号定义
    reg     [11:0]      cnt_h       ;
    wire                add_cnt_h   ;
    wire                end_cnt_h   ;
    reg     [9:0]       cnt_v       ;
    wire                add_cnt_v   ;
    wire                end_cnt_v   ;
    
    reg     [1:0]       vsync_r     ;//同步打拍
    wire                vsync_nedge ;//下降沿
    reg                 flag        ;//串并转换标志
    
    reg     [15:0]      data        ;
    reg                 data_vld    ;
    reg                 data_sop    ;
    reg                 data_eop    ;

//计数器
    
    always @(posedge clk or negedge rst_n) begin 
        if (rst_n==0) begin
            cnt_h <= 0; 
        end
        else if(add_cnt_h) begin
            if(end_cnt_h)
                cnt_h <= 0; 
            else
                cnt_h <= cnt_h+1 ;
       end
    end
    assign add_cnt_h = flag & href;
    assign end_cnt_h = add_cnt_h  && cnt_h == (`H_AP << 1)-1;
    
    always @(posedge clk or negedge rst_n) begin 
        if (rst_n==0) begin
            cnt_v <= 0; 
        end
        else if(add_cnt_v) begin
            if(end_cnt_v)
                cnt_v <= 0; 
            else
                cnt_v <= cnt_v+1 ;
       end
    end
    assign add_cnt_v = end_cnt_h;
    assign end_cnt_v = add_cnt_v  && cnt_v == `V_AP-1 ;

//vsync同步打拍
    always  @(posedge clk or negedge rst_n)begin
        if(~rst_n)begin
            vsync_r <= 2'b00;
        end
        else begin
            vsync_r <= {vsync_r[0],vsync};
        end
    end
    assign vsync_nedge = vsync_r[1] & ~vsync_r[0];

    always  @(posedge clk or negedge rst_n)begin
        if(~rst_n)begin
            flag <= 1'b0;
        end
        else if(enable & vsync_nedge)begin  //摄像头配置完成且场同步信号拉低之后开始采集有效数据
            flag <= 1'b1;
        end
        else if(end_cnt_v)begin     //一帧数据采集完拉低
            flag <= 1'b0;   
        end
    end

//data
    always  @(posedge clk or negedge rst_n)begin
        if(~rst_n)begin
            data <= 0;
        end
        else begin
            data <= {data[7:0],din};//左移
            //data <= 16'b1101_1010_1111_0111;//16'hdaf7
        end
    end

//data_sop
    always  @(posedge clk or negedge rst_n)begin
        if(~rst_n)begin
            data_sop <= 1'b0;
            data_eop <= 1'b0;
            data_vld <= 1'b0;
        end
        else begin
            data_sop <= add_cnt_h && cnt_h == 2-1 && cnt_v == 0;
            data_eop <= end_cnt_v;
            data_vld <= add_cnt_h && cnt_h[0] == 1'b1;
        end
    end

    assign dout = data;
    assign dout_sop = data_sop;
    assign dout_eop = data_eop;
    assign dout_vld = data_vld;

endmodule 

2.读写控制模块

`include"param.v"
module sdram_ctrl (
    input               clk             ,
    input               clk_in          ,
    input               clk_out         ,
    input               rst_n           ,
    //数据输入
    input   [15:0]      din             ,//摄像头输入像素数据
    input               din_sop         ,
    input               din_eop         ,    
    input               din_vld         ,
    //数据输出
    input               rdreq           ,//vga的读数据请求
    output  [15:0]      dout            ,//输出给vga的数据
    output              dout_vld        ,//输出给vga的数据有效标志
    //sdram_interface
    output              avm_write       ,//输出给sdram 接口 IP 的写请求
    output              avm_read        ,//输出给sdram 接口 IP 的读请求
    output  [23:0]      avm_addr        ,//输出给sdram 接口 IP 的读写地址
    output  [15:0]      avm_wrdata      ,//输出给sdram 接口 IP 的写数据
    input   [15:0]      avs_rddata      ,//sdram 接口 IP 输入的读数据
    input               avs_rddata_vld  ,
    input               avs_waitrequest    
);

//参数定义
    localparam  IDLE  = 4'b0001,
                WRITE = 4'b0010,
                READ  = 4'b0100,
                DONE  = 4'b1000;

//信号定义

    reg     [3:0]       state_c     ;
    reg     [3:0]       state_n     ;

    reg     [8:0]       cnt         ;//突发读写计数器
    wire                add_cnt     ;
    wire                end_cnt     ;
    
    reg     [1:0]       wr_bank     ;//写bank
    reg     [1:0]       rd_bank     ;//读bank
    reg     [21:0]      wr_addr     ;//写地址   行地址 + 列地址
    wire                add_wr_addr ;
    wire                end_wr_addr ;
    reg     [21:0]      rd_addr     ;//读地址   行地址 + 列地址
    wire                add_rd_addr ;
    wire                end_rd_addr ;

    reg                 change_bank ;//切换bank 
    reg                 wr_finish   ;//一帧数据写完
    reg     [1:0]       wr_finish_r ;//同步到写侧
    reg                 wr_data_flag;//wrfifo写数据的标志

    reg                 wr_flag     ;
    reg                 rd_flag     ;
    reg                 flag_sel    ;
    reg                 prior_flag  ;

    wire                idle2write  ;  
    wire                idle2read   ;
    wire                write2done  ;
    wire                read2done   ;

    reg     [15:0]      rd_data     ;//rfifo读数据输出
    reg                 rd_data_vld ;

    wire    [17:0]      wfifo_data  ; 
    wire                wfifo_rdreq ;
    wire                wfifo_wrreq ;
    wire    [17:0]      wfifo_q     ;
    wire                wfifo_empty ;
    wire    [10:0]      wfifo_usedw ;
    wire                wfifo_full  ;

    wire    [15:0]      rfifo_data  ;
    wire                rfifo_rdreq ;
    wire                rfifo_wrreq ;
    wire    [15:0]      rfifo_q     ;
    wire                rfifo_empty ;
    wire                rfifo_full  ;
    wire    [10:0]      rfifo_usedw ;

//状态机
    always  @(posedge clk or negedge rst_n)begin
        if(~rst_n)begin
            state_c <= IDLE;
        end
        else begin
            state_c <= state_n;
        end
    end

    always  @(*)begin
        case(state_c)
            IDLE  :begin 
                if(idle2write)
                    state_n = WRITE;
                else if(idle2read)
                    state_n = READ;
                else 
                    state_n = state_c;
            end 
            WRITE :begin 
                if(write2done)
                    state_n = DONE;
                else 
                    state_n = state_c;
            end     
            READ  :begin 
                if(read2done)
                    state_n = DONE;
                else 
                    state_n = state_c;
            end 
            DONE  :state_n = IDLE;
            default:state_n = IDLE;
        endcase  
    end

    assign idle2write = state_c == IDLE  && (~prior_flag && wfifo_usedw >= `USER_BL);
    assign idle2read  = state_c == IDLE  && prior_flag && rfifo_usedw <= `RD_UT;
    assign write2done = state_c == WRITE && end_cnt;
    assign read2done  = state_c == READ  && end_cnt;

//计数器
    always @(posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            cnt <= 0;
        end
        else if(add_cnt)begin
            if(end_cnt)
                cnt <= 0;
            else
                cnt <= cnt + 1;
        end
    end

    assign add_cnt = (state_c == WRITE | state_c == READ) & ~avs_waitrequest; 
    assign end_cnt = add_cnt && cnt== `USER_BL-1;  

/************************读写优先级仲裁*****************************/
//rd_flag     ;//读请求标志
    always @(posedge clk or negedge rst_n)begin 
        if(!rst_n)begin
            rd_flag <= 0;
        end 
        else if(rfifo_usedw <= `RD_LT)begin   
            rd_flag <= 1'b1;
        end 
        else if(rfifo_usedw > `RD_UT)begin 
            rd_flag <= 1'b0;
        end 
    end

//wr_flag     ;//写请求标志
    always @(posedge clk or negedge rst_n)begin 
        if(!rst_n)begin
            wr_flag <= 0;
        end 
        else if(wfifo_usedw >= `USER_BL)begin 
            wr_flag <= 1'b1;
        end 
        else begin 
            wr_flag <= 1'b0;
        end 
    end

//flag_sel    ;//标记上一次操作
    always @(posedge clk or negedge rst_n)begin 
        if(!rst_n)begin
            flag_sel <= 0;
        end 
        else if(read2done)begin 
            flag_sel <= 1;
        end 
        else if(write2done)begin 
            flag_sel <= 0;
        end 
    end

//prior_flag  ;//优先级标志 0:写优先级高   1:读优先级高     仲裁读、写的优先级
    always @(posedge clk or negedge rst_n)begin 
        if(!rst_n)begin
            prior_flag <= 0;
        end 
        else if(wr_flag && (flag_sel || (~flag_sel && ~rd_flag)))begin   //突发写优先级高
            prior_flag <= 1'b0;
        end 
        else if(rd_flag && (~flag_sel || (flag_sel && ~wr_flag)))begin   //突发读优先级高
            prior_flag <= 1'b1;
        end 
    end

/******************************************************************/    

/********************      地址设计    ****************************/    

//wr_bank  rd_bank
    always  @(posedge clk or negedge rst_n)begin
        if(~rst_n)begin
            wr_bank <= 2'b00;
            rd_bank <= 2'b11;
        end
        else if(change_bank)begin
            wr_bank <= ~wr_bank;
            rd_bank <= ~rd_bank;
        end
    end

// wr_addr   rd_addr
    always @(posedge clk or negedge rst_n) begin 
        if (rst_n==0) begin
            wr_addr <= 0; 
        end
        else if(add_wr_addr) begin
            if(end_wr_addr)
                wr_addr <= 0; 
            else
                wr_addr <= wr_addr+1 ;
       end
    end
    assign add_wr_addr = (state_c == WRITE) && ~avs_waitrequest;
    assign end_wr_addr = add_wr_addr  && wr_addr == `BURST_MAX-1 ;
    
    always @(posedge clk or negedge rst_n) begin 
        if (rst_n==0) begin
            rd_addr <= 0; 
        end
        else if(add_rd_addr) begin
            if(end_rd_addr)
                rd_addr <= 0; 
            else
                rd_addr <= rd_addr+1 ;
       end
    end
    assign add_rd_addr = (state_c == READ) && ~avs_waitrequest;
    assign end_rd_addr = add_rd_addr  && rd_addr == `BURST_MAX-1;

//wr_finish     一帧数据全部写到SDRAM
    always  @(posedge clk or negedge rst_n)begin
        if(~rst_n)begin
            wr_finish <= 1'b0;
        end
        else if(~wr_finish & wfifo_q[17])begin  //写完  从wrfifo读出eop
            wr_finish <= 1'b1;
        end
        else if(wr_finish && end_rd_addr)begin  //读完
            wr_finish <= 1'b0;
        end
    end

//change_bank ;//切换bank 
    always  @(posedge clk or negedge rst_n)begin
        if(~rst_n)begin
            change_bank <= 1'b0;
        end
        else begin
            change_bank <= wr_finish && end_rd_addr;
        end
    end

/****************************************************************/

/*********************** wrfifo 写数据   ************************/
//控制像素数据帧 写入 或 丢帧

    always  @(posedge clk_in or negedge rst_n)begin
        if(~rst_n)begin
            wr_data_flag <= 1'b0;
        end 
        else if(~wr_data_flag & ~wr_finish_r[1] & din_sop)begin//可以向wrfifo写数据
            wr_data_flag <= 1'b1;
        end
        else if(/*wr_finish_r[1] && din_sop*/wr_data_flag & din_eop)begin//不可以向wrfifo写入数据
            wr_data_flag <= 1'b0;
        end
    end

    always  @(posedge clk_in or negedge rst_n)begin //把wr_finish从wrfifo的读侧同步到写侧
        if(~rst_n)begin
            wr_finish_r <= 0;
        end
        else begin
            wr_finish_r <= {wr_finish_r[0],wr_finish};
        end
    end

/****************************************************************/

    always  @(posedge clk_out or negedge rst_n)begin
        if(~rst_n)begin
            rd_data <= 0;
            rd_data_vld <= 1'b0;
        end
        else begin
            rd_data <= rfifo_q;
            rd_data_vld <= rfifo_rdreq;
        end
    end

wrfifo	wrfifo_inst (
	.aclr   (~rst_n     ),
	.data   (wfifo_data ),
	.rdclk  (clk        ),
	.rdreq  (wfifo_rdreq),
	.wrclk  (clk_in     ),
	.wrreq  (wfifo_wrreq),
	.q      (wfifo_q    ),
	.rdempty(wfifo_empty),
	.rdusedw(wfifo_usedw),
	.wrfull (wfifo_full )
	);

    assign wfifo_data = {din_eop,din_sop,din};
    assign wfifo_wrreq = ~wfifo_full & din_vld & ((~wr_finish_r[1] & din_sop) ||wr_data_flag);
    assign wfifo_rdreq = state_c == WRITE && ~avs_waitrequest;

rdfifo u_rdfifo(
	.aclr       (~rst_n     ),
	.data       (rfifo_data ),
	.rdclk      (clk_out    ),
	.rdreq      (rfifo_rdreq),
	.wrclk      (clk        ),
	.wrreq      (rfifo_wrreq),
	.q          (rfifo_q    ), 
	.rdempty    (rfifo_empty),
	.wrfull     (rfifo_full ),
	.wrusedw    (rfifo_usedw)
);

    assign rfifo_data = avs_rddata;
    assign rfifo_wrreq = ~rfifo_full & avs_rddata_vld;
    assign rfifo_rdreq = ~rfifo_empty & rdreq;

//输出
    assign dout       = rd_data;
    assign dout_vld   = rd_data_vld;
    assign avm_wrdata = wfifo_q[15:0];
    assign avm_write  = ~(state_c == WRITE && ~avs_waitrequest);
    assign avm_read   = ~(state_c == READ && ~avs_waitrequest);
    assign avm_addr   = (state_c == WRITE)?{wr_bank[1],wr_addr[21:9],wr_bank[0],wr_addr[8:0]}
                       :((state_c == READ)?{rd_bank[1],rd_addr[21:9],rd_bank[0],rd_addr[8:0]}
                       :0);

endmodule 

四、参考

基于FPGA的图像实时采集

五、源码

https://github.com/IvanXiang/FPGA_COMS_SDRAM_VGA

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

基于FPGA的图像边缘检测 的相关文章

  • 工具类里面调用service接口或者mapper接口

    我们在开发中经常会遇到需要将一些频繁进行的操作抽取封装到工具类中 xff0c springboot不支持注入静态属性 所以在工具类中使用 64 Autowired或者其他注解自动注入会失败 xff0c 才用如下方法这可以避免注入失败 spa
  • windows下停止【kill】nginx命令

    杀死nginx taskkill fi 34 imagename eq nginx EXE 34 f taskkill f t im nginx exe stop bat taskkill f t im nginx exe pause
  • 基本类型对应的缓冲池

    基本类型对应的缓冲池如下 xff1a boolean values true and false all byte values short values between 128 and 127 int values between 128
  • 记录JVM中Eden区、Survivor from区和Survivor to区及Minor GC和Major GC的理解

    仅做学习笔记 JVM中Eden区 Survivor from区和Survivor to区 本文主要根据 深入理解JVM 中内存回收策略 xff0c 主要关注如下五个方面 xff1a 1 xff1a Eden区分配 2 xff1a 大对象直接
  • ubuntu下修改python默认版本的方法

    Ubuntu安装之后会面临多个python版本共存的问题 xff08 python2和python3 xff09 xff0c 但是有时候安装其他库的时候会安装在默认的python版本环境下 xff08 比如 xff0c 通常默认版本是pyt
  • C++:C语言实现HTTP的GET和POST请求

    https www cnblogs com diligenceday p 6255788 html
  • Linux C/C++ UDP Socket 网络通信

    Python微信订餐小程序课程视频 https edu csdn net course detail 36074 Python实战量化交易理财系统 https edu csdn net course detail 35475 昨晚 Vv 让
  • Xcode工程创建多个target

    Xcode工程创建多个target 小菜本人有时候会在一个Xcode工程中新建多个包含main函数的 m文件用于用于学习Objective C xff0c 于是要用到target这个东西 target对应于一个可运行文件和一些编译配置 点击
  • JLINK简介

    一 什么是JLINK JLINK是一个兼容JTAG的仿真器 xff0c 作用是烧入程序和Debug 二 JLINK是如何处理数据的 xff1f 1 PC端应用程序将数据以某种协议格式 xff0c 通过USB接口发送给J Link 2 J L
  • 蓝桥杯单片机-DS1302时钟模块

    一 简介 1 采用SPI三线接口通信 xff08 SCK SDA RST xff09 上升沿数据被写入DS1302 xff0c 下降沿被读出 二 应用 1 在ds1302 c文件中定义三个数组 unsigned char code READ
  • 蓝桥杯单片机-定时器

    一 简介 有三个寄存器与定时器相关 xff08 TMOD xff0c TCON xff0c 数值设置寄存器TH TL xff09 1 定时器工作方式设置寄存器TMOD GATE 门控制位 GATE 61 0时 定时器 计数器启动与停止仅受T
  • 蓝桥杯单片机-NE555模块

    一 简介 1 NE555在开发板中用于输出频率可变 xff0c 占空比不变的方波 2 NE555是纯硬件的设计 xff0c 通过电位器RB3可改变其信号输出频率 不需要编程实现其功能 考点 xff1a 使用定时器的计数模式测量NE555输出
  • C语言学习笔记(基于单片机)

    目录 一 关键字部分 static code const extern bit sbit sft struct xff08 结构体 xff09 1 结构体的初始化 2 结构体的赋值 3 应用 data idata pdata xdata 与
  • 蓝桥杯单片机-赛前总结

    目录 一 省赛中开发平台涉及的模块 xff1a 1 IIC驱动 2 DS1302驱动 3 onewire驱动 4 定时器读取NE555频率 二 一些功能性操作 1 外部中断 2 矩阵按键 3 PWM输出 4 毫秒延时函数 三 需要注意的一些
  • 相互依赖的so库,在编译时如何解耦

    有时候 xff0c 我们写的程序 xff0c 会涉及到相互引用的问题 比如frameworks av media libstagefright下的这个libstagefright xff0c 被frameworks av media lib
  • boost库学习总结

    第一次使用boost库是因为网络编程 xff0c 由于时间比较紧 xff0c 没有时间每个库都学 xff0c 所以前期想找个专门的boost库网络教程 xff08 以前自己就用过socket写过 xff0c 但是为了跨平台 xff0c 而且
  • C51单片机判断点亮的是奇数位还是偶数位

    学单片机的时候想到一个问题 xff1a 如何判断单片机点亮的LED灯是奇数位还是偶数位 xff1f 在网上搜了一圈没找到 xff0c 于是打算自己写一个 单片机型号 xff1a AT89C52 xff0c LED为低电平有效接法 xff0c
  • Linux学习笔记——如何在交叉编译时使用共享库

    0 前言 在较为复杂的项目中会利用到交叉编译得到的共享库 xff08 so文件 xff09 在这种情况下便会产生以下疑问 xff0c 例如 xff1a 1 交叉编译时的共享库是否需要放置于目标板中 xff0c 如果需要放置在哪个目录中 2
  • 实例变量(instance var)与属性(@property)的关系

    实例变量 instance var 与属性 64 property 的关系 Objective C 2 0之后 xff0c 声明一个 64 property name自动产生一个实例变量 xff0c 名为 name xff0c 因此省去实例
  • VS+CUDA+Matlab环境配置经验 (达到用matlab使用nvcc进行gpu并行加速)

    前前后后配了一个多星期的环境 xff0c 终于完成了 xff0c 梳理一下我的经验给大家分享也留作以后参考 一 版本兼容性问题 一开始安装的时候我并不懂 xff0c 没有什么顺序和版本的概念 xff0c 所以各种组件不能相互支持 首先明确

随机推荐

  • 华为无线WiFi配置802.1x认证

    一 拓扑 xff1a 二 简介 xff1a 本篇主要介绍华为交换机设备配合Windows server 2019配置的802 1x 43 NPS协同做的有线网络认证 xff08 可跟做 xff09 现有的华为6605无线AC配置 xff1a
  • 寝室一伙计

    我们寝室一伙计 xff0c 昨天晚上睡觉的时候 xff0c 说梦话 xff0c 笑 xff0c 磨牙 xff0c 还有吃奶 xff0c 等等等等 xff0c 我服了
  • Qt学习笔记(五)重定向

    实时获取程序中qt所输出的信息 xff0c 并显示到QTextBrowser上 1 在main文件中添加以下内容 xx为你的界面类名 xx clk 61 NULL void myMessageOutput QtMsgType type co
  • 串口通信中接收数据时延迟处理与缓存处理的解决方案(C#)

    利用串口进行通信 xff0c 当发送方 xff08 A xff09 将数据写入串口后 xff0c 通过无线或有线方式将数据传送给接收方 xff08 B xff09 xff0c B通过调用串口读方法comm read 参数 即可将数据读出 原
  • robomaster电控究极学习教程(以哨兵为例)------一、串口dma和遥控器

    robomaster电控究极学习教程 xff08 以哨兵为例 xff09 一 串口dma和遥控器 文章目录 robomaster电控究极学习教程 xff08 以哨兵为例 xff09 一 串口dma和遥控器 一 串口DMA的作用二 步骤1 c
  • 无人机架构

    无人机架构 基本设计需求 xff0c 如 xff1a xff08 1 xff09 慎思规划和反应式行为 xff1b xff08 2 xff09 容许不确定性 xff1b xff08 3 xff09 考虑危险 xff1b xff08 4 xf
  • 第八课 C++中的__LINE__宏

    在C 43 43 编程中 xff0c 我们有时候需要知道当前源代码的行号 xff0c 这时候就可以使用 LINE 宏 本文将介绍如何使用 LINE 宏 xff0c 以及它的使用示例 LINE 宏简介 LINE 是C 43 43 中的一个预定
  • 介绍@dynamic的用法

    介绍 64 dynamic的用法 Objective C 2 0提供了属性 64 property xff0c 可以让编译器自动生成setter和getter方法 如果不想编译器自作主张生成这些setter和getter方法 xff0c 则
  • OkHttpUtils的使用

    OkHttpUtils是一个非常好的网络协议框架 xff0c 它是在OkHttp的基础上进行了二次封装 要使用这个类首先下载jar包 xff0c 如下 xff1a http download csdn net download xxdw19
  • 十进制整数转为十六进制整数(C++实现)

    一 代码功能 xff1a 输入一个十进制整数 xff0c 将其转化为十六进制整数并输出 二 源码 include lt iostream gt include lt cstring gt include lt cmath gt using
  • 我的四轴专用PID参数整定方法及原理---超长文慎入(转)

    给四轴调了好久的PID xff0c 总算是调好了 xff0c 现分享PID参数整定的心得给大家 xff0c 还请大家喷的时候手下留情 首先说明一下 xff0c 这篇文章的主旨并不是直接教你怎么调 xff0c 而是告诉你这么调有什么道理 xf
  • 简单的TCP客户端发包工具

    一 TCP介绍 先放这里有时间在写 xff0c 最近在写DuiLib相关的使用内容 xff0c 这部分大家凑活着看 二 程序截图 下载链接 链接 xff1a https pan baidu com s 1MzNUzwd7WwBat6vNMc
  • C++常用头文件汇总

    之前说过的头文件这就来了 1 首先是本人最喜欢也是最最方便的万能头文件 xff0c 顾名思义 xff0c 不管是天上飘的还是地下埋的 xff0c 只要不是不对的头文件它都包含 xff0c 除了本篇第14个头文件 xff1a include
  • 基于I2C/SPI的温湿度采集与OLED显示

    基于I2C SPI的温湿度采集与OLED显示 一 AHT20温湿度采集1 I2C2 温湿度采集代码效果 二 OLED显示1 显示学号姓名2 诗句显示 三 总结四 参考 一 AHT20温湿度采集 1 I2C 解释什么是 软件I2C 和 硬件I
  • 游戏客户端编程

    游戏客户端编程 1 代码实现服务器连接发送按钮 2 显示消息3 发送信息4 播放背景音乐5 变换游戏背景图片6 参考 1 代码实现 服务器连接 span class token keyword private span span class
  • 卷积神经网络实现表情识别

    卷积神经网络实现表情识别 CNN人脸表情识别图片预处理原本效果处理后效果 图片数据集效果 CNN人脸识别创建模型归一化与数据增强创建网络 摄像头人脸识别图片识别 参考 CNN人脸表情识别 图片预处理 span class token key
  • IIC协议及其工程【FPGA】

    IIC协议及其工程 FPGA 一 IIC协议1 IIC简介2 IIC中相关的术语1 应答信号 xff08 ACK xff09 2 无应答信号 xff08 NOACK xff09 3 虚写3 IIC的时序 二 EEPROM1 时钟频率2 起始
  • char *与char []的区别

    其实 xff0c 只要记住一点就能很好区分char 和char xff1a char 定义的是一个指向字符串的指针 xff08 注意 xff1a C语言中没有对应字符串的内置类型或者类类型 xff09 xff0c 而char 就是C语言中的
  • SPI协议读取FLASH【FPGA】

    SPI协议读取FLASH FPGA 一 SPI协议1 SPI简介2 SPI物理层3 SPI协议层CPOL CPHA 及通讯模式 4 SPI 基本通讯过程5 通讯的起始和停止信号6 数据有效性 二 Flash1 状态寄存器1 WIP xff0
  • 基于FPGA的图像边缘检测

    基于FPGA的图像边缘检测 一 图像处理算法1 灰度转换2 高斯滤波3 二值化4 Sobel 二 项目框架1 摄像头配置模块2 图像处理模块3 数据缓存模块4 其它模块 三 部分代码1 数据采集模块2 读写控制模块 四 参考五 源码 简介