1. 把数据从视频通道通过一维方式传送到片内RAM中并作Sobel边缘提取算法。
我们只对摄像头采集的一块数据进行Sobel边缘提取。采用一维EDMA传送方式,每一次传送采集的一行中的部分数据(DAT_copy()函数)。在PAL制式下,先把一行数据放到nMemTemp数组中,比如我们要把从144行到432行,从180列到435列的图像进行Sobel边缘提取,最后把变换后的数据输出到显示缓冲区。
unsigned char nMemTemp[720];
for ( i = 0; i < numLines; i ++ ) { m_nID=DAT_copy(capFrameBuf->frame.iFrm.y1+i*capLinePitch,nMemTemp,numPixels);
DAT_wait(m_nID);
if ( i>144 && i<432 )
Sobel(); DAT_copy(nMemTemp,disFrameBuf->frame.iFrm.y1+i*disLinePitch,numPixels);
}
因为Sobel算法需要三行数据,我们可以开辟一个可以存放三行数据的缓冲区,通过指针的交换把从视频通道过来的数据分别放到缓冲区中。保存的三行图像使用翻卷的缓冲区管理,三个变量分别指示当前使用的y行、y-1行和y-2行在缓冲区中的起始偏移量。我们可以这样来做:轮流往三块缓存区拷贝数据。只要拷贝的指针变化就可以。在我们拷贝当前这一块的时候,已经拷贝的另外两块数据依然没有变化,所以我们就可以实现三块数据保存采集图像中的相邻的三行数据。如下:
缓冲区1 |
cLines[0-255] |
缓冲区2 |
cLines[256-512] |
缓冲区3 |
cLines[513-768] |
表 缓存区分配
三个指针*pImg1,*pImg2,*pImg3分别轮流指向三个缓冲区。
m_nOffset1=0;
m_nOffset2=256;
m_nOffset3=512;
unsigned char cLines[256*3];
void Sobel()
{
unsigned int m_nID;
m_nID=DAT_copy(nMemTemp+180,cLines+m_nOffset3,256);
pImg1=cLines; pImg1+=m_nOffset1;
pImg2=cLines; pImg2+=m_nOffset2;
pImg3=cLines; pImg3+=m_nOffset3;
x1=(*pImg1); pImg1++; x2=(*pImg1); pImg1++;
x4=(*pImg2); pImg2++; x5=(*pImg2); pImg2++;
x7=(*pImg3); pImg3++; x8=(*pImg3); pImg3++;
for ( mi=0;mi<256;mi++,pImg1++,pImg2++,pImg3++ )
{
x3=(*pImg1); x6=(*pImg2); x9=(*pImg3);
m_nWork1=x7+x8+x8-x2-x2-x3;
m_nWork2=x3+x6+x6-x4-x4-x7;
if ( m_nWork1<m_nWork2 )
m_nWork1=m_nWork2;
m_nWork2=m_nWork1+x9-x1;
if ( m_nWork2>255 ) m_nWork2=1;
else if ( m_nWork2<0 ) m_nWork2=0;
nMemTemp[mi+180]=m_nWork2;
x1=x2; x2=x3;
x4=x5; x5=x6;
x7=x8; x8=x9;
}
nMemTemp[mi]=0;
m_nWork=m_nOffset1; m_nOffset1=m_nOffset2;
m_nOffset2=m_nOffset3; m_nOffset3=m_nWork;
}
2. 把数据从视频通道通过二维方式传送到SDRAM中并作Sobel边缘提取算法。
我们可以通过DAT_copy2d()函数直接把采集的一幅图像亮度分量存放到SDRAM中,如下:
DAT_copy2d(DAT_2D2D,
capFrameBuf->frame.iFrm.y1,
m_dbFrameBufferTemp,
numPixels,
numLines,
numPixels);
其中:m_dbFrameBufferTemp是指向SDRAM中缓冲区的指针,numPixels是一行的象素数,numLines是行数。当把数据存放到SDRAM的一个数组中后,Sobel算法的实现就非常简单了。当然也可以参照一维的方法来实现。