Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 从网络摄像机自上而下拍摄图像_C#_Wpf_Image_Api_Capture - Fatal编程技术网

C# 从网络摄像机自上而下拍摄图像

C# 从网络摄像机自上而下拍摄图像,c#,wpf,image,api,capture,C#,Wpf,Image,Api,Capture,我从摄像机里得到了镜头。像这样: 初始化: 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, pcoun

我从摄像机里得到了镜头。像这样:

初始化:

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;
在哪里

抓取器(capGrabber):


我将图像颠倒(自上而下)。我们需要解决这个问题。我找到了一些东西(使用结构BITMAPINFO),但我没有工作。询问任何想法。

这个问题似乎与你的工作有关

有些人添加WPF变换以将位图旋转180度,但我发现最简单的解决方案是按相反顺序复制位图,即替换

CopyMemory(Map, pBuffer, bufferLen);

注:数字4表示代表一个像素的字节数,即32位(RGB32)除以8

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个刻度

Petr Gotthard考虑到了正确的问题,但代码没有解决这个问题

根据:

在自底向上的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 ]
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);
所以要把它放回去,我们需要步幅(宽度),然后我们一行一行地倒转

因此,接受Petr的回答,再加上一步,我们得到:

[ 2, 1, 0 ]
[ 5, 4, 3 ]
[ 8, 7, 6 ]
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);

请注意,您不能只是颠倒顺序,因为这将左右翻转。相反,您必须根据步幅进行倒车。IE
int stride=Width*PixelFormats.Bgr32.BitsPerPixel/8;对于(IntPtr pMap=Map,pBuf=buffer+bufferLen;pBuf.ToInt64()>buffer.ToInt64();pMap+=stride,pBuf-=stride)CopyMemory(pMap,pBuf-stride,stride)
在我的例子中,图像位来自
ffmpeg.exe
进程的重定向stdout管道,然后被传递到WPF
CreateBitmapSource…
方法中,因此我只是在源代码处通过向
ffmpeg
进程的命令行添加
-vf vflip
来处理它。
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);