圖像預(yù)處理算法適合在FPGA上完成,原理簡(jiǎn)單且需要快速處理,通常有灰度化、中值、均值濾波等,以及顏色空間轉(zhuǎn)換算法。
灰度圖像是一種特殊的彩色圖像(R=G=B的彩色圖像) 只有一種顏色分量,單通道的0-255
方法:一般有分量法、最大值法、平均值法、加權(quán)平均法四種方法對(duì)彩色圖像進(jìn)行灰度化。
一:最大值法
二:平均值法
1.原理

?除以256可以看作是向右移8位,同樣,512,1024,2048等2的n次都可以
2.verilog實(shí)現(xiàn)
分析:只有加法乘法以及移位操作
module rgb2gray
(
input clk, //時(shí)鐘
input reset_p, //復(fù)位
input rgb_valid, //rgb輸入有效標(biāo)識(shí)
input rgb_hs, //rgb輸入行信號(hào)
input rgb_vs, //rgb輸入場(chǎng)信號(hào)
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輸出有效標(biāo)識(shí)
output reg gray_hs, //gray輸出行信號(hào)
output reg gray_vs //gray輸出場(chǎng)信號(hào)
);
//求平均法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
三,加權(quán)平均 RGB--Ycbcr
1.基本原理
Y'為顏色的亮度(luma)分量、而CB和CR則為藍(lán)色和紅色的濃度偏移量成份。常見(jiàn)的3 個(gè)基本色彩模型是RGB,CMYK和YUV。YCbCr是YUV經(jīng)過(guò)縮放和偏移的翻版,JPEG、MPEG均采用此格式。主要的子采樣格式有 YCbCr 4:2:0、YCbCr 4:2:2 和 YCbCr 4:4:4。


圖來(lái)自:FPGA實(shí)現(xiàn)圖像灰度轉(zhuǎn)換(2):RGB轉(zhuǎn)YCbCr轉(zhuǎn)Gray - 咸魚(yú)IC - 博客園 (cnblogs.com)
將三個(gè)分量以不同的權(quán)值進(jìn)行加權(quán)平均:
gray(i, j) = 0.299 ? ??(??,??) + 0.587 ? ??(??,??) + 0.114 ? ??(??,??)
在實(shí)際應(yīng)用時(shí),為了能避免低速的浮點(diǎn)運(yùn)算以及除法運(yùn)算,先將式子縮放 1024 倍來(lái)實(shí)現(xiàn)運(yùn)算算法,如下:
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.代碼實(shí)現(xiàn)
1)公式計(jì)算法實(shí)現(xiàn):
首先將RGB565轉(zhuǎn)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;
//乘法轉(zhuǎn)換成移位相加方式
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];
//打拍計(jì)算
always@(posedge clk)
begin
gray_valid <= rgb_valid;
gray_hs <= rgb_hs;
gray_vs <= rgb_vs;
end
進(jìn)行打拍計(jì)算,在圖像處理時(shí),我們是有數(shù)據(jù)的同步信號(hào)的,有的是數(shù)據(jù)使能信號(hào),有的還有行同步信號(hào)和幀同步信號(hào)。經(jīng)過(guò)圖像處理后的數(shù)據(jù)延遲了拍數(shù),這些同步信號(hào)也要相應(yīng)的打拍,否則最終的圖像顯示會(huì)出問(wèn)題。
將Y,Cb,Cr分量都獲取的代碼實(shí)現(xiàn)辦法:
module rgb2gray
(
input clk, //時(shí)鐘
input reset_p, //復(fù)位
input rgb_valid, //rgb輸入有效標(biāo)識(shí)
input rgb_hs, //rgb輸入行信號(hào)
input rgb_vs, //rgb輸入場(chǎng)信號(hào)
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輸出有效標(biāo)識(shí)
output gray_hs, //gray輸出行信號(hào)
output gray_vs //gray輸出場(chǎng)信號(hào)
);
//典型灰度轉(zhuǎn)換公式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輸入有效標(biāo)識(shí)
reg [3:0] rgb_hs_r; //rgb輸入行信號(hào)
reg [3:0] rgb_vs_r; //rgb輸入場(chǎng)信號(hào)
提取三種分量的RGB值,并且進(jìn)行相加得到
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擴(kuò)大256倍
Cr1 <= R3 - G3 - B3 + 16'd32768; //128擴(kuò)大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顯示屏上進(jìn)行顯示灰度處理實(shí)現(xiàn)的效果:
也可以只提取77 < Cb < 127,133 < Cr < 173輸出值為8'hFF,也就是說(shuō)將該范圍內(nèi)的圖像標(biāo)記出來(lái)。即膚色提?。?/p>
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顯示屏上進(jìn)行顯示膚色提取實(shí)現(xiàn)的效果:
?可以發(fā)現(xiàn),它的椒鹽噪聲太多,需要進(jìn)行濾波處理來(lái)減少椒鹽噪聲。文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-798462.html
2)查找表法:
采用查找表方法實(shí)現(xiàn),主要的優(yōu)勢(shì)是直接通過(guò) 訪問(wèn) ROM 內(nèi)的數(shù)據(jù),相對(duì)使用移位相加實(shí)現(xiàn)乘法使用的 LUT 資源會(huì)少點(diǎn),但占用的存儲(chǔ)器會(huì)更多。
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
//`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 //灰度轉(zhuǎn)換公式 Gray = R*0.299+G*0.587+B*0.114
...//方法 2
`endif
`ifdef LUT//查找表方式
...//方法 3
`endif
endmodule
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
//---------------------------------------------
//典型灰度轉(zhuǎn)換公式 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
//---------------------------------------------
//查找表方式,可以省去公式法中乘法運(yùn)算 Gray =(R*77 + G*150 + B*29) >>8,將 3 個(gè)分量
乘以系數(shù)后的數(shù)值存儲(chǔ)在 ROM 中
//方法 3
//---------------------------------------------
end
endgenerate
endmodule
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)
);
記錄學(xué)習(xí)過(guò)程,搬運(yùn)于小梅哥的文檔,非原創(chuàng)?。∏謾?quán)請(qǐng)聯(lián)系刪除。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-798462.html
到了這里,關(guān)于圖像預(yù)處理算法————灰度化處理的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!