最近在用OV2640做图像处理,自己设计了一个pcb,上面有正点原子4.3‘的TFT屏幕和OV2640,单片机是stm32f407。调试了一天,发现无论如何变更初始化系数都无法实现缩放功能。翻看过论坛里的一个帖子,说是要设置好开窗函数和输出窗口,但是问题好像没有那么简单,下面我详细说明一下我遇到的情况。
首先,OV2640有四个窗口设置,分别为传感器窗口、图像尺寸、图像窗口和图像输出大小设置。根据《STM32F4开发指南-寄存器版本》_V1.1中所写:“如果设置的图像输出大小不等于图像窗口设置大小,那么图像就会被缩放处理,只有这两者设置一样大的时候,输出比例才是1:1的”(参见p.538)。这句话也在事例代码中体现了:
[mw_shl_code=c,true]if(scale==0)
{
OV2640_ImageWin_Set((1600-lcddev.width)/2,(1200-lcddev.height)/2,lcddev.width,lcddev.height);//1:1真实尺寸
OV2640_OutSize_Set(lcddev.width,lcddev.height);
sprintf((char*)msgbuf,"Full Size 1:1");
}else
{
OV2640_ImageWin_Set(0,0,1600,1200);
OV2640_OutSize_Set(lcddev.width,lcddev.height);//全尺寸缩放
sprintf((char*)msgbuf,"Scale");
}[/mw_shl_code]
代码中写的很清楚,当scale=0时,也就是1:1的真实尺寸,传感器的尺寸是1600*1200,也就是说有这么多个像素点,而4.3‘的LCD屏幕有800*480个像素,所谓的1:1真实尺寸就是在1600*1200这个矩阵中开一个800*480的窗口,这个窗口在传感器正中心,传感器的每一个像素点对应LCD上的每一个像素点,这就是1:1的意思。
当scale=1时,也就是全尺寸缩放,显然LCD只有800*480的空间,但是传感器有1600*1200,因此这里的意思是说将1600*1200这么多像素通过OV2640内部的DSP功能进行全自动尺寸缩放为800*480输出,在LCD上看到的内容就是整个传感器所拍摄到的内容。
以上是我对这代代码的理解,如果没有错误,请继续往下看。
我用的LCD屏幕就是正点原子800*480的4.3‘的屏幕,但是我的输出窗口设置为200*200,也就是OV2640_OutSize_Set(200, 200),然后在LCD上左上角开始显示200*200的图像。
四个窗口的设置:
传感器尺寸初始化与示例代码一致(均为1600*1200):
[mw_shl_code=c,true]0x12, 0x00,// UXGA 1600*1200
0x17, 0x11,
0x18, 0x75,
0x19, 0x01,
0x1a, 0x97,
0x32, 0x36,
0x03, 0x0f,[/mw_shl_code]
图像尺寸也相同(均为1600*1200):
[mw_shl_code=c,true]0xc0, 0xc8,// 图像尺寸 1600*1200
0xc1, 0x96,
0x8c, 0x00,[/mw_shl_code]
而图像窗口和图像输出大小设置如下:
[mw_shl_code=c,true]uint16_t outh = 200, outw = 200;
uint8_t temp = 0;
uint16_t hsize, vsize;
uint16_t offx, offy;
offx = 0;
offy = 0;
hsize = 1600 / 4;
vsize = 1200 / 4;
SCCB_WriteByte(SCCB_ID, 0xFF, 0x00);
SCCB_WriteByte(SCCB_ID, 0xE0, 0x04);
SCCB_WriteByte(SCCB_ID, 0x51, hsize & 0xFF);// 设置H_SIZE的低八位
SCCB_WriteByte(SCCB_ID, 0x52, vsize & 0xFF);// 设置V_SIZE的低八位
SCCB_WriteByte(SCCB_ID, 0x53, offx & 0xFF);// 设置offx的低八位
SCCB_WriteByte(SCCB_ID, 0x54, offy & 0xFF);// 设置offy的低八位
temp = (vsize >> 1) & 0x80;
temp |= (offy >> 4) & 0x70;
temp |= (hsize >> 5) & 0x08;
temp |= (offx >> 8) & 0x07;
SCCB_WriteByte(SCCB_ID, 0x55, temp); // 设置H_SIZE/V_SIZE/OFFX,OFFY的高位
SCCB_WriteByte(SCCB_ID, 0x57, (hsize >> 2) & 0x80); // 设置H_SIZE/V_SIZE/OFFX,OFFY的高位
SCCB_WriteByte(SCCB_ID, 0xE0, 0x00);
Delay_ms(100);
outw = width / 4;
outh = height / 4;
SCCB_WriteByte(SCCB_ID, 0xFF, 0x00);
SCCB_WriteByte(SCCB_ID, 0xE0, 0x04);
SCCB_WriteByte(SCCB_ID, 0x5A, outw & 0xFF); // 设置OUTW的低八位
SCCB_WriteByte(SCCB_ID, 0x5B, outh & 0xFF); // 设置OUTH的低八位
temp = (outw >> 8) & 0x03;
temp |= (outh >> 6) & 0x04;
SCCB_WriteByte(SCCB_ID, 0x5C, temp); // 设置OUTH/OUTW的高位
SCCB_WriteByte(SCCB_ID, 0xE0, 0x00);[/mw_shl_code]
为了保证一致性,上述两个窗口的设置与示例代码也一致。可以看到,图像窗口设置为1600*1200,图像输出大小为200*200。如果说之前分析正点原子的那两段代码没错,那么这里无非就是将1600*1200的图像经过内部DSP图像处理之后缩放为200*200吧?也就是说在200*200的LCD屏幕范围上可以看到整个传感器所拍摄的东西?
但是,情况并不是这样,从LCD屏幕上看到的图像就感觉像是在1600*1200的传感器中开出了一个200*200的窗,然后显示出来。因为本人将上述代码的hisze和vsize(这两个值就是图像窗口大小)分别更换为800和800之后,显示图像的物体大小丝毫没有改变(应该是800*800的图像缩放到200*200),反而和1600*1200一模一样,就好比图像窗口的设置根本没起到作用。效果如图所示:
这个图是1600*1200的图像窗口设置
在200*200的图像输出大小下的结果。
这个图是800*800的图像窗口设置在200*200的图像输出大小下的结果。
总结一下,四个窗口设置分别为:
传感器窗口1600*1200
图像尺寸1600*1200
图像窗口???
图像输出大小设置200*200
第三个图像窗口设置无论设置成1600*1200还是800*800,图像输出始终没有缩放,感觉一直是1:1输出,求解答!!!
|