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 可以使用很多图片处理的方法,本文告诉大家的是一个图片处理,可以把处理的图片保存在文件. 在阅读本文,我假设大家 ...
随机推荐
- android应用中去掉标题栏的方法
现在我坚定的认为写技术博客对自己有很大的帮助,写博客给自己一个学而思的机会. 在Android中去掉标题栏有三种方法,它们也有各自的特点. 1.在代码里实现 this.requestWindowFea ...
- 用Swift GestureRecognizer 的几个注意点
最近做了一些关于 GestureRecognizer 的工作 ,随笔记录一些需要注意的点: 1. PanGestureRecognizer (1)在使用时 注意在哪个view添加了 手势识别 self ...
- SQL SERVER with递归示例一则
WITH SUBQUERY AS ( SELECT ORGID FROM OM_ORGANIZATION WHERE PARENTORGID = 'ROOT' UNION ALL SELECT B.O ...
- js实现倒计时 类似团购网站
一.demo与效果展示 为节约时间,我就直接套用了企鹅团的界面作为demo的背景.因为是倒计时,所以需要一个固定的时间,为了n年后,某位仁兄打开demo页面依然在倒计时,所以我把倒计时时间设成了205 ...
- ASP.NET Web API路由规则(二)
默认的规则 在ASP.NET MVC4中 global.asax.cs代码中并无注册默认路由规则的代码 代码如下: public class WebApiApplication : System.We ...
- ZooKeeper学习第四期---构建ZooKeeper应用
一.配置服务 配置服务是分布式应用所需要的基本服务之一,它使集群中的机器可以共享配置信息中那些公共的部分.简单地说,ZooKeeper可以作为一个具有高可用性的配置存储器,允许分布式应用的参与者检索和 ...
- matlab如何连同换行也输入txt中
\r是回车符,\n是换行符,两者结合方能在txt显示为换行 fidID = fopen('test.txt', 'w+'); str='string'; fprintf(fidID,'%s \r\n' ...
- 信息安全系统设计基础第一次实验报告 20135201&&20135306&&20135307
信息安全系统设计基础实验 班级: 201353 姓名:张忻 张嘉琪 黄韧 学号:20135301 20135307 20135306 实验日期:2015.11.10 实验名称: S3C2410的lin ...
- 如何自学 Android 编程?
最近知乎上有网友问我怎么自学Android,其实说实在的,我学的也一塌糊涂,当然在学习过程也积累了一些知识,对于以前没接触过Android的朋友,或者刚入门Android 的朋友,这篇文章作为入门,那 ...
- Bootstrap系列 -- 26. 下拉菜单标题
Bootstrap下拉菜单中使用 dropdown-header 来显示菜单标题,和上一篇说道的分割线一样 <div class="dropdown"> <but ...