【转】终于干了点正事。。三天用了三个库opencv、emgu、aforge.net[2011.7.30]

原文转自:

http://blog.csdn.net/tutuguaiguai0427/article/details/6646051

这阵子,确切说这几天,还是看了好多东西的。虽然无用功居多。

上篇日志说的东西做完以后暂时就没事了,然后窝实验室吹着空调做我的小屋。

后来实在觉得无聊找了点事做。

第一天是打算消除视频水印的。其实最土或者说其实最有效的方法是单帧PS,但是,明显我不是这么勤快的人。我学的可不是PS,总觉得这是搞设计之类的人用的。

然后记得上次在xiaotie博客看过程序除水印的,又翻出那篇文章,具体代码没有,只有思路。

虽然他说半透明的水印才可以去,不然修复不了。

但,为了消除那个彻底不透明的水印,我还是试了他的方法。

1.手动做mask图片。想想一个视频也就P一个图还是能承受的,如果不是手动的话这个程序可就麻烦了,何况效果不一定好。我先把视频用opencv播放,放一帧写一张图片,这样可以挑一张纯一点的图片方便抠水印。

2.试验单张图片效果。随便载入一张有那个水印的图片,然后用PS的水印图片做MASK,用inpaint函数。调了几下半径,效果也就一般,可以去掉水印但是那一块地方总有杂色。如果视频本来就不清晰,杂色比较多,或者需要重新打上你自己的水印(这个比较邪恶)那还行。MASK不同出来的效果也不同,我试过精确按文字形状的和直接抹成一条的各种mask。有的出来是一团杂色,有的则是一小块一小块的。

3.其实我没做3,第二步效果好的话其实第三步就是类似于批处理了,就是播放视频,读帧,处理,写帧。然后就木有然后了。

需要注意的是用inpaint函数的时候,应该说用mask的时候,那个mask不是直接用PS涂成黑白就可以的。mask需要单通道8位的图片,试了几次失败以后我就把图片载入,然后在程序处理成8位单通道。处理完也可以存盘,然后以后直接读那个图作为MASK就可以了。处理的时候用threshold()函数处理一下,每个像素不是0就是1。用mask的时候就不处理0的点了。

然后那个就告一段落了,再做一个视频捕捉,播放,截图,录制功能的软件,图片还要增加文字和当前系统时间,界面用C#。

出于惯性思维直接打开opencv,一小时之内绝对能搞定。然后C#写界面,C++托管,搞定。然后悲剧的根源就是试图将opencv跳出的框塞进C#,反正就那效果,懂得。

其实之前就有这个问题,C#+opengcv那个播放视频的窗口固定不了,只能是从界面蹦出来的。但是当时逃避了一下,后来改用了WMP的控件,因为那次只是播放本地的视频,WMP还直接支持滚动条前进后退的,真爽。但这次是逃不过了。纠结于各种诸如bitmap、句柄之类的问题后,发现可以用设置父窗口的办法。

[cpp] view plaincopy

  1. cvNamedWindow("Capture");
  2. // 将这个窗口缩至最小
  3. cvResizeWindow("Capture",1,1);
  4. // 获取窗口句柄
  5. HWND hWnd = (HWND) cvGetWindowHandle("Capture");
  6. // 获取该窗口的父窗口句柄
  7. HWND hParent = ::GetParent(hWnd);
  8. // 获取C#form1窗口句柄
  9. HWND hwnd1=::FindWindowW(NULL,L"Form1");
  10. //HWND hwnd2=::FindWindowEx(hwnd1,NULL,NULL,L"pictureBox1");//这个居然就失败,会定位到桌面的左上角HWND hwnd3=::FindWindowEx(hwnd1,NULL,NULL,NULL);
  11. if(!hwnd3)cvNamedWindow("C");//其实这句作用类似于message,我随手写的,神奇的是,不加这句的时候怎么都不行,一加居然就好了,然后我也就没改
  12. // 将GUI窗口设置为视频播放窗口的父窗口,使视频在 GUI 的指定区域播放
  13. ::SetParent(hWnd, hwnd3);
  14. // 隐藏所创建的视频播放窗口 ::ShowWindow(hParent, SW_HIDE);

但是这样还是会先跳出一个框,然后它就钻进C#的界面了,估计电脑卡会很明显。呜呜。

之前用opencv的时候都是用waitKey的办法用键盘控制录制、截图之类的功能。

但是按键的时候焦点肯定需要在opencv的窗口,于是又悲剧了。

花了很久都没有搞定,不知道怎么让焦点选到那个跳出的窗口,此时已经是隐藏了的。

反正我到现在还不知道怎么搞。在这荒凉到长草的博客里,我想应该也不会有几个人看我日志,然后就更没什么人会解答这个问题了吧。

想了很久,觉得其实就这样几个思路,一是想办法把那个隐藏的设为焦点,二是传递事件,从C#传到dll里的C++,三是opencv写的那部分只返回图片,还是要bitmap的。

前两个我都失败了,第三个各种纠结以后发现如果不在opencv转换的话也不行,C#和c++都只认识自己的图片的类型,据说CLR也是可以支持C#那个,但是我的不行。

opencv转换有一个函数,2.2版本刚好取消,有人把它抠出来,我添加以后提示缺少一个头文件,加入以后发现是MFC的,然后配置也要改,改完不支持原来的。总之,也失败了。

求助师兄的时候他说那些按键的控制不能写在opencv,必须从opencv返回图片,至于转换他是内存RGB流写成bitmap。于是,我知道,我的路走不下去了。等转换完这效率都不知道啥样了。

网上搜的那些大部分都用的是emgu,在C#用托管用opencv的貌似不多。我也发现这样调试不方便。

继续挣扎了很久,未遂,决定用MFC,但是,又放弃了,重回C#。

这次选择了emgu。果然很方便,不用托管,函数也现成。

满怀希望的运行,发现摄像头显示的画面始终黑色,自己加的文字可以看到。

去emgu自带的例子运行,也是这个情况。

然后我就崩溃了,上次用emgu就是各种配置问题,当时opencv和emgu都换成64位就可以了,这次连64都不行啊。程序在别人32的机子上跑,emgu换成32位,工程也选择32位,连一帧都没取到。ORZ。

挣扎了很久我决定继续放弃emgu,然后,目标转向Aforge.NET。当时就听说它很强大但是资料很少。山穷水尽的时候管它有没有资料,反正摄像头捕捉这种对视觉库本来就感觉有点杀鸡用牛刀的意思。从来没接触过这个,下载,安装。发现最新版本是27号才发布的,里面刚好添加了写视频文件的新的类。NICE。

跟emgu一样,开发效率也很高。这次吸取教训先试试系统自带例子能否运行。事实证明很成功。

放心大胆的写。也没多久就OK了。运行。又崩溃。那个新添加的库无法加载。"Could not load file or assembly ‘AForge.Video.FFMPEG.dll‘ or one of its dependencies. The specified module could not be found."想死的心都有了。

这个库果然资料很少。找到官网的论坛,发现整个论坛AFoge.NET Framework部分只有为数不多的人发个帖子问问题,然后基本只有管理员在回答。

管理员的location还是英国。不知道是哪国人,反正都是英语发帖。

发了个帖子问完以后因为上一天寝室太热一整晚没睡着所以就趴着睡了觉。睡醒发现管理员回复了。让我把Externals\ffmpeg\bin下的dll自己拷到工程的output文件夹。照做以后

“Mixed mode assembly is built against version ‘v2.0.50727‘ of the runtime and cannot be loaded in the 4.0 runtime without additional configuration information.",继续把错误信息发到帖子上。很快管理员就回复了。真好的人啊。给了我一个帖子的链接,是google出来的结果,还很含蓄的告诉我要勤于google。汗。

第一种方法是修改app.exe.config

[html] view plaincopy

  1. <?xml version="1.0"?>
  2. <configuration>
  3. <startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0,Profile=Client"/></startup></configuration>

第二种是把4.0降下来。

因为没有成功编译,所以我没有那个config文件。(后来想想真傻,把那个库注释掉不就行了么。)

所以只能降成.NET3.5。还自己编译了2.0的dll。再编译我的工程。结果那个之前出问题的dll居然依赖.NET4.0的文件。ORZ。

于是我只能换回来4.0。这时候居然发现可以运行了说。但保险起见我还是把config给修改了。

再跑的时候发现录制的时候我可以用USB的摄像头,笔记本的不能用。预览都可以的。

再问管理员GG,人家又迅速答复了,说这个库不认你用的是啥设备,应该是别的问题。

然后当我把fps设置去掉的时候,自带的可以用了,USB的罢工了。

之后就是尝试各种fps,发现设置8的时候都可以用。

用系统自带的例子测了下摄像头的fps,USB的就8-9,自带的9-10的样子,因为那个是动态测量的。

然后就只能设fps,试试会不会挂了。

还有之前说的加时间加文字。时间很好实现,C#有对应的函数。但opencv是不支持添加中文的字符串的,emgu所以也不支持。用aforge.NET的时候就可以了。opencv下有人是安装字库来实现的,看着好复杂。

至于很多人也有的一个问题,就是录进去的视频特别快。尤其我这样添加了时间,走快了很明显。

今天终于想通了。我太高估我摄像头了。AVI的帧率设的25,以前没发现摄像头连它一半帧率都没到,也就是一秒才捕10帧,我楞写25帧到avi,当然就走的快了,再加压缩的时候应该也是有损失的。但是当我把文件设到很低的时候有时候有会出错,跟先前设fps的时候一样的错误,说视频文件无法打开(其实就是创建)。

写到这里的时候我突然在想,如果还是fps25,忽略连贯的问题,只考虑准确走时,也许可以设一个定时器,固定时间写入,不管有没有新帧,反正某个变量里面有新帧就替换,没有就继续写原来的。一会试试,这个估计不太花时间。如果还是不行就先这样吧。

因为现在有新任务了,做视频摘要。

贝贝加油,哦耶。

时间: 2024-10-10 06:28:54

【转】终于干了点正事。。三天用了三个库opencv、emgu、aforge.net[2011.7.30]的相关文章

终于&quot;干死了&quot;拖延症

# 就在几十分钟前终于"干死了"拖延症 七月份就说了要学会使用git 4-5个月过去了还是0 今天终于上手了 # 以后我的代码就会commit到git 代码则主要是js, python, fp相关 # 此时几乎是人生最隐忍的时候 斗志, 情感, 经济都是灰色 周围安静的像是惊悚电影 不过这时候才适合思考 加油, 你想要的 end- -

大胆地去做自己坚信的事情,去做不伤害国家和客户的事情 做企业一定要专注。为企业制定战略目标,绝对不能超过三个。超过三个,你就记不住了,员工也记不住

注:马云认为,我们不勤奋,也不聪明,结果我们这些人都变成了富翁,是什么原因?因为我们的运气好,我们其实很傻,一些聪明的人被别的公司挖走了,剩下的人不聪明,没有人来挖,结果居然变得这么有钱,只有眼光看得远,才能走得更远. 红旗出版社最新出版的<马云内部讲话:相信明天>(修订本)已于近日上市,本书新增了 80% 左右首次披露的马云讲话.其中他看待自己和阿里巴巴的员工的观点很符合这个外星人的思维. 马云说,四五年前阿里巴巴招员工很难,现在招员工很容易,街上会走路的人都被我们招来了.我们不勤奋,也不聪

lanczos算法及C++实现(三)实对称三对角阵特征值分解的分治算法

本文属作者原创,转载请注明出处 http://www.cnblogs.com/qxred/p/dcalgorithm.html 本系列目录: lanczos算法及C++实现(一)框架及简单实现 lanczos算法及C++实现(二)实对称阵奇异值分解的QR算法 lanczos算法及C++实现(三)实对称三对角阵特征值分解的分治算法 0. 参考文献 https://en.wikipedia.org/wiki/Divide-and-conquer_eigenvalue_algorithm A. Mel

c语言代码编程题汇总:将三个随机的三个数按从大到小输出

将三个随机的三个数按从大到小输出 程序代码如下: 1 /* 2 2017年3月12日17:55:24 3 功能:将三个随机的三个数按从大到小输出 4 */ 5 #include"stdio.h" 6 void fun(int ,int ,int ); 7 void fun1(int , int ); 8 int main() 9 { 10 int a,b,c; 11 printf("please input three number :"); 12 scanf(&q

Android Gradle Pluin指南(三)——依赖关系、android库和多项目配置

原文地址:http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Dependencies-Android-Libraries-and-Multi-project-setup 4.Dependencies,Android Libraries and Multi-project setup(依赖关系,Android库和多项目设置) Gradle项目可以依赖于其它组件.这些组件可以是外部二进制包,或者是其它的Gradle项

ubuntu/linux mint 创建proc文件的三种方法(三)

在做内核驱动开发的时候,可以使用/proc下的文件,获取相应的信息,以便调试. 大多数/proc下的文件是只读的,但为了示例的完整性,都提供了写方法. 方法一:使用create_proc_entry创建proc文件(简单,但写操作有缓冲区溢出的危险): 方法二:使用proc_create和seq_file创建proc文件(较方法三简洁): 方法三:使用proc_create_data和seq_file创建proc文件(较麻烦,但比较完整): 示例四:在proc文件中使用内核链表的一个示例(用的方

Lucene.Net 2.3.1开发介绍 —— 三、索引(三)

原文:Lucene.Net 2.3.1开发介绍 -- 三.索引(三) 3.Field配置所产生的效果 索引数据,简单的代码,只要两个方法就搞定了,而在索引过程中用到的一些类里最简单,作用也不小的就是Field,接下来看看Field的各项设置都会有什么样的效果. 代码 3.1 Code 1/**//// <summary> 2/// 索引数据 3/// </summary> 4private void Index() 5{ 6    Analyzer analyzer = new S

linux C(hello world)三个数最大和三个数最新

linux C(hello world)三个数最大和三个数最新

第一章:大三和弦与小三和弦,四部和声

大三和弦: 小三和弦: 增三与减三也很常用啦 四部和声: 重复音:某个音出现重复,通常是根音 声部交叉是禁止的