zoukankan      html  css  js  c++  java
  • C# WPF 显示图片和视频显示 EmuguCv、AForge.Net测试(续)

    介绍

    本文是接着上文《C# WPF 显示图片和视频显示 EmuguCv、AForge.Net测试》写的,建议先看下上文,因为有些代码还需要了解。

    增添

    接着上文的代码,我们可以在事件处理方法videoSource_NewFrame 里面加一些对每帧图片的处理  。

           

     private void videoSource_NewFrame(object sender, NewFrameEventArgs eventArgs)
    
            {
    
                //eventArgs.Frame.Save(stream, System.Drawing.Imaging.ImageFormat.Bmp);
    
                if (this.Dispatcher != null)
    
                {
    
                    this.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Render, (SendOrPostCallback)delegate
    
                    {
    
                        if (map != IntPtr.Zero)
    
                        {
    
                            var tempImg = eventArgs.Frame;
    
                            if (this.switchRecognize)//处理代码
    
                            {
    
                                tempImg= this.recognizer.Recognize(tempImg);
    
                            }
    
                            System.Drawing.Imaging.BitmapData bmpData = tempImg.LockBits(new System.Drawing.Rectangle(0, 0, (int)sizeMemory.Width, (int)sizeMemory.Height),
    
                            System.Drawing.Imaging.ImageLockMode.ReadWrite, System.Drawing.Imaging.PixelFormat.Format32bppRgb);
    
                            /* Get the pointer to the pixels */
    
                            IntPtr pBmp = bmpData.Scan0;
    
                            int srcStride = bmpData.Stride;//步?长¡è
    
                            int pSize = srcStride * (int)sizeMemory.Height;
    
                            CopyMemory(map, pBmp, pSize);
    
                            tempImg.UnlockBits(bmpData);
    
                            tempImg.Dispose();//释放资源

                 GC.Collect();
    } if (bitmapSource != null) { bitmapSource.Invalidate(); } }, null); } if (captureLock) { try { lock (mutCurrentImg) { eventArgs.Frame.Save(imageFileName); } } catch (System.Exception ex) { } captureLock = false; } }

    在处理每帧图片的时候,可以做一些放大、缩小、校验等等操作,当然是比较耗费性能和内存的。这里我想要强调的是在处理图片之后会返回一个新的对象Bitmap,这个对象我们需要手动释放。如果不释放内存将会逐渐增加然后回到原点(刚启动摄像头并switchRecognize为真时为初内存,逐渐增加到原来的15倍左右就会回到原点。也就是托管的内存资源会自动释放,不过要等。)。

    到目前为止,加上

    tempImg.Dispose();//释放资源

    程序本身的内存停止增长,但是操作系统的整体内存还是在增长然后自动释放。这时候需要手动控制系统的垃圾收未使用的内存 GC.Collect();

    工作集

    这里用到啦CreateFileMapping创建映射内存,所以会考虑到工作集。

    所谓工作集是指进程已映射的物理内存部分(即这些内存块全在物理内存中,并且 CPU 可以直接访问),还有一部分不在工作集中的虚拟内存则可能在转换列表中(CPU 不能通过虚地址访问,需要 Windows 映射之后才能访问),还有一部分则在磁盘上的页面文件里。工作集在进程运行时会被 Windows 自动调整,频繁访问的页面(4KB 的块)会留在内存中,而不频繁访问的页面在内存紧张时会被从工作集中移出,暂时保存在内存中的“转换列表”中,或者进一步换出到页面文件中。当应用程序再次访问某一页面时,操作系统会将它重新加回工作集中。

    实现共享内存操作和释放代码:

      //内存共享类
        internal class Win32Mess
        {
    
            [DllImport("Kernel32.dll", EntryPoint = "RtlMoveMemory")]
            private static extern void CopyMemory(IntPtr Destination, IntPtr Source, int Length);
    
            [DllImport("user32.dll", CharSet = CharSet.Auto)]
            public static extern IntPtr SendMessage(IntPtr hWnd, int Msg, int wParam, IntPtr lParam);
    
            [DllImport("Kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
            public static extern IntPtr CreateFileMapping(int hFile, IntPtr lpAttributes, uint flProtect, uint dwMaxSizeHi, uint dwMaxSizeLow, string lpName);
    
            [DllImport("Kernel32.dll", CharSet = CharSet.Auto)]
            public static extern IntPtr OpenFileMapping(int dwDesiredAccess, [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, string lpName);
    
            [DllImport("Kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
            public static extern IntPtr MapViewOfFile(IntPtr hFileMapping, uint dwDesiredAccess, uint dwFileOffsetHigh, uint dwFileOffsetLow, uint dwNumberOfBytesToMap);
    
            [DllImport("Kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
            public static extern bool UnmapViewOfFile(IntPtr pvBaseAddress);
    
            [DllImport("Kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
            public static extern bool CloseHandle(IntPtr handle);
    
            [DllImport("kernel32", EntryPoint = "GetLastError")]
            public static extern int GetLastError();
    
            const int ERROR_ALREADY_EXISTS = 183;
    
            const int FILE_MAP_COPY = 0x0001;
            const int FILE_MAP_WRITE = 0x0002;
            const int FILE_MAP_READ = 0x0004;
            const int FILE_MAP_ALL_ACCESS = 0x0002 | 0x0004; //0xF001F;
    
            const int PAGE_READONLY = 0x02;
            const int PAGE_READWRITE = 0x04;
            const int PAGE_WRITECOPY = 0x08;
            const int PAGE_EXECUTE = 0x10;
            const int PAGE_EXECUTE_READ = 0x20;
            const int PAGE_EXECUTE_READWRITE = 0x40;
    
            const int SEC_COMMIT = 0x8000000;
            const int SEC_IMAGE = 0x1000000;
            const int SEC_NOCACHE = 0x10000000;
            const int SEC_RESERVE = 0x4000000;
    
            const int INVALID_HANDLE_VALUE = -1;
    
            IntPtr m_hSharedMemoryFile = IntPtr.Zero;
            IntPtr m_pwData = IntPtr.Zero;
            bool m_bAlreadyExist = false;
            bool m_bInit = false;
            public bool IsOpen
            {
                get { return this.m_bInit; }
            }
            long m_MemSize = 0;
    
            public Win32Mess()
            {
            }
            ~Win32Mess()
            {
                Close();
            }
    
            /// 
            /// 初始化共享内存
            /// 
            /// 共享内存名称
            /// 共享内存大小
            /// 
            public int Init(string strName, long lngSize)
            {
                if (lngSize <= 0 || lngSize > 0x00800000) lngSize = 0x00800000;
                m_MemSize = lngSize;
                if (strName.Length > 0)
                {
                    //创建内存共享体(INVALID_HANDLE_VALUE)
                    m_hSharedMemoryFile = CreateFileMapping(INVALID_HANDLE_VALUE, IntPtr.Zero, (uint)PAGE_READWRITE, 0, (uint)lngSize, strName);
                    if (m_hSharedMemoryFile == IntPtr.Zero)
                    {
                        m_bAlreadyExist = false;
                        m_bInit = false;
                        return 2; //创建共享体失败
                    }
                    else
                    {
                        if (GetLastError() == ERROR_ALREADY_EXISTS) //已经创建
                        {
                            m_bAlreadyExist = true;
                        }
                        else                                         //新创建
                        {
                            m_bAlreadyExist = false;
                        }
                    }
                    //---------------------------------------
                    //创建内存映射
                    m_pwData = MapViewOfFile(m_hSharedMemoryFile, FILE_MAP_ALL_ACCESS, 0, 0, (uint)lngSize);
                    if (m_pwData == IntPtr.Zero)
                    {
                        m_bInit = false;
                        CloseHandle(m_hSharedMemoryFile);
                        return 3; //创建内存映射失败
                    }
                    else
                    {
                        m_bInit = true;
                        if (m_bAlreadyExist == false)
                        {
                            //初始化
                        }
                    }
                    //----------------------------------------
                }
                else
                {
                    return 1; //参数错误     
                }
    
                return 0;     //创建成功
            }
            public InteropBitmap GetImage(System.Drawing.Size sizeMemory)
            {
                if (m_bInit)
                    return System.Windows.Interop.Imaging.CreateBitmapSourceFromMemorySection(m_hSharedMemoryFile, (int)sizeMemory.Width, (int)sizeMemory.Height, PixelFormats.Bgr32,
                         (int)(sizeMemory.Width * PixelFormats.Bgr32.BitsPerPixel / 8), 0) as InteropBitmap;
                else
                    return null;
    
            }
    
            /// 
            /// 关闭共享内存
            /// 
            public void Close()
            {
                if (m_bInit)
                {
                    UnmapViewOfFile(m_pwData);
                    CloseHandle(m_hSharedMemoryFile);//多次释放会报错,所以需要下行代码值零
                    m_hSharedMemoryFile = IntPtr.Zero;
                    m_bInit = false;
                }
            }
    
            /// 
            /// 读数据
            /// 
            /// 数据
            /// 起始地址
            /// 个数
            /// 
            public int Read(ref byte[] bytData, int lngAddr, int lngSize)
            {
                if (lngAddr + lngSize > m_MemSize) return 2; //超出数据区
                if (m_bInit)
                {
                    Marshal.Copy(m_pwData, bytData, lngAddr, lngSize);
                }
                else
                {
                    return 1; //共享内存未初始化
                }
                return 0;     //读成功
            }
    
            /// 
            /// 写数据
            /// 
            /// 数据
            /// 起始地址
            /// 个数
            /// 
            public int Write(byte[] bytData, int lngAddr, int lngSize)
            {
                if (lngAddr + lngSize > m_MemSize) return 2; //超出数据区
                if (m_bInit)
                {
                    Marshal.Copy(bytData, lngAddr, m_pwData, lngSize);
                }
                else
                {
                    return 1; //共享内存未初始化
                }
                return 0;     //写成功
            }
            public int Write(IntPtr lngAddr, int lngSize)
            {
                if (lngSize > m_MemSize) return 2; //超出数据区
                if (m_bInit)
                {
                    CopyMemory(m_pwData, lngAddr, lngSize);
                }
                else
                {
                    return 1; //共享内存未初始化
                }
                return 0;     //写成功
            }
        }
  • 相关阅读:
    斯托克斯定理(Stokes' theorem)
    记号的认识、公式的理解
    记号的认识、公式的理解
    Python 金融数据分析 (一)—— 股票数据
    Python 金融数据分析 (一)—— 股票数据
    开源项目
    开源项目
    感知机模型及其对偶形式
    感知机模型及其对偶形式
    jni编译non-numeric second argument to `wordlist' function错误
  • 原文地址:https://www.cnblogs.com/kissfu/p/3319844.html
Copyright © 2011-2022 走看看