C# 使用OpenCV 类VideoCapture 和 Mat的正确方法

embedded/2024/12/22 15:06:29/

在做WPF桌面程序时候,要调用USB摄像头,因此接触了OpenCV , 遇到了各种坑,严重烧肝终于找到原因。 涉及的类包括VideoCapture , Mat. 

问题1.内存泄漏 

运行以下 代码片段,会发现内存持续飙升

                for (int i = 0; i < 1000; i++){using (Mat image = new Mat())using (VideoCapture capture = VideoCapture.FromCamera(1)){ capture.Read(image);Cv2.WaitKey(1000);capture.Release();image.Release();} }

解决办法:

把代码行:

using (VideoCapture capture = VideoCapture.FromCamera(1))

改成以下(指定API格式),内存立即平稳:

using (VideoCapture capture = VideoCapture.FromCamera(1,VideoCaptureAPIs.DSHOW))

在github OpenCV的项目讨论中找到的灵感,不得不说洋人讨论问题还是比较用心和无私。

问题2.尝试读取或写入受保护的内存。这通常指示其他内存已损坏。

这个问题出现的很隐蔽,直到我从网上一片文章找到的观点“非托管内存对象,实例化最好当场用掉,不要通过回调/事件等在线程之间传来传去” ,才知道可能的问题: 我源代码有把Mat对象传给百度人脸SDK处理(寻找人脸,画框之类的),然后通过回调函数把Mat对象交给UI线程显示。因此,我首先保守的把Mat 变量用using方式使用(用完立即回收),然后把要传给UI线程的Mat对象克隆一份交给视图使用(也许不是最佳的效率),然后问题迎刃而解。修改后的代码片段如下:

using (Mat image = new Mat())
{isWorking = true;cap.Read(image); // same as cvQueryFrameif (!image.Empty()){BDFaceTrackInfo[] track_info = new BDFaceTrackInfo[ilen];for (int i = 0; i < ilen; i++){track_info[i].box = new BDFaceBBox();track_info[i].box.score = 0;track_info[i].box.width = 0;track_info[i].landmark.data = new float[144];track_info[i].face_id = 0;} int faceSize = ilen;//返回人脸数  分配人脸数和检测到人脸数的最小值int curSize = ilen;//当前人脸数 输入分配的人脸数,输出实际检测到的人脸数int type = 0;IntPtr ptT = Marshal.AllocHGlobal(sizeTrack * ilen);faceSize = track(ptT, image.CvPtr, type);for (int index = 0; index < faceSize; index++){IntPtr ptr = new IntPtr();if (8 == IntPtr.Size){ptr = (IntPtr)(ptT.ToInt64() + sizeTrack * index);}else if (4 == IntPtr.Size){ptr = (IntPtr)(ptT.ToInt32() + sizeTrack * index);}track_info[index] = (BDFaceTrackInfo)Marshal.PtrToStructure(ptr, typeof(BDFaceTrackInfo));}Marshal.FreeHGlobal(ptT);FaceDraw.draw_rects( image, faceSize, track_info);uiThread(image.Clone()); Console.WriteLine("mat not empty");}else{Console.WriteLine("mat is empty");}
}

注意:

using (Mat image = new Mat()) 

uiThread(image.Clone());

最后祝同学们debug愉快,也许我的一小步,是码友们一大步:)


http://www.ppmy.cn/embedded/102128.html

相关文章

人工数据的没落:APIGen的崛起

APIGen全面解析 ©作者|Angela 来源|神州问学 引言 在现代软件工程中&#xff0c;确保应用程序的质量和可靠性已经变得至关重要。高质量的测试数据是实现这一目标的基石。Salesforce AI Research团队近日宣布&#xff0c;他们已成功开发出一种名为APIGen的创新技术&#…

游戏发行技术体系框架图

有朋友问&#xff0c;不知道各个模块之间的关系。简单画个框架图&#xff1a; 几个注意事项&#xff1a; 测试和运维是覆盖全周期的其它的可以根据是否相邻判断业务相关。三方理论上应该都有SDK接入。 存在一部分三方SDK从业务角度无需经过SDK&#xff0c;游戏较少或排期紧张…

水库大坝预警系统的力量

在自然界与人类社会的和谐共生中&#xff0c;水库作为重要的水利基础设施&#xff0c;不仅承担着防洪、灌溉、供水、发电等多重功能&#xff0c;更是保障民生安全、促进经济发展的生命线。然而&#xff0c;水库大坝一旦遭遇极端天气、地质灾害或管理不善等因素&#xff0c;其安…

一文get透欧美搜索套利offer推广OutBrain原生广告优势分析

解锁数字营销新境界&#xff1a;欧美搜索套利下的OutBrain原生广告优势深度剖析 在数字营销日新月异的今天&#xff0c;如何精准触达目标受众&#xff0c;实现高效转化&#xff0c;成为众多品牌与广告主关注的焦点。特别是在欧美市场&#xff0c;搜索套利&#xff08;Search Ar…

TCP的报文段结构与TCP编程的小工具

TCP协议的报文由两个主要部分组成&#xff1a;TCP首部和数据部分。TCP首部是控制TCP连接和传输的重要部分&#xff0c;而数据部分则包含了实际要传输的应用层数据。 TCP报文段结构 一个完整的TCP报文段包括TCP首部和数据部分。 TCP首部结构 TCP首部的标准长度是 20 字节&am…

22:【stm32】定时器三:输出比较

输出比较 1、简介2、标准库编程 1、简介 通过CCR里面的值和计数器CNT里面的值进行比较&#xff0c;然后输出高电平/单片机&#xff0c;进而产生需要的信号。 如上图所示&#xff0c;预分频器71&#xff0c;则最小单元为1us&#xff0c;自动重装器为999&#xff0c;则周期为1ms…

【Three.js基础学习】19.Custom models with Blender

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 前言 blender模型资源:【blender】一个汉堡包-CSDN博客 一、代码 import ./style.css import * as THREE from three import { OrbitControls } from three/examples/jsm/co…

Ubuntu20.04下解决ROS与Anaconda冲突,取消终端默认base虚拟环境

0. 背景知识 在Ubuntu系统中&#xff0c;存在两个python&#xff1a;python2.7和python3.8&#xff08;注意这两个版本不可删除&#xff0c;否则Ubuntu系统瘫痪&#xff09;&#xff1b;装了anaconda后&#xff0c;出现了第三个版本的python3.9。 因此系统中三个版本python&a…