改善OV5640的锯齿现象(应用梯度导向算法)

关于梯度导向算法的内容来自于http://blog.chinaaet.com/crazybingo/p/32548

来看bayer pattern,其中的一部分示意图如下:

  

因为人眼对绿色分量最为敏感,因此G分量占的比重大,为像素总数的一半;像素总数的四分之一为R,四分之一为B。将Bayer Raw图像转换为RGB图像,本系统尝试过两种算法:1.双线性插值法。2.边缘导向算法。双线性插值法就是使用周围邻域像素来恢复自身像素值的办法,

 

R在中间,四边G,四角B的排列为例,其中,像素的下标为坐标。

 

对于(2,2)点像素,RR22G为(G12+G21+G23+G32/4B为(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

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值