百度发现,很少有人涉足使用vfw的相机取像的回调函数,不知道是什么原因。
1,vc++下设置回调函数如下:
capSetCallbackOnFrame(m_hCamWnd,framecallbackproc);
2,回调函数如下:
LRESULT CALLBACK framecallbackproc(HWND hWnd, LPVIDEOHDR lpvHdr)
{
return
(LRESULT)TRUE;
}
3,取像时,设置断点,发现lpvhdr->lpdata中的数据是640*480*2bytes。
4,通过BITMAPINFO bmpinfo;
capGetVideoFormat(m_hCamWnd, &bmpinfo, sizeof(BITMAPINFO));
查看得知,lpvhdr->lpdata中是16位的rgb彩色图像。
5,使用rgb565(16位彩色编制)解析,灰度图像成功,彩色很难看。使用rgb555(16位彩色编制)解析,灰度和彩色都很差。
6,虽然这个灰度图像已经足以进行人脸识别,但问题没解决,这个16位彩色编制到底是什么鬼?
7,百度有高人指出是yuyv16位彩色编制,至于解析,很少有人吭声了,最后看了左飞的图像处理,才有些明白。
8,再百度yuyv2rgb,竟然有c++代码,尝试了一把,竟然成功了,久违的色彩饱满的到来。这些东西少之又少,做一记录,以备他时之用。
9,yuyv16位彩色编制c++代码没仔细看,直到要翻译为c#时,才研究透彻,下面给出两个版本代码,做以对比:
a,vc++:
int ConvertYUY2toRGB24(char *pOutputRgb, unsigned char *pInputBuffer, int tInputWidth, int tInputHeight)
{
unsigned char *yuyv = pInputBuffer;
int z = 0 , i = 0, j = 0;
for(i = 0 ; i < tInputHeight; i++) //宽度的像素点数
{
for (j = 0; j < tInputWidth; j++) //长度的像素点数
{
int r, g, b;
int y, u, v;
short rgb;
if (!z)
y = yuyv[0] << 8;
else
y = yuyv[2] << 8;
u = yuyv[1] - 128;
v = yuyv[3] - 128;
r = (y + (359 * v)) >> 8;
g = (y - (88 * u) - (183 * v)) >> 8;
b = (y + (454 * u)) >> 8;
r = (r > 255) ? 255 : ((r < 0) ? 0 : r); // RGB的范围为0~255,0为最弱,255为最亮
g = (g > 255) ? 255 : ((g < 0) ? 0 : g);
b = (b > 255) ? 255 : ((b < 0) ? 0 : b);
*pOutputRgb++=b;
*pOutputRgb++=g;
*pOutputRgb++=r;
if (z++)
{
z = 0;
yuyv += 4;
}
}
}
return 0;
}
//////////////////////
b,c#版本:
public int ConvertYUY2toRGB24(byte[] pOutputRgb, byte[] pInputBuffer, int tInputWidth, int tInputHeight)
{
byte[] yuyv = pInputBuffer;
int z = 0, i = 0, j = 0;
int num = 0;
int num1 = 0;
for (i = 0; i < tInputHeight; i++) //宽度的像素点数
{
for (j = 0; j < tInputWidth; j++) //长度的像素点数
{
int r, g, b;
int y, u, v;
// short rgb;
if (0 != z)
y = yuyv[num1 + 0] << 8;
else
y = yuyv[num1 + 2] << 8;
u = yuyv[num1 + 1] - 128;
v = yuyv[num1 + 3] - 128;
r = (y + (359 * v)) >> 8;
g = (y - (88 * u) - (183 * v)) >> 8;
b = (y + (454 * u)) >> 8;
r = (r > 255) ? 255 : ((r < 0) ? 0 : r); // RGB的范围为0~255,0为最弱,255为最亮
g = (g > 255) ? 255 : ((g < 0) ? 0 : g);
b = (b > 255) ? 255 : ((b < 0) ? 0 : b);
pOutputRgb[num] = (byte)b;
pOutputRgb[num + 1] = (byte)g;
pOutputRgb[num + 2] = (byte)r;
num += 3;
if (0 != z)
{
z = 0;
num1 += 4;
}
else { z++; }
}
}
return 0;
}
有兴趣的人,可以研究一下,我发现win8.1下自带摄像头保存图像分辨率是1280*1080,但是它看到的视野和这个回调函数是一样的,这说明了一个问题,微软在众多的摄像头中使用了归一化思想,一统在vfw640*480分辨率下,vfw很经典,值得学习,从win98,win2K,winxp,win7,win8.1一路走来,均可以运行,却在win10下终止了。其实我们可以用更专业的摄像头,何必非要用win10的摄像头?vfw是一种怀念,寄托而已,20年的岁月相伴走来,值得拥有。
另外,vfw除了有图像回调函数,还有声音回调函数,真是一举两得,回调函数的效率还是非常高的,是否可以替换掉我语音识别中声音采集程序呢?
待续(慢慢来!...........)每天一点小改变☺