3. 图像二值化阈值处理的FPGA实现
任务与实现范围
本模块对 8 位灰度视频流做实时二值化:像素值 ≥ 阈值输出 255,否则输出 0。阈值由外部输入 thresh 提供,可通过按键或串口在运行时修改。模块采用流水线寄存器输出,保证每拍一个像素的吞吐,适配视频时序。
核心代码(Verilog)
module binarize #(
parameter WIDTH = 8
)(
input wire clk,
input wire rst_n,
input wire de, // 数据有效
input wire [WIDTH-1:0] gray, // 灰度输入
input wire [WIDTH-1:0] thresh, // 可配置阈值
output reg de_out,
output reg [WIDTH-1:0] bin_out // 0 或 255
);
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
de_out <= 1'b0;
bin_out <= {WIDTH{1'b0}};
end else begin
de_out <= de;
bin_out <= (gray >= thresh) ? {WIDTH{1'b1}} : {WIDTH{1'b0}};
end
end
endmodule
阈值动态调整(按键/串口接入)
阈值寄存器在视频时钟域外更新,写入后下一帧生效。下面给出按键步进与串口单字节写入两种最小接入方式,二者共用同一阈值寄存器。
module thresh_ctrl (
input wire clk,
input wire rst_n,
input wire key_inc, // 按键:阈值 +8
input wire key_dec, // 按键:阈值 -8
input wire uart_valid, // 串口收到 1 字节
input wire [7:0] uart_data, // 串口数据即新阈值
output reg [7:0] thresh
);
always @(posedge clk or negedge rst_n) begin
if (!rst_n)
thresh <= 8'd128; // 默认阈值
else if (uart_valid)
thresh <= uart_data; // 串口直接设定
else if (key_inc)
thresh <= (thresh > 8'd247) ? 8'd255 : thresh + 8'd8;
else if (key_dec)
thresh <= (thresh < 8'd8) ? 8'd0 : thresh - 8'd8;
end
endmodule
顶层连接与运行
// 视频像素时钟域
binarize u_bin (
.clk(clk_pix), .rst_n(rst_n),
.de(de_in), .gray(gray_in),
.thresh(thresh),
.de_out(de_out), .bin_out(bin_out)
);
// 阈值控制(可用同一 clk_pix 或系统时钟,跨域时加同步)
thresh_ctrl u_thr (
.clk(clk_pix), .rst_n(rst_n),
.key_inc(key_inc), .key_dec(key_dec),
.uart_valid(uart_valid), .uart_data(uart_data),
.thresh(thresh)
);
运行方式:将 bin_out 与 de_out 接入 VGA/HDMI 显示通路,灰度源接摄像头或测试图。按键每按一次阈值变化 8;串口发送单字节(如 0x40=64)即设为该值。综合工具用 Vivado/Quartus 均可,无特殊 IP。
验证方法与通过条件
- 仿真:给
gray依次输入 0、100、200,thresh=128,检查bin_out应为 0、0、255,且de_out比de延迟 1 拍。 - 上板:显示画面应呈黑白两色;按
key_inc白色区域增大,按key_dec白色区域减小;串口写入新阈值后画面立即按新阈值分割。 - 通过条件:输出仅含 0/255,阈值改变时分割边界随之移动,且无像素丢失(
de_out与de计数一致)。
数据流示意
按键或串口更新阈值寄存器,比较器每拍将灰度与阈值比较,输出二值像素,实现实时分割。