全部版块 我的主页
论坛 数据科学与人工智能 人工智能 机器学习
78 0
2025-11-24

图像处理模块输入输出信号定义及处理流程

帧同步信号:

// ---------------------------------------------
// Frame and line housekeeping
// ---------------------------------------------
reg vs_frame_d0;
always @(posedge video_clk or posedge rst) begin
    if (rst) begin
        vs_frame_d0 <= 1'b0;
    end else begin
        vs_frame_d0 <= i_vs;
    end
end
wire frame_start = vs_frame_d0 & ~i_vs; // 场同步下降沿(一帧开始)

reg prev_de;
always @(posedge video_clk or posedge rst) begin
    if (rst) begin
        prev_de <= 1'b0;
    end else begin
        prev_de <= i_de;
    end
end
wire line_start = i_de & ~prev_de; // 数据有效信号上升沿(一行开始)
wire line_end   = ~i_de & prev_de; // 数据有效信号下降沿(一行结束)

reg [11:0] col_cnt; // 列计数器
reg [11:0] row_cnt; // 行计数器

i_vs
(场同步)和
i_de
(数据有效)信号进行边沿检测,生成
frame_start
(帧开始)和
line_start
(行开始)信号。使用计数器
col_cnt
row_cnt
跟踪当前像素的列和行位置。

输入输出信号定义

  • input                       video_clk,
        input                       rst,
        input                       i_hs,
        input                       i_vs,
        input                       i_de,
        input      [DATA_WIDTH-1:0] i_data,
        input                       sw_gray,
        input                       sw_filter,
        input                       sw_edge,
        input                       sw_dilate,
        // 新增按钮检测相关信号
        input                       btn_detect_en,     // 按钮检测使能
        output reg                  btn_pressed,       // 按钮按下状态
        output reg                  detection_active,  // 检测进行中状态
        output reg [11:0]           btn_pixel_count,   // 按钮区域内像素计数
        output                      o_hs,
        output                      o_vs,
        output                      o_de,
        output reg [DATA_WIDTH-1:0] o_data
  • DATA_WIDTH
    :输入视频数据宽度(24 位 RGB)。
  • H_ACTIVE
    :视频水平有效像素数。
  • THRESHOLD
    :二值化阈值。
  • BTN_*
    :按钮检测区域的坐标参数。
  • video_clk
    :视频像素时钟。
  • rst
    :全局复位。
  • i_hs/i_vs/i_de
    :输入视频的行同步、场同步和数据有效信号。
  • i_data
    :输入的 24 位 RGB 像素数据。
  • sw_*
    :功能选择开关(灰度、腐蚀、边缘检测、膨胀)。
  • btn_detect_en
    :按钮检测使能信号。
  • btn_pressed
    :按钮按下状态输出。
  • o_hs/o_vs/o_de/o_data
    :处理后的视频输出信号。

灰度转换

// ---------------------------------------------
// RGB -> Grayscale conversion for image processing
// ---------------------------------------------
wire [7:0]  r_comp = i_data[23:16];
wire [7:0]  g_comp = i_data[15:8];
wire [7:0]  b_comp = i_data[7:0];
wire [17:0] gray_sum = (r_comp * 77) + (g_comp * 150) + (b_comp * 29);
wire [7:0] gray_value = (gray_sum + 128) >> 8; // 灰度值(标准ITU-R 601转换公式)

将 24 位 RGB 像素转换为 8 位灰度值。转换公式:

Y = 0.299*R + 0.587*G + 0.114*B
,为了避免浮点数运算,使用整数乘法实现(77=299/4, 150=587/4, 29=114/4)。结果右移 8 位(除以 256)并加上 128 进行四舍五入。

二值化处理

// ---------------------------------------------
// 二值化处理
// ---------------------------------------------
wire binary_pixel = (gray_value > THRESHOLD) ? 1'b1 : 1'b0;

将灰度值转换为二值图像(1 表示白色,0 表示黑色)。阈值由参数

THRESHOLD
设定(默认 128)。

行延迟

// ------------------------------------------------------------- //
// Single-line delay for streaming video data
// ------------------------------------------------------------- //
module line_delay
#(
    parameter DATA_WIDTH = 8,
    parameter LINE_LENGTH = 1024
)
(
    input                     clk,
    input                     rst,
    input                     frame_start,
    input                     enable,
    input      [DATA_WIDTH-1:0] din,
    output reg [DATA_WIDTH-1:0] dout,
    output reg                valid
);

reg [DATA_WIDTH-1:0] buffer [0:LINE_LENGTH-1]; // 行缓冲
reg [ADDR_WIDTH-1:0] addr; // 地址计数器
reg filled; // 缓冲填满标志

always @(posedge clk or posedge rst) begin
    if (rst) begin
        addr   <= 0;
        filled <= 1'b0;
        valid  <= 1'b0;
    end else begin
        if (frame_start) begin
            addr   <= 0;
            filled <= 1'b0;
            valid  <= 1'b0;
        end
        if (enable) begin
            dout <= buffer[addr]; // 输出延迟一行的数据
            buffer[addr] <= din;  // 写入当前数据
            addr <= addr + 1;
            if (addr == LINE_LAST) begin
                filled <= 1'b1; // 第一行写入完成后,后续输出有效
            end
            valid <= filled; // 缓冲填满后,输出有效
        end else begin
            valid <= 1'b0;
        end
    end
end
endmodule

实现一行像素的延迟,用于构建 3x3 窗口(需要当前行、上一行和上上行的数据)。使用一个寄存器数组

buffer
存储一行像素。
enable
信号由
i_de
控制,只有在数据有效时才写入 / 读出。

valid
信号表示输出数据是否有效(前两行数据无效,从第三行开始有效)。应用:在
image_processing
模块中被实例化两次,分别用于存储二值图像和灰度图像的行数据。

腐蚀

// ---------------------------------------------
// Erosion algorithm for binary image
// ---------------------------------------------
wire erosion_binary;

assign erosion_binary = r0c0_bin & r0c1_bin & r0c2_bin &
                       r1c0_bin & r1c1_bin & r1c2_bin &
                       r2c0_bin & r2c1_bin & r2c2_bin;

wire [7:0] erosion_value = erosion_binary ? 8'hFF : 8'h00;

对二值图像进行腐蚀操作,用于消除小的白色噪点。原理:3x3 窗口内所有像素都为 1 时,输出才为 1,否则为 0。结果是使白色区域收缩。

膨胀

// ---------------------------------------------
// Dilation algorithm for binary image
// ---------------------------------------------
wire dilation_binary;

wire row0_or = r0c0_bin | r0c1_bin | r0c2_bin;
wire row1_or = r1c0_bin | r1c1_bin | r1c2_bin;
wire row2_or = r2c0_bin | r2c1_bin | r2c2_bin;

assign dilation_binary = row0_or | row1_or | row2_or;

wire [7:0] dilation_value = dilation_binary ? 8'hFF : 8'h00;

对二值图像进行膨胀操作,用于填补白色区域的空洞。原理:3x3 窗口内任意一个像素为 1 时,输出就为 1。结果是使白色区域扩张。

边缘检测

// ---------------------------------------------
// Sobel edge detection (使用灰度数据)
// ---------------------------------------------
// 计算 Sobel 算子的 Gx 和 Gy
wire signed [11:0] sobel_gx = (r0c2_s + (r1c2_s <<< 1) + r2c2_s) -
                              (r0c0_s + (r1c0_s <<< 1) + r2c0_s);
wire signed [11:0] sobel_gy = (r2c0_s + (r2c1_s <<< 1) + r2c2_s) -
                              (r0c0_s + (r0c1_s <<< 1) + r0c2_s);

// 计算梯度绝对值之和
wire [11:0] abs_gx = (sobel_gx < 0) ? -sobel_gx : sobel_gx;
wire [11:0] abs_gy = (sobel_gy < 0) ? -sobel_gy : sobel_gy;
wire [12:0] edge_sum = abs_gx + abs_gy;

// 边缘强度阈值判断
wire [7:0] edge_value = (edge_sum > 255) ? 8'hFF : edge_sum[7:0];

对灰度图像进行边缘检测,找出图像中的轮廓。原理:使用 Sobel 算子计算水平(Gx)和垂直(Gy)方向的梯度,然后求梯度的绝对值之和。如果梯度和超过 255,则输出白色(边缘),否则输出对应的灰度值。

输出检测

// ---------------------------------------------
// 结果选择与输出
// ---------------------------------------------
always @* begin
    mux_data = color_rgb; // 默认输出原始彩色图像
    mux_de   = color_de;
    
    if (btn_detect_en) begin
        mux_data = btn_highlight_rgb; // 按钮检测模式下高亮显示按钮区域
        mux_de   = btn_highlight_de;
    end else if (sw_edge) begin
        mux_data = edge_rgb; // 边缘检测结果
        mux_de   = edge_de;
    end else if (sw_dilate) begin
        mux_data = dilation_rgb; // 膨胀结果
        mux_de   = dilation_de;
    end else if (sw_filter) begin
        mux_data = erosion_rgb; // 腐蚀结果
        mux_de   = erosion_de;
    end else if (sw_gray) begin
        mux_data = gray_rgb; // 灰度图像
        mux_de   = gray_de;
    end
end

// 输出同步
always @(posedge video_clk or posedge rst) begin
    if (rst) begin
        o_data <= 0;
        o_de_r <= 1'b0;
    end else begin
        o_data <= mux_data;
        o_de_r <= mux_de;
    end
end

assign o_hs = hs_d0; // 行同步延迟一拍(与数据对齐)
assign o_vs = vs_d0; // 场同步延迟一拍
assign o_de = o_de_r;

根据开关信号(

sw_*
)和按钮检测使能(
btn_detect_en
)选择不同的处理结果输出。优先级:按钮检测 > 边缘检测 > 膨胀 > 腐蚀 > 灰度 > 原始彩色。

为了保证输出的同步性,对行同步(

hs_d0
)和场同步(
vs_d0
)信号进行了一拍延迟,确保它们与处理后的数据对齐。

二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

相关推荐
栏目导航
热门文章
推荐文章

说点什么

分享

扫码加好友,拉您进群
各岗位、行业、专业交流群