1

カメラから映像を取得します。このような:

初期化:

uint pcount = (uint)(capGrabber.Width * capGrabber.Height * PixelFormats.Bgr32.BitsPerPixel / 8);
section = CreateFileMapping(new IntPtr(-1), IntPtr.Zero, 0x04, 0, pcount, null);
map = MapViewOfFile(section, 0xF001F, 0, 0, pcount);
BitmapSource = System.Windows.Interop.Imaging.CreateBitmapSourceFromMemorySection(section, capGrabber.Width, capGrabber.Height, PixelFormats.Bgr32, capGrabber.Width * PixelFormats.Bgr32.BitsPerPixel / 8, 0) as InteropBitmap;
capGrabber.Map = map;

どこ

IntPtr map;
IntPtr section;
InteropBitmap BitmapSource;

グラバー (capGrabber):

public int BufferCB(double sampleTime, IntPtr pBuffer, int bufferLen)
{
    if (Map != IntPtr.Zero)
    {
        CopyMemory(Map, pBuffer, bufferLen);
        OnNewFrameArrived();
    }

    return 0;            
}

画像を上下逆さまにします(トップダウン)。これを修正する必要があります。いくつかのものを見つけました (構造 BITMAPINFO を使用) が、動作していません。アイデアを聞いてください。

4

3 に答える 3

1

この問題は、トップダウンとボトムアップのDIBに関連しているようです。

ビットマップを180度回転させるためにWPF変換を追加する人もいますが、私が見つけた最も簡単な解決策は、ビットマップを逆の順序でコピーすることです。

CopyMemory(Map, pBuffer, bufferLen);

for(IntPtr pMap = Map, pBuf = pBuffer+bufferLen; pBuf.ToInt64() > pBuffer.ToInt64(); pMap += 4, pBuf -= 4)
    CopyMemory(pMap, pBuf-4, 4);

数字の4は、1ピクセルを表すバイト数、つまり32ビット(RGB32)を8で割ったものを意味することに注意してください。

于 2013-03-23T12:07:17.093 に答える
1
var target = m_Map;
var bytesPerRow = (m_Width * 4);
var source = aBuffer + aLength - bytesPerRow;

for (int i = m_Height - 1; i > 0; i--)
{
    Interop.CopyMemory(target, source, bytesPerRow);
    target += bytesPerRow;
    source -= bytesPerRow;
}

はるかに高性能。元のコードは、反復ごとに 224 467 428 ティックかかります。行ごとのコピーには 4 041 288 ティックしかかかりません

于 2013-10-21T12:29:13.003 に答える
1

Petr Gotthard は正しい問題を念頭に置いていますが、コードは問題を解決していません。

MSDNによると:

ボトムアップ DIB では、イメージ バッファーはピクセルの一番下の行から始まり、次の行が続きます。イメージの一番上の行は、バッファーの最後の行です。したがって、メモリ内の最初のバイトは、イメージの左下のピクセルです。GDI では、すべての DIB がボトムアップです。次の図は、ボトムアップ DIB の物理的なレイアウトを示しています。

これが意味することは、画像が一番上の行ではなく、一番下の行を最初に描画していることです。これにより、垂直ミラー効果が作成されます。ただし、左右が逆になるわけではありません。

次の配列を検討してください。

[ 0, 1, 2 ]
[ 3, 4, 5 ]
[ 6, 7, 8 ]

トップダウンは、記載されているとおりに読み取り、出力します。しかし、ボトムアップでは次のように解析します。

[ 6, 7, 8 ]
[ 3, 4, 5 ]
[ 0, 1, 2 ]

単純に逆にすると、次のようになります。

[ 2, 1, 0 ]
[ 5, 4, 3 ]
[ 8, 7, 6 ]

それを元に戻すには、ストライド (幅) が必要です。次に、行ごとに反転します。

したがって、Petr の回答に一歩足を踏み入れると、次のようになります。

int stride = Width * PixelFormats.Bgr32.BitsPerPixel / 8;
for (IntPtr pMap = Map, pBuf = buffer + bufferLen; pBuf.ToInt64() > buffer.ToInt64(); pMap += stride, pBuf -= stride)
    CopyMemory(pMap, pBuf - stride, stride);
于 2014-11-07T20:01:52.923 に答える