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(, , (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 = ; 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 = -; 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 = ; public Win32Mess()
{
}
~Win32Mess()
{
Close();
} ///
/// 初始化共享内存
///
/// 共享内存名称
/// 共享内存大小
///
public int Init(string strName, long lngSize)
{
if (lngSize <= || lngSize > 0x00800000) lngSize = 0x00800000;
m_MemSize = lngSize;
if (strName.Length > )
{
//创建内存共享体(INVALID_HANDLE_VALUE)
m_hSharedMemoryFile = CreateFileMapping(INVALID_HANDLE_VALUE, IntPtr.Zero, (uint)PAGE_READWRITE, , (uint)lngSize, strName);
if (m_hSharedMemoryFile == IntPtr.Zero)
{
m_bAlreadyExist = false;
m_bInit = false;
return ; //创建共享体失败
}
else
{
if (GetLastError() == ERROR_ALREADY_EXISTS) //已经创建
{
m_bAlreadyExist = true;
}
else //新创建
{
m_bAlreadyExist = false;
}
}
//---------------------------------------
//创建内存映射
m_pwData = MapViewOfFile(m_hSharedMemoryFile, FILE_MAP_ALL_ACCESS, , , (uint)lngSize);
if (m_pwData == IntPtr.Zero)
{
m_bInit = false;
CloseHandle(m_hSharedMemoryFile);
return ; //创建内存映射失败
}
else
{
m_bInit = true;
if (m_bAlreadyExist == false)
{
//初始化
}
}
//----------------------------------------
}
else
{
return ; //参数错误
} return ; //创建成功
}
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 / ), ) 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 ; //超出数据区
if (m_bInit)
{
Marshal.Copy(m_pwData, bytData, lngAddr, lngSize);
}
else
{
return ; //共享内存未初始化
}
return ; //读成功
} ///
/// 写数据
///
/// 数据
/// 起始地址
/// 个数
///
public int Write(byte[] bytData, int lngAddr, int lngSize)
{
if (lngAddr + lngSize > m_MemSize) return ; //超出数据区
if (m_bInit)
{
Marshal.Copy(bytData, lngAddr, m_pwData, lngSize);
}
else
{
return ; //共享内存未初始化
}
return ; //写成功
}
public int Write(IntPtr lngAddr, int lngSize)
{
if (lngSize > m_MemSize) return ; //超出数据区
if (m_bInit)
{
CopyMemory(m_pwData, lngAddr, lngSize);
}
else
{
return ; //共享内存未初始化
}
return ; //写成功
}
}
C# WPF 显示图片和视频显示 EmuguCv、AForge.Net测试(续)的更多相关文章
- C# WPF 显示图片和视频显示 EmuguCv、AForge.Net测试
WPF 没有用到 PictureBox, 而是用Image代替. 下面我试着加载显示一个图片 . XAML <Image x:Name="srcImg"Width=" ...
- WPF显示图片
1.WPF显示图片内部一部分 <Rectangle Height="> <Rectangle.Fill > <ImageBrush ImageSource=&q ...
- wpf image控件循环显示图片 以达到动画效果 问题及解决方案
1>最初方案: 用wpf的image控件循环显示图片,达到动画效果,其实就是在后台代码动态改变Image.Source的值,关键代码: ; i < ; i++)//六百张图片 { Bitm ...
- WPF 获取元素(Visual)相对于屏幕设备的缩放比例,可用于清晰显示图片
原文:WPF 获取元素(Visual)相对于屏幕设备的缩放比例,可用于清晰显示图片 我们知道,在 WPF 中的坐标单位不是屏幕像素单位,所以如果需要知道某个控件的像素尺寸,以便做一些与屏幕像素尺寸相关 ...
- C# wpf image绑定viewModel没有显示图片
在wpf绑定图片,用viewModel的图片绑定image 我是用viewModel.cs public class viewModel:INotifyPropertyChanged { #regio ...
- WPF 标签预览可以显示图片运行后不显示
使用<Image HorizontalAlignment="Left" Height="100" Margin="106,111,0,0&quo ...
- EmguCV控件Emgu.CV.UI.ImageBox及C# picturebox显示图片连续刷新出现闪烁问题
在上一篇里,EmguCV(OpenCV)实现高效显示汉字及叠加 实现了视频叠加及显示,但存在问题,就是 Emgu.CV.UI.ImageBox及C# picturebox显示图片时都会出现闪烁,尤其 ...
- wpf显示视频,image控件闪屏,使用winform控件实现
使用C#调用mingw的动态库实现视频识别软件,程序通过C++调用opencv打开视频,将图像的原始数据以rgb24的方式传递给C#端,C#通过构造图像对象给控件赋值的方式显示图片. 一开始使用wpf ...
- WPF 修改图片颜色
原文:WPF 修改图片颜色 本文告诉大家如何修改图片的颜色,如去掉图片的蓝色 在 WPF 可以使用很多图片处理的方法,本文告诉大家的是一个图片处理,可以把处理的图片保存在文件. 在阅读本文,我假设大家 ...
随机推荐
- 纯CSS3实现兔斯基简单害羞表情
前言 很不巧前天突然就感冒了,都怪自己吃太多饼干导致上火了.整个人都无精打采.本来想多做几个兔斯基表情的,但身体发热很难受.所以就只完成一个简单点的表情耍一耍. 正文 先看一下这个简单到不能再简单的小 ...
- es2自动发现插件
https://www.elastic.co/guide/en/elasticsearch/plugins/current/discovery-multicast-usage.html http:// ...
- C++ List的用法(整理)
转自http://blog.csdn.net/lskyne/article/details/10418823 Lists将元素按顺序储存在链表中. 与 向量(vectors)相比, 它允许快速的插入和 ...
- echo "scale=100; a(1)*4" | bc -l 输出圆周率
突然看到echo "scale=100; a(1)*4" | bc -l可以输出圆周率,很惊奇,后来发现很简单. 首先bc是“basic calculator”的缩写,就是初级的计 ...
- Linux常用指令---工作
查看所有用户cat /etc/passwd 复制整个目录cp -ri A/B/* A1/B1/ 若复制过程中询问是否覆盖,输入y按回车 另外若A A1不在同一目录下,最好填绝对路径,就是/xxx/xx ...
- 第十章 系统级I/O
第十章 系统级I/O 一.Unix I/O 1.一个unix文件就是一个m个字节的序列 2.unix外壳创建的每个进程开始时都有三个打开的文件:标准输入(0) .标准输出(1)和标准错误(-1). 二 ...
- iOS中UIMenuController的使用
不知你有没有发现,在你的微信朋友中,长按一段文字(正文或者评论),会弹出这样子的玩意: 要想在你的view或者viewController中实现长按弹出菜单栏你必须要调用becomeFirstResp ...
- Python数据可视化编程实战——导入数据
1.从csv文件导入数据 原理:with语句打开文件并绑定到对象f.不必担心在操作完资源后去关闭数据文件,with的上下文管理器会帮助处理.然后,csv.reader()方法返回reader对象,通过 ...
- 记”Uri.IsWellFormedUriString”中的BUG
场景 先上逻辑代码 1: /// <summary> 2: /// 图片真实地址 3: /// </summary> 4: public string FullImagePat ...
- linq入门系列导航
写在前面 为什么突然想起来学学linq呢?还是源于在跟一个同事聊天的时候,说到他们正在弄得一个项目,在里面用到了linq to sql.突然想到距上次使用linq to sql是三年前的事情了.下班回 ...