关于梯度导向算法的内容来自于http://blog.chinaaet.com/crazybingo/p/32548
来看bayer pattern,其中的一部分示意图如下:
因为人眼对绿色分量最为敏感,因此G分量占的比重大,为像素总数的一半;像素总数的四分之一为R,四分之一为B。将Bayer Raw图像转换为RGB图像,本系统尝试过两种算法:1.双线性插值法。2.边缘导向算法。双线性插值法就是使用周围邻域像素来恢复自身像素值的办法,
以R在中间,四边G,四角B的排列为例,其中,像素的下标为坐标。
对于(2,2)点像素,R为R22,G为(G12+G21+G23+G32)/4,B为(B11+B13+B31+B33)/4
双线性插值算法实现简单,并且适合用FPGA流水线方式进行操作,在平滑的区域有比较好的实现效果,但是在图像的轮廓区域,由于像素的取值并没有考虑到方向性,采用双线性插值算法,将产生锯齿状的效应,大大影响图像质量。
为了克服双线性插值算法带来的图像轮廓的锯齿效应,本系统考虑到第二种算法:边缘导向插值算法。这种插值算法通过比较水平方向、垂直方向和对角线方向的梯度大小,选择梯度较小方向上的像素点,来计算当前像素值。仍然以R在中间,四边G,四角B的排列为例:
因为边缘导向插值算法考虑到了图像边缘区域的变化,因此可以避免边缘区域的锯齿现象。本系统通过对比两种算法,在资源足够的情况下,采用了效果更好的边缘导向插值算法。
将RAW2RGB的源码粘贴如下:
module RAW2RGB ( iCLK,
iRST_N,
//Read Port 1
iDATA,
iDVAL,
oRed,
oGreen,
oBlue,
oDVAL,
iZoom,
iX_Cont,
iY_Cont
);
//--------------------------------------------------//
parameter DATA_SIZE = 10;
input iCLK,iRST_N;
input [DATA_SIZE-1:0] iDATA;
input iDVAL;
output [DATA_SIZE-1:0] oRed;
output [DATA_SIZE-1:0] oGreen;
output [DATA_SIZE-1:0] oBlue;
output oDVAL;
input [1:0] iZoom;
input [15:0] iX_Cont;
input [15:0] iY_Cont;
wire [DATA_SIZE-1:0] wData0;
wire [DATA_SIZE-1:0] wData1;
wire [DATA_SIZE-1:0] wData2;
reg [DATA_SIZE-1:0] rRed;
reg [DATA_SIZE-1:0] rGreen;
reg [DATA_SIZE-1:0] rBlue;
reg rDval;
reg [DATA_SIZE-1:0] wData0_d1,wData0_d2;
reg [DATA_SIZE-1:0] wData1_d1,wData1_d2;
reg [DATA_SIZE-1:0] wData2_d1,wData2_d2;
reg oDVAL;
reg dval_ctrl;
reg dval_ctrl_en;
//out
assign oRed = rRed;
assign oGreen = rGreen;
assign oBlue = rBlue;
LineBuffer_vhdl L1 (
.clken(iDVAL),
.aclr(~iRST_N),
.clock(iCLK),
.shiftin(iDATA),
.shiftout(),
.taps({wData2,wData1,wData0})
);
always@(posedge iCLK or negedge iRST_N)
begin
if (!iRST_N)
begin
dval_ctrl<=0;
end
else
begin
if(iY_Cont>1)
begin
dval_ctrl<=1;
end
else
begin
dval_ctrl<=0;
end
end
end
always@(posedge dval_ctrl or negedge iRST_N)
begin
if (!iRST_N)
begin
dval_ctrl_en<=0;
end
else
begin
dval_ctrl_en<=1;
end
end
always@(posedge iCLK or negedge iRST_N)
begin
if (!iRST_N)
begin
rDval<=0;
oDVAL <= 0;
end
else
if(dval_ctrl_en)
begin
rDval<=iDVAL;
oDVAL<=rDval;
end
else
begin
rDval<=iDVAL;
oDVAL<=0;
end
end
always@(posedge iCLK or negedge iRST_N)
begin
if (!iRST_N)
begin
wData0_d1<=0;
wData0_d2<=0;
wData1_d1<=0;
wData1_d2<=0;
wData2_d1<=0;
wData2_d2<=0;
end
else
begin
{wData0_d2,wData0_d1}<={wData0_d1,wData0};
{wData1_d2,wData1_d1}<={wData1_d1,wData1};
{wData2_d2,wData2_d1}<={wData2_d1,wData2};
end
end
always@(posedge iCLK or negedge iRST_N)
begin
if (!iRST_N)
begin
rRed<=0;
rGreen<=0;
rBlue<=0;
end
else if ({iY_Cont[0],iX_Cont[0]} == 2'b00)//2'b11
begin
rRed<=wData1_d1;
//Hg > Vg
if( (wData1_d2 >= wData1 && wData2_d1 >= wData0_d1 && (wData1_d2- wData1)>(wData2_d1-wData0_d1) )||
( wData1_d2 >= wData1 && wData2_d1 < wData0_d1 && (wData1_d2 - wData1)>(wData0_d1 - wData2_d1) ) ||
( wData1_d2 < wData1 && wData2_d1 >= wData0_d1 && (wData1 - wData1_d2)>(wData2_d1 - wData0_d1) ) ||
( wData1_d2 < wData1 && wData2_d1 < wData0_d1 && (wData1 - wData1_d2)>(wData0_d1 - wData2_d1) )
)
rGreen<=(wData2_d1+ wData0_d1)/2;
//Hg < Vg
if( (wData1_d2 >= wData1 && wData2_d1 >= wData0_d1 && (wData1_d2- wData1)<(wData2_d1-wData0_d1) )||
( wData1_d2 >= wData1 && wData2_d1 < wData0_d1 && (wData1_d2 - wData1)<(wData0_d1 - wData2_d1) ) ||
( wData1_d2 < wData1 && wData2_d1 >= wData0_d1 && (wData1 - wData1_d2)<(wData2_d1 - wData0_d1) ) ||
( wData1_d2 < wData1 && wData2_d1 < wData0_d1 && (wData1 - wData1_d2)<(wData0_d1 - wData2_d1) )
)
rGreen<=(wData1_d2+ wData1)/2;
//Hg = Vg
if( (wData1_d2 >= wData1 && wData2_d1 >= wData0_d1 && (wData1_d2- wData1)==(wData2_d1-wData0_d1) )||
( wData1_d2 >= wData1 && wData2_d1 < wData0_d1 && (wData1_d2 - wData1)==(wData0_d1 - wData2_d1) ) ||
( wData1_d2 < wData1 && wData2_d1 >= wData0_d1 && (wData1 - wData1_d2)==(wData2_d1 - wData0_d1) ) ||
( wData1_d2 < wData1 && wData2_d1 < wData0_d1 && (wData1 - wData1_d2)==(wData0_d1 - wData2_d1) )
)
rGreen<=(wData1+wData2_d1+wData1_d2 + wData0_d1)/4;
//Db1 > Db2
if( (wData2_d2 >= wData0 && wData2 >= wData0_d2 && (wData2_d2- wData0)>(wData2-wData0_d2) )||
(wData2_d2 >= wData0 && wData2 < wData0_d2 && (wData2_d2- wData0)>(wData0_d2 - wData2) )||
(wData2_d2 < wData0 && wData2 >= wData0_d2 && (wData0 - wData2_d2)>(wData2-wData0_d2) )||
(wData2_d2 < wData0 && wData2 < wData0_d2 && (wData0 - wData2_d2)>(wData0_d2 - wData2) ) )
rBlue<=(wData2+wData0_d2)/2;
//Db1 < Db2
if( (wData2_d2 >= wData0 && wData2 >= wData0_d2 && (wData2_d2- wData0)<(wData2-wData0_d2) )||
(wData2_d2 >= wData0 && wData2 < wData0_d2 && (wData2_d2- wData0)<(wData0_d2 - wData2) )||
(wData2_d2 < wData0 && wData2 >= wData0_d2 && (wData0 - wData2_d2)<(wData2-wData0_d2) )||
(wData2_d2 < wData0 && wData2 < wData0_d2 && (wData0 - wData2_d2)<(wData0_d2 - wData2) ) )
rBlue<=(wData2_d2+wData0)/2;
//Db1 = Db2
if( (wData2_d2 >= wData0 && wData2 >= wData0_d2 && (wData2_d2- wData0)==(wData2-wData0_d2) )||
(wData2_d2 >= wData0 && wData2 < wData0_d2 && (wData2_d2- wData0)==(wData0_d2 - wData2) )||
(wData2_d2 < wData0 && wData2 >= wData0_d2 && (wData0 - wData2_d2)==(wData2-wData0_d2) )||
(wData2_d2 < wData0 && wData2 < wData0_d2 && (wData0 - wData2_d2)==(wData0_d2 - wData2) ) )
rBlue<=(wData0+wData2+wData0_d2 + wData2_d2)/4;
end
else if ({iY_Cont[0],iX_Cont[0]} == 2'b01)//2'b10
begin
rRed<=(wData1+wData1_d2)/2;
rGreen<=(wData0+wData2+wData0_d2 + wData2_d2)/4;
rBlue<=(wData0_d1+wData2_d1)/2;
end
else if ({iY_Cont[0],iX_Cont[0]} == 2'b10)//2'b01
begin
rRed<=(wData2_d1+wData0_d1)/2;
rGreen<=(wData0+wData2+wData0_d2 + wData2_d2)/4;
rBlue<=(wData1+wData1_d2)/2;
end
else if ({iY_Cont[0],iX_Cont[0]} == 2'b11)//2'b00
begin
rBlue<=wData1_d1;
//Hg > Vg
if( (wData1_d2 >= wData1 && wData2_d1 >= wData0_d1 && (wData1_d2- wData1)>(wData2_d1-wData0_d1) )||
( wData1_d2 >= wData1 && wData2_d1 < wData0_d1 && (wData1_d2 - wData1)>(wData0_d1 - wData2_d1) ) ||
( wData1_d2 < wData1 && wData2_d1 >= wData0_d1 && (wData1 - wData1_d2)>(wData2_d1 - wData0_d1) ) ||
( wData1_d2 < wData1 && wData2_d1 < wData0_d1 && (wData1 - wData1_d2)>(wData0_d1 - wData2_d1) )
)
rGreen<=(wData2_d1+ wData0_d1)/2;
//Hg < Vg
if( (wData1_d2 >= wData1 && wData2_d1 >= wData0_d1 && (wData1_d2- wData1)<(wData2_d1-wData0_d1) )||
( wData1_d2 >= wData1 && wData2_d1 < wData0_d1 && (wData1_d2 - wData1)<(wData0_d1 - wData2_d1) ) ||
( wData1_d2 < wData1 && wData2_d1 >= wData0_d1 && (wData1 - wData1_d2)<(wData2_d1 - wData0_d1) ) ||
( wData1_d2 < wData1 && wData2_d1 < wData0_d1 && (wData1 - wData1_d2)<(wData0_d1 - wData2_d1) )
)
rGreen<=(wData1_d2+ wData1)/2;
//Hg = Vg
if( (wData1_d2 >= wData1 && wData2_d1 >= wData0_d1 && (wData1_d2- wData1)==(wData2_d1-wData0_d1) )||
( wData1_d2 >= wData1 && wData2_d1 < wData0_d1 && (wData1_d2 - wData1)==(wData0_d1 - wData2_d1) ) ||
( wData1_d2 < wData1 && wData2_d1 >= wData0_d1 && (wData1 - wData1_d2)==(wData2_d1 - wData0_d1) ) ||
( wData1_d2 < wData1 && wData2_d1 < wData0_d1 && (wData1 - wData1_d2)==(wData0_d1 - wData2_d1) )
)
rGreen<=(wData1+wData2_d1+wData1_d2 + wData0_d1)/4;
//Db1 > Db2
if( (wData2_d2 >= wData0 && wData2 >= wData0_d2 && (wData2_d2- wData0)>(wData2-wData0_d2) )||
(wData2_d2 >= wData0 && wData2 < wData0_d2 && (wData2_d2- wData0)>(wData0_d2 - wData2) )||
(wData2_d2 < wData0 && wData2 >= wData0_d2 && (wData0 - wData2_d2)>(wData2-wData0_d2) )||
(wData2_d2 < wData0 && wData2 < wData0_d2 && (wData0 - wData2_d2)>(wData0_d2 - wData2) ) )
rRed<=(wData2+wData0_d2)/2;
//Db1 < Db2
if( (wData2_d2 >= wData0 && wData2 >= wData0_d2 && (wData2_d2- wData0)<(wData2-wData0_d2) )||
(wData2_d2 >= wData0 && wData2 < wData0_d2 && (wData2_d2- wData0)<(wData0_d2 - wData2) )||
(wData2_d2 < wData0 && wData2 >= wData0_d2 && (wData0 - wData2_d2)<(wData2-wData0_d2) )||
(wData2_d2 < wData0 && wData2 < wData0_d2 && (wData0 - wData2_d2)<(wData0_d2 - wData2) ) )
rRed<=(wData2_d2+wData0)/2;
//Db1 = Db2
if( (wData2_d2 >= wData0 && wData2 >= wData0_d2 && (wData2_d2- wData0)==(wData2-wData0_d2) )||
(wData2_d2 >= wData0 && wData2 < wData0_d2 && (wData2_d2- wData0)==(wData0_d2 - wData2) )||
(wData2_d2 < wData0 && wData2 >= wData0_d2 && (wData0 - wData2_d2)==(wData2-wData0_d2) )||
(wData2_d2 < wData0 && wData2 < wData0_d2 && (wData0 - wData2_d2)==(wData0_d2 - wData2) ) )
rRed<=(wData0+wData2+wData0_d2 + wData2_d2)/4;
end
end
endmodule