图像预处理算法—灰度化处理

文摘   2024-10-18 18:15   四川  

图像预处理算法适合在FPGA上完成,原理简单且需要快速处理,通常有灰度化、中值、均值滤波等,以及颜色空间转换算法。

灰度图像是一种特殊的彩色图像(R=G=B的彩色图像) 只有一种颜色分量,单通道的0-255

方法:一般有分量法、最大值法、平均值法、加权平均法四种方法对彩色图像进行灰度化。

一:最大值法

将彩色图像中的三分量亮度 R  G  的最大值作为灰度图的灰度值。具体表达式如下。

                                           

                                             gray(i, j) = max[𝑅(𝑖,𝑗),𝐺(𝑖,𝑗),𝐵(𝑖,𝑗)]

二:平均值法

1.原理

将彩色图像中的三分量亮度求平均得到一个灰度值。如下 

                             gray(i, j) = { 𝑅(𝑖,𝑗) + 𝐺(𝑖,𝑗) + 𝐵(𝑖,𝑗) }  / 3

上式中有除法,考虑到在 FPGA 中实现除法比较的消耗资源(除法就可以使用 移位的方式 实现),这里在实现前可以先做如下的近似处理:

 除以256可以看作是向右移8位,同样,512,1024,2048等2的n次都可以

2.verilog实现

分析:只有加法乘法以及移位操作

module rgb2gray

(
input clk, //时钟
input reset_p, //复位
input rgb_valid, //rgb输入有效标识
input rgb_hs, //rgb输入行信号
input rgb_vs, //rgb输入场信号
input [7:0] red_8b_i, //R输入
input [7:0] green_8b_i, //G输入
input [7:0] blue_8b_i, //B输入

output [7:0] gray_8b_o, //GRAY输出
output reg gray_valid, //gray输出有效标识
output reg gray_hs, //gray输出行信号
output reg gray_vs //gray输出场信号
);

//求平均法GRAY = (R+B+G)/3=((R+B+G)*85)>>8 =((R+B+G)*(64+16+4+1))>>8

=(R+B+G)*64+(R+B+G)*16+(R+B+G)*4+(R+B+G) >>8

(sum << 6)+(sum << 4)+(sum << 2)+ sum >>8

  wire [9:0]sum;
reg [15:0]gray_r;

assign sum = red_8b_i + green_8b_i + blue_8b_i;

always@(posedge clk or posedge reset_p)
begin
if(reset_p)
gray_r <= 16'd0;
else if(rgb_valid)
gray_r <= (sum << 6)+(sum << 4)+(sum << 2)+ sum;
else
gray_r <= 16'd0;
end
 assign gray_8b_o = gray_r[15:8];   //>>8右移8位

always@(posedge clk)
begin
gray_valid <= rgb_valid;
gray_hs <= rgb_hs;
gray_vs <= rgb_vs;
end

避免除法做近似处理计算的 gray 和 直接通过除法求的平均值  是稍存在偏差的。这个是可以接收的误差范围。

三,加权平均 RGB--Ycbcr

1.基本原理

Y'为颜色的亮度(luma)分量、而CB和CR则为蓝色和红色的浓度偏移量成份。常见的3 个基本色彩模型是RGB,CMYK和YUV。YCbCr是YUV经过缩放和偏移的翻版,JPEG、MPEG均采用此格式。主要的子采样格式有 YCbCr 4:2:0、YCbCr 4:2:2 和 YCbCr 4:4:4。

RGB888 转 YCbCr 的公式,

Y=0.299R+0.587G+0.114B

Cb= 0.568(B-Y)+128=-0.172R-0.339G+0.511B+128 

Cr=0.713(R-Y)+128=0.511R-0.428G-0.083B+128

效果如下:

由结果可以看到,相比 RGB 分量转灰度图来说,YCbCr 取 Y 分量的灰度图更具有层次感,和原图片更为接近。

 

将三个分量以不同的权值进行加权平均:

gray(i, j) = 0.299 ∗ 𝑅(𝑖,𝑗) + 0.587 ∗ 𝐺(𝑖,𝑗) + 0.114 ∗ 𝐵(𝑖,𝑗)

在实际应用时,为了能避免低速的浮点运算以及除法运算,先将式子缩放 1024 倍来实现运算算法,如下:

gray(i, j) = [0.299 ∗ 𝑅(𝑖,𝑗) + 0.587 ∗ 𝐺(𝑖,𝑗) + 0.114 ∗ 𝐵(𝑖,𝑗)] ∗ 1024/1024

近似取整处理后:

gray(i, j) ≈ [306 ∗ 𝑅(𝑖,𝑗) + 601 ∗ 𝐺(𝑖,𝑗) + 117 ∗ 𝐵(𝑖,𝑗)]/1024

除以1024使用向右移10位:

gray(i, j) ≈ [306 ∗ 𝑅(𝑖,𝑗) + 601 ∗ 𝐺(𝑖,𝑗) + 117 ∗ 𝐵(𝑖,𝑗)] ≫ 10

也可以压缩到 位以内,式子变为如下。具体压缩到多少位可以根据实际需求:

gray(i, j) = [77 ∗ 𝑅(𝑖,𝑗) + 150 ∗ 𝐺(𝑖,𝑗) + 29 ∗ 𝐵(𝑖,𝑗)] ≫ 8

2.代码实现

1)公式计算法实现:

首先将RGB565转RGB888形式:

 rgb2gray
#(
.PROC_METHOD ( "FORMULA" )//"AVERAGE" :求平均法
//or "FORMULA" :直接公式法
//or "LUT" :查找表法
)rgb2gray
(
.clk (loc_clk50m )
,//input
.reset_p (g_rst_p ),//input
.rgb_valid (image_data_valid ),//input
.rgb_hs (image_data_hs ),//input
.rgb_vs (image_data_vs ),//input

.red_8b_i ({image_data[15:11],3'b000}),//input R[7:0]
.green_8b_i ({image_data[10:5],2'b00} ),//input G[7:0]
.blue_8b_i ({image_data[4:0],3'b000} ),//input B[7:0]

.gray_8b_o (image_gray_data ),//output [7:0]
.gray_valid (image_gray_data_valid ),//output reg
.gray_hs ( ),//output reg
.gray_vs ( ) //output reg
);
    wire [15:0]red_x77;
wire [15:0]green_x150;
wire [15:0]blue_x29;
reg [15:0]sum;

//乘法转换成移位相加方式
assign red_x77 = (red_8b_i << 6) + (red_8b_i << 3) + (red_8b_i << 2) + red_8b_i;
assign green_x150 = (green_8b_i<< 7) + (green_8b_i<< 4) + (green_8b_i<< 2) + (green_8b_i<<1);
assign blue_x29 = (blue_8b_i << 4) + (blue_8b_i << 3) + (blue_8b_i << 2) + blue_8b_i;

always@(posedge clk or posedge reset_p)
begin
if(reset_p)
sum <= 16'd0;
else if(rgb_valid)
sum <= red_x77 + green_x150 + blue_x29;
else
sum <= 16'd0;
end

//提取Y亮度为灰度输出
assign gray_8b_o = sum[15:8];

//打拍计算
always@(posedge clk)
begin
gray_valid <= rgb_valid;
gray_hs <= rgb_hs;
gray_vs <= rgb_vs;
end
进行打拍计算,在图像处理时,我们是有数据的同步信号的,有的是数据使能信号,有的还有行同步信号和帧同步信号。经过图像处理后的数据延迟了拍数,这些同步信号也要相应的打拍,否则最终的图像显示会出问题。
Y,Cb,Cr分量都获取的代码实现办法:
module rgb2gray
(
input clk, //时钟
input reset_p, //复位

input rgb_valid, //rgb输入有效标识
input rgb_hs, //rgb输入行信号
input rgb_vs, //rgb输入场信号
input [7:0] red_8b_i, //R输入
input [7:0] green_8b_i, //G输入
input [7:0] blue_8b_i, //B输入

output reg [7:0] gray_8b_o, //GRAY输出
output gray_valid, //gray输出有效标识
output gray_hs, //gray输出行信号
output gray_vs //gray输出场信号
);
//典型灰度转换公式Gray = R*0.299+G*0.587+B*0.114=(R*77 + G*150 + B*29) >>8
// Y = 0.299*R + 0.587*G + 0.114*B
// Cb = 0.586*
(B-Y) + 128 = -0.172*R - 0.339*G + 0.511*B + 128
// Cr = 0.713*
(R-Y) + 128 = 0.511*R - 0.428*G - 0.083*B + 128
// --->
// Y = ( 77*
R + 150*G + 29*B) >> 8
// Cb = (-43*R - 85*G + 128*B) >> 8 + 128
// Cr = (128*
R - 107*G - 21*B) >> 8 + 128
// --->
// Y = ( 77*R + 150*G + 29*B) >> 8
// Cb = (-43*
R - 85*G + 128*B + 32768) >> 8
// Cr = (128*R - 107*G - 21*B + 32768) >> 8
    reg  [15:0] R1;
reg [15:0] R2;
reg [15:0] R3;
reg [15:0] G1;
reg [15:0] G2;
reg [15:0] G3;
reg [15:0] B1;
reg [15:0] B2;
reg [15:0] B3;
reg [15:0] Y1;
reg [15:0] Cb1;
reg [15:0] Cr1;
reg [7:0] Y2,Cb2,Cr2;
reg [3:0] rgb_valid_r; //rgb输入有效标识
reg [3:0] rgb_hs_r; //rgb输入行信号
reg [3:0] rgb_vs_r; //rgb输入场信号
提取三种分量的RGB值,并且进行相加得到
    always@(posedge clk or negedge reset_p) begin
if (reset_p) begin
{R1,G1,B1} <= {16'd0,16'd0,16'd0};
{R2,G2,B2} <= {16'd0,16'd0,16'd0};
{R3,G3,B3} <= {16'd0,16'd0,16'd0};
end
else begin
{R1,G1,B1} <= {{red_8b_i * 16'd77},{green_8b_i * 16'd150},{blue_8b_i * 16'd29}};
{R2,G2,B2} <= {{red_8b_i * 16'd43},{green_8b_i * 16'd85},{blue_8b_i * 16'd128}};
{R3,G3,B3} <= {{red_8b_i * 16'd128},{green_8b_i * 16'd107},{blue_8b_i * 16'd21}};
end
end

always@(posedge clk or negedge reset_p) begin
if (reset_p) begin
Y1 <= 16'd0;
Cb1 <= 16'd0;
Cr1 <= 16'd0;
end
else begin
Y1 <= R1+G1+B1;
Cb1 <= B2 - R2 - G2 + 16'd32768;//128扩大256倍
Cr1 <= R3 - G3 - B3 + 16'd32768; //128扩大256倍
end
end

//右移8位得到
always@(posedge clk or negedge reset_p) begin
if (reset_p) begin
Y2 <= 8'd0;
Cb2 <= 8'd0;
Cr2 <= 8'd0;
end
else begin
Y2 <= Y1[15:8];
Cb2 <= Cb1[15:8];
Cr2 <= Cr1[15:8];
end
end

最终输出Y分量为灰度:
assign gray_8b_o = Y2;
在HDMI显示屏上进行显示灰度处理实现的效果:

也可以只提取77 < Cb < 127,133 < Cr < 173输出值为8'hFF,也就是说将该范围内的图像标记出来。即肤色提取:

    always@(posedge clk or negedge reset_p) begin
if (reset_p)
gray_8b_o <= 8'h0;
else if ( (Cb2 > 77) && (Cb2 < 127) && (Cr2 > 133) && (Cr2 < 173))
gray_8b_o <= 8'hFF;
else
gray_8b_o <= 8'h0;
end
在HDMI显示屏上进行显示肤色提取实现的效果:

 可以发现,它的椒盐噪声太多,需要进行滤波处理来减少椒盐噪声。

2)查找表法:
采用查找表方法实现,主要的优势是直接通过 访问 ROM 内的数据,相对使用移位相加实现乘法使用的 LUT 资源会少点,但占用的存储器会更多。

需要将 R  G  乘以系数之后的数值存储在 ROM 中,然后通过读取 ROM 方式来得到计算之后的数值。使用 Vivado 添加 3 个 ROM IP 核,分别通过 R*75、G*147、B*36(0≤R≤255,0≤G≤255,0≤B≤255)的计算值建立 3 个初始化 coe 文件.

    rom_red_x77 rom_red_x77(
.clka (clk ), // input wire clka
.ena (rgb_valid ), // input wire ena
.addra (red_8b_i ), // input wire [7 : 0] addra
.douta (red_x77 ) // output wire [14 : 0] douta
);

rom_green_x150 rom_green_x150(
.clka (clk ), // input wire clka
.ena (rgb_valid ), // input wire ena
.addra (green_8b_i ), // input wire [7 : 0] addra
.douta (green_x150 ) // output wire [15 : 0] douta
);

rom_blue_x29 rom_blue_x29(
.clka (clk ), // input wire clka
.ena (rgb_valid ), // input wire ena
.addra (blue_8b_i ), // input wire [7 : 0] addra
.douta (blue_x29 ) // output wire [13 : 0] douta
);
    always@(posedge clk or posedge reset_p)
begin
if(reset_p)
sum <= 16'd0;
else if(rgb_valid_dly1)
sum <= red_x77 + green_x150 + blue_x29;
else
sum <= 16'd0;
end

assign gray_8b_o = sum[15:8];
    always@(posedge clk)
begin
rgb_valid_dly1 <= rgb_valid;
rgb_hs_dly1 <= rgb_hs;
rgb_vs_dly1 <= rgb_vs;
end
    always@(posedge clk)
begin
gray_valid <= rgb_valid_dly1;
gray_hs <= rgb_hs_dly1;
gray_vs <= rgb_vs_dly1;
end

如果能将多种实现方法的.v 文件整合到一个模块保存在一个 .v 文件,使用起来就更加的方便。

整合方法1: 宏定义法

通过不同的宏定义条件编译方式进行选择某种实现方式

//`define AVERAGE //求平均法
//`define FORMULA //直接公式法
`define LUT //查找表法
module rgb2gray (
clk,
rst_n,
rgb_valid,
red_8b_i,
green_8b_i,
blue_8b_i,
gray_8b_o,
gray_valid
);
`ifdef AVERAGE //求平均法 GRAY=(R+B+G)/3=((R+B+G)*85)>>8
...//方法 1
`endif
`ifdef FORMULA //灰度转换公式 Gray = R*0.299+G*0.587+B*0.114
...//方法 2
`endif
`ifdef LUT//查找表方式
...//方法 3
`endif
endmodule

整合方法2: 使用 generate -if 方法

添加三种方法名称的定义

module rgb2gray
#(
parameter PROC_METHOD = "AVERAGE" //"AVERAGE" :求平均法
//or "FORMULA" :直接公式法
//or "LUT" :查找表法
)
(
clk,
rst_n,
rgb_valid,
red_8b_i,
green_8b_i,
blue_8b_i,
gray_8b_o,
gray_valid
);
generate
if (PROC_METHOD == "AVERAGE") begin: PROC_AVERAGE
//---------------------------------------------
//求平均法 GRAY = (R+B+G)/3=((R+B+G)*85)>>8
//方法 1
//---------------------------------------------
end
else if (PROC_METHOD == "FORMULA") begin: PROC_FORMULA
//---------------------------------------------
//典型灰度转换公式 Gray = R*0.299+G*0.587+B*0.114=(R*77 + G*150 + B*29) >>8
//方法 2
//---------------------------------------------
end
else if(PROC_METHOD == "LUT") begin: PROC_LUT
//---------------------------------------------
//查找表方式,可以省去公式法中乘法运算 Gray =(R*77 + G*150 + B*29) >>8,将 3 个分量
乘以系数后的数值存储在 ROM 中
//方法 3
//---------------------------------------------
end
endgenerate
endmodule

以上两种方法直接在例化模块时就可通过 重定义参数 PROC_METHOD 实现不同方法的设置,例化:

 rgb2gray
#(
.PROC_METHOD("FORMULA") //"AVERAGE" :求平均法
//or "FORMULA" :直接公式法
//or "LUT" :查找表法
)
rgb2gray_average
 (
.clk (clk ),
. reset_p (reset_p ),
.rgb_valid (rgb_valid ),
.red_8b_i (red_8b_i ),
.green_8b_i(green_8b_i),
.blue_8b_i (blue_8b_i ),
.gray_8b_o (gray_8b_o ),
.gray_valid(gray_valid)
);

景芯SoC v4.0芯片全流程实战


终身辅导、一对一辅导是景芯SoC训练营的特色!

手把手教您搭建SoC,从入门到进阶,带您掌握架构、算法、设计、验证、DFT、后端全流程低功耗!直播视频不定期升级!让您快速超越同龄人!

报名微信:13541390811


景芯全流程课程如下:

  • 景芯SoC设计  视频+文档+实战+一对一终身辅导(视频免费无期限)

  • 景芯SoC验证  视频+文档+实战+一对一终身辅导视频免费无期限

  • 景芯SoC中端  视频+文档+实战+一对一终身辅导视频免费无期限

  • 景芯SoC后端  视频+文档+实战+一对一终身辅导视频免费无期限


进阶课程:

  • 12nm 2.5GHz A72 低功耗DVFS实战培训(价格不到同行1/2)

  • DDR4/3项目实战培训(价格不到同行1/2)



小编逐步将教程、芯片设计全流程知识公布在知识星球,包括设计、验证、DFT、后端全流程知识以及大量技术文档,如果你和我一样渴求知识,不惧怕全流程的知识爆炸,那么欢迎您加入讨论学习,共同进步!



景芯主营业务是design service+一对一芯片辅导培训!


另外小编团队提供芯片Design Service,设计服务包括:

  • 提供SoC、MCU、ISP、CIS等芯片设计、验证、DFT设计服务

  • 提供DDR/PCIE/MIPI/CAN/USB/ETH/QSPI/UART/I2C等IP设计

  • 提供7nm、12nm、28nm、40nm、55nm、65nm、90nm等后端设计

  • 提供高校、企业定制化芯片设计服务、设计培训业务


景芯SoC v4.0芯片全流程实战训练营的宗旨:

手把手教您掌握SoC算法、设计、验证、DFT、后端全流程低功耗!


景芯SoCv3.0,是一款用于【芯片全流程实战培训】的低功耗多媒体SoC!

景芯SoC系统分为三个层次的功耗管理,并集成低功耗RISC-V处理器,集成ITCM SRAM、DTCM SRAM,集成MIPI、ISP、USB、QSPI、UART、I2C、GPIO等IP,采用SMIC40工艺流片。



(一)SoC设计课程,您将学会
  • 高速接口的Verilog设计实现
  • 从图像算法到RTL设计实现
  • MIPI、ISP的Verilog实现与仿真
  • Lint、CDC检查及UVM验证
  • SoC子系统的C驱动仿真
  • 后仿真
仅设计一门课程内容就抵得上其他培训机构的5-6门课程,价格仅其1/6

(二)SoC验证课程,您将学会
  • SoC子系统级的UVM环境搭建
  • SoC子系统级的UVC环境搭建
  • SoC子系统级的VIP环境搭建
  • SoC子系统的DMA SRAM UVM联合验证
  • SoC子系统的UART UVC验证
  • SoC子系统的长包、短包、超长包、毛刺包、包头/包尾错误UVM验证

仅验证一门课程内容就抵得上其他培训机构的3-4门课程,价格仅其1/6


(三)SoC中端课程,您将学会
  • DFT设计(芯片级)
  • Synthesis逻辑综合(芯片级)
  • 低功耗UPF设计、CLP技术
  • formal验证等技术

仅中端一门课程内容就抵得上其他培训机构的4-5门课程价格仅其1/6

(四)SoC后课程,您将学会

  • 低功耗设计

  • 布局布线(低功耗FF flow)
  • StarRC/QRC
  • STA/Tempus
  • 功耗分析
  • DRC/LVS设计

仅后端一门课程内容就抵得上其他培训机构的3-4门课程,价格仅其1/6



课程提供服务器供大家实践!带你从算法、前端、DFT到后端全流程参与SoC项目设计。请联系号主报名!联系微信:135-4139-0811

景芯SoC训练营图像处理的数据通路:



一键式完成C代码编译、仿真、综合、DFT插入、形式验证、布局布线、寄生参数抽取、STA分析、DRC/LVS、后仿真、形式验证、功耗分析等全流程。升级后的芯片设计工程V4.0 flow如下:


SoC一键式执行flow



MIPI DPHY+CSI2解码


数字电路中经典设计:多条通信数据Lane Merging设计实现

数字电路中经典设计:多条通信数据Lane Distribution实现




景芯SoC验证架构


景芯SoC全芯片验证架构:


景芯资深老学员告诉我,留学X国的硕士去外企某芯片巨头薪资是20万+美金!折合RMB超过140万,才25岁左右的小伙子!薪资超140万!


小编去看了glassdoor的工资:

1-3经经验的ASIC Engineer的工资报价有212K美刀,20万美刀。

7-9年经验的ASIC Engineer的工资报价有311K美刀,30万美刀。

当然具体薪资也是看每个候选人的水平以及岗位匹配度。

学历、项目经验都是非常重要的,期待着景芯战友们的更多捷报!走出国门,世界更精彩!景芯SoC项目的正能量之大,小编自己都很震撼,小编一定持续打磨,让景芯战友们一起成功!


景芯SoC UPF低功耗设计

全芯片UPF低功耗设计(含DFT设计)


景芯SoC训练营培训项目,低功耗设计前,功耗为27.9mW。

低功耗设计后,功耗为0.285mW,功耗降低98.9%!



电压降检查:


低功耗检查:


芯片的版图设计V1.0


芯片的版图设计V2.0


芯片的版图设计V4.0


低功耗设计的DRC/LVS,芯片顶层的LVS实践价值极高,具有挑战性!业界独一无二的经验分享。




ISP图像处理

  •    dpc - 坏点校正


  •    blc - 黑电平校正 


  •    bnr - 拜耳降噪

  •    dgain - 数字增益 

  •    demosaic - 去马赛克


  •    wb - 白平衡增益 

  •    ccm - 色彩校正矩阵 

  •    csc - 色彩空间转换 (基于整数优化的RGB2YUV转换公式)

  •    gamma - Gamma校正 (对亮度基于查表的Gamma校正)

  •    ee - 边缘增强


  •    stat_ae - 自动曝光统计 

  •    stat_awb - 自动白平衡统计


CNN图像识别


支持手写数字的AI识别:

仿真结果:仿真识别上图7、2、1、0、4、1、4、9



景芯SoC 3.0 ISP:



景芯SoC V3.0 DFT方案:




如果您和小编一样渴求进步,想掌握芯片设计全流程,欢迎加入小编知识星球,疯狂成长,一起进步!早日成为芯片大佬!


景芯学员们,小编十分感谢你们对景芯的肯定、信任和支持,你们的鼓励让小编十分感激,小编一定更努力精心打磨景芯SoC实战课,我承诺,一定要做到零差评,让大家无论资深还是资浅都能从景芯训练营获得成长!




以上就是今天分享的内容,如果您和小编一样渴求进步,想掌握芯片设计全流程,欢迎加入小编知识星球,疯狂成长,一起进步!早日成为芯片大佬!


景芯SoC V3.0课程提供服务器供大家实践!手把手教您学会SoC的算法、前端、DFT、后端全流程实战。


请联系号主报名!联系微信:135-4139-0811


景芯SoC训练营图像处理的数据通路:

景芯SoC的CRG设计:


一键式完成C代码编译、仿真、综合、DFT插入、形式验证、布局布线、寄生参数抽取、STA分析、DRC/LVS、后仿真、形式验证、功耗分析等全流程。升级后的芯片设计工程V2.0 flow如下:


SoC一键式执行flow



MIPI DPHY+CSI2解码


数字电路中经典设计:多条通信数据Lane Merging设计实现

数字电路中经典设计:多条通信数据Lane Distribution实现





UPF低功耗设计

全芯片UPF低功耗设计(含DFT设计)


景芯SoC训练营培训项目,低功耗设计前,功耗为27.9mW。

低功耗设计后,功耗为0.285mW,功耗降低98.9%!



电压降检查:


低功耗检查:


低功耗设计的DRC/LVS,芯片顶层的LVS实践价值极高,具有挑战性!业界独一无二的经验分享。




全栈芯片工程师
十多年SoC、MCU、ISP、CIS芯片设计经验!为客户提供优质的design service!研究生毕业于电子科大,曾就职海思,后加入创业公司任芯片设计经理,创办了景芯SoC全流程芯片设计培训营!
 最新文章