新知yuyv(怀念vfw)(vsual c++ && c#)

百度发现,很少有人涉足使用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除了有图像回调函数,还有声音回调函数,真是一举两得,回调函数的效率还是非常高的,是否可以替换掉我语音识别中声音采集程序呢?

待续(慢慢来!...........)每天一点小改变☺

我的邮箱[email protected];[email protected]

发布了66 篇原创文章 · 获赞 12 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/ganggangwawa/article/details/103111719