4

次のように取得される画像データがあります。

unsigned char* imageData = NULL;
GetImage(imageData);

生のimageDataBayerGR8 形式として返されます。

G R G R G R G R ... 
B G B G B G B G ...
G R G R G R G R ...
      ...

これらの各ピクセルは 8 ビットを占有します。

取得されている画像は 2752x2200 (ピクセル) です。

ビットマップを設定し、この画像データを使用してビットマップを作成すると、ビットマップは常に空白になります。これが私のビットマップ設定です:

    BITMAPFILEHEADER* bf = new BITMAPFILEHEADER;
    bf->bfType = 0x4d42;
    bf->bfSize = 6054400 + 54 + sizeof(BITMAPINFO);
    bf->bfOffBits = 54;

    BITMAPINFOHEADER* bih = new BITMAPINFOHEADER;
    bih->biSize = 40;
    bih->biWidth = 2752;
    bih->biHeight = 2200;
    bih->biPlanes = 1;
    bih->biBitCount = 8;
    bih->biCompression = 0;
    bih->biXPelsPerMeter = 2835;
    bih->biYPelsPerMeter = 2835;
    bih->biClrUsed = 0;
    bih->biClrImportant = 0;

これまでのところ、次のことを試しました。

HDC hdc = ::GetDC(NULL);
HBITMAP hbit = CreateDIBitmap(hdc, globalinfoheader, CBM_INIT, imageData, pbmi, DIB_RGB_COLORS);

しかし、私が言ったように、ビットマップは最終的に空のライトグレーのイメージになります。私はビットマップに関するウィキペディアの記事を見てきました.biClrUsed値と関係があるように感じますが、それがどのような値であるべきかわかりません.これまでのところ、数字で遊んでいます.

また、次のように、画像データを直接 CImage (後で HBITMAP に変換します) に変換しようとしました。

void ConvertImageBufferToCImage(unsigned char *pInBuffer, CImage *pOutImage)
{
    if ( NULL != *pOutImage )
    {
        unsigned char *pCursor = (unsigned char*)pOutImage->GetBits();
        int nHeight = 2200;
        int nWidth = 2752;
        int nStride = 0;

        if ( 0 < nStride)
        {
            for ( int y=0; y<nHeight; ++y )
            {
                for ( int x=0; x<nWidth; ++x )
                {
                    *pCursor = *pInBuffer;
                    ++pCursor;
                    ++pInBuffer;
                }
                // Consider stride
                pCursor += nStride;
            }
        }
        else
        {
            memcpy( pOutImage->GetBits(), pInBuffer, nWidth * nHeight );
        }
    }
}

私の質問は 、生のベイヤー画像データを取得して、そこから RGB カラー ビットマップを取得するにはどうすればよいですか?

編集:

とった。これが機能するように作成した関数です(補間法):

/////////////////////////////////////////////////////////////
// ConvertBayer8ToBgr()
// Converts raw BayerGR8 pixels into
//     BGR pixels.
//
//  G | R | G | R              B G R | B G R | B G R | B G R
// --- --- --- ---            ------- ------- ------- -------
//  B | G | B | G        |\    B G R | B G R | B G R | B G R
// --- --- --- ---  -----  \  ------- ------- ------- -------
//  G | R | G | R   -----  /   B G R | B G R | B G R | B G R
// --- --- --- ---       |/   ------- ------- ------- -------
//  B | G | B | G              B G R | B G R | B G R | B G R
//
/////////////////////////////////////////////////////////////
void ConvertBayer8ToBGR(VmbUchar_t* bayerImgDat, VmbUchar_t* bgrOutputDat)
{
    VmbUchar_t* newimagedata_start = bgrOutputDat;

    int currentTempIndex = 0;
    int nearestBluesAvg = 0;
    int nearestRedsAvg = 0;
    int nearestGreensAvg = 0;

    for(int j = 0; j < 1100; j++)
    {
        for(int i = 0; i < 2752; i++) //G R G R G... 
        {
            if(currentTempIndex % 2 == 0 /* even, green */)
            {
                //avg blue
                if(j == 0) //if in the first row, only take next blue
                {
                    nearestBluesAvg = *(bayerImgDat+currentTempIndex+2752);
                }
                else
                {
                    nearestBluesAvg = (*(bayerImgDat + currentTempIndex + 2752) + *(bayerImgDat+currentTempIndex-2752)) / 2;
                }
                *bgrOutputDat = nearestBluesAvg; //b
                bgrOutputDat++;
                *bgrOutputDat = *(bayerImgDat + currentTempIndex); //g
                bgrOutputDat++;
                //avg red
                if(i == 0) //if in first column, only take next red 
                {
                    nearestRedsAvg = *(bayerImgDat+currentTempIndex+1);
                }
                else
                {
                    nearestRedsAvg = ( (*(bayerImgDat+currentTempIndex+1)) + (*(bayerImgDat+currentTempIndex-1)) ) / 2;
                }
                *bgrOutputDat = nearestRedsAvg; //r
                bgrOutputDat++;

                currentTempIndex++;
            }
            else /* odd, red*/
            {
                //avg blue
                if(i == 1099) //if in last column, take just left-down blue pixel
                {
                    nearestBluesAvg = *(bayerImgDat+currentTempIndex-1+2752);
                }
                else // else take both left-down and right-down
                {
                    nearestBluesAvg = (*(bayerImgDat+currentTempIndex+1+2752) + *(bayerImgDat+currentTempIndex-1+2752)) / 2;
                }
                *bgrOutputDat = nearestBluesAvg; //b
                bgrOutputDat++;
                //avg green
                nearestGreensAvg = (*(bayerImgDat+currentTempIndex-1) + *(bayerImgDat+currentTempIndex+2752)) / 2;
                *bgrOutputDat = nearestGreensAvg;  //g
                bgrOutputDat++;
                *bgrOutputDat = *(bayerImgDat + currentTempIndex); //r
                bgrOutputDat++;

                currentTempIndex++;
            }
        }
        for(int i = 0; i < 2752; i++)//B G B G B G B....
        {
            if(currentTempIndex % 2 == 0 /* even, blue */)
            {

                *bgrOutputDat = *(bayerImgDat + currentTempIndex); //b
                bgrOutputDat++;
                //avg green
                nearestGreensAvg = (*(bayerImgDat + currentTempIndex + 1) + *(bayerImgDat + currentTempIndex -2752)) / 2;
                *bgrOutputDat = nearestGreensAvg; //g
                bgrOutputDat++;
                //avg red
                if(i == 0) //if first column, take only right-up pixel
                {
                    nearestRedsAvg = *(bayerImgDat+currentTempIndex+1-2752);
                }
                else //else take both left-up and right-up pixels
                {
                    nearestRedsAvg = (*(bayerImgDat+currentTempIndex-1-2752) + *(bayerImgDat+currentTempIndex+1-2752)) / 2;
                }
                *bgrOutputDat = nearestRedsAvg; //r
                bgrOutputDat++;

                currentTempIndex++;

            }
            else /* odd, green*/
            {
                //avg blue
                if(i == 2751) //if in last column, only take previous blue (next blue doesnt exist)
                {
                    nearestBluesAvg = *(bayerImgDat + currentTempIndex - 1);
                }
                else //else take both next and previous
                {
                    nearestBluesAvg = (*(bayerImgDat+currentTempIndex+1) + *(bayerImgDat+currentTempIndex-1)) / 2;
                }
                *bgrOutputDat = nearestBluesAvg; //b
                bgrOutputDat++;
                *bgrOutputDat = *(bayerImgDat + currentTempIndex); //g
                bgrOutputDat++;
                //avg red
                if(j == 1099) //if in last row, only take previous red (next red doesn't exist)
                {
                    nearestRedsAvg = *(bayerImgDat+currentTempIndex-2752);
                }
                else //else take both
                {
                    nearestRedsAvg = (*(bayerImgDat+currentTempIndex+2752) + *(bayerImgDat+currentTempIndex-2752)) / 2;
                }
                *bgrOutputDat = nearestRedsAvg; //r
                bgrOutputDat++;

                currentTempIndex++;
            }
        }
    }


    bgrOutputDat = newimagedata_start;
}
4

1 に答える 1

3

ベイヤー画像のコンポーネントを補間する必要があります。役立つリンクは次のとおりです。

http://www.siliconimaging.com/RGB%20Bayer.htm

補間セクションの途中まで見てください。

ターゲット画像に関する限り、標準の RGB 24 ビットまたは 32 ビット ビットマップを作成し、Bayer 画像からコンポーネントを補間する際にビットを設定するだけです。

質問の半分は色変換に関するもので、半分はビットマップ コードが機能しない理由に関するものです。Windows で RGB ビットマップを作成する例は無数にあるので、ここでは説明しません。

于 2013-05-13T22:44:58.193 に答える