OpenCV(EmguCV)2.1新特性介绍之图像差异StereoSGBM与设置窗口属性SetWindowProperty(StereoSGBM Of OpenCV 2.1)

作者:王先荣


    上次介绍了OpenCV2.1中新增的图像分割算法GrabCut,本文将介绍StereoSGBM与SetWindowProperty。其中StereoSGBM用于计算两幅图像间的差异图,跟已有的StereoBM和StereoGC作用一样,算法不同而已;SetWindowProperty用于设置窗口的属性,目前仅可用于设置全屏属性。

比较图像间的差异StereoSGBM
    StereoSGBM用于计算两幅图像间的差异图,在OpenCV的在线文档中有非常详细的介绍,地址是:“http://opencv.willowgarage.com/documentation/cpp/camera_calibration_and_3d_reconstruction.html#stereosgbm”。参数非常多,如果不使用默认的参数,需要仔细查看每个参数的说明,以免出错。OpenCV的具体实现在命名空间cv中的StereoSGBM类,目前还没有对应的C风格封装;EmguCV将其封装在StereoSGBM类中。
    StereoSGBM除了参数很多之外,使用起来蛮简单的,如下所示:

//创建StereoSGBM对象
StereoSGBM sgbm = new StereoSGBM((int)nudMinDisparity.Value, (int)nudNumDisparities.Value, (int)nudSADWindowSize.Value, (int)nudP1.Value,
(
int)nudP2.Value, (int)nudDisp12MaxDiff.Value, (int)nudPreFilterCap.Value, (int)nudUniquenessRatio.Value,
(
int)nudSpeckleWindowSize.Value, (int)nudSpeckleRange.Value, chkFullDP.Checked);
//查找两幅图像间的相关性(差异)
sgbm.FindStereoCorrespondence(leftImage, rightImage, disparityImage);
//显示结果
pbDisparity.Image = disparityImage.Bitmap;
//释放资源
sgbm.Dispose();

 

 

完整的示例(附带了StereoBM和StereoGC的示例)请看:

StereoSGBM完整示例
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
using System.Runtime.InteropServices;
using Emgu.CV;
using Emgu.CV.CvEnum;
using Emgu.CV.Structure;

namespace NewFeaturesOfOpenCV2._1
{
public partial class FormStereoCorrespondence : Form
{
//私有成员
private string leftImageFileName = "wky_sls_2272x1704.jpg"; //左边的图像文件名
private string rightImageFileName = "wky_sls_2272x1704_2.jpg"; //右边的图像文件名
private Image<Gray, Byte> leftImage = null; //左边的灰度图像
private Image<Gray, Byte> rightImage = null; //右边的灰度图像
private Image<Gray, Int16> disparityImage = null; //差异图像
private Stopwatch sw = new Stopwatch(); //计时器

public FormStereoCorrespondence()
{
InitializeComponent();
}

//设置SGBM的默认参数
private void btnFillDefaultParameters_Click(object sender, EventArgs e)
{
nudSADWindowSize.Value
= 3;
nudP1.Value
= 0;
nudP2.Value
= 0;
nudDisp12MaxDiff.Value
= 0;
nudPreFilterCap.Value
= 0;
nudUniquenessRatio.Value
= 0;
nudSpeckleWindowSize.Value
= 0;
nudSpeckleRange.Value
= 0;
chkFullDP.Checked
= false;
}

//设置SGBM的推荐参数
private void btnFillRecommendedParameters_Click(object sender, EventArgs e)
{
nudUniquenessRatio.Value
= 5;
nudSpeckleWindowSize.Value
= 50;
nudSpeckleRange.Value
= 16;
}

//窗体加载时
private void FormStereoCorrespondence_Load(object sender, EventArgs e)
{
//设置提示
toolTip.SetToolTip(nudNumDisparities, "必须大于0,且能被16除尽");
toolTip.SetToolTip(nudSADWindowSize,
"缺省为0;如果指定则必须是正奇数,推荐值为3~11");
toolTip.SetToolTip(nudP1,
"缺省为0;推荐值为8*number_of_image_channels*SADWindowSize*SADWindowSize");
toolTip.SetToolTip(nudP2,
"缺省为0;如果指定则P2>P1,推荐值为32*number_of_image_channels*SADWindowSize*SADWindowSize");
toolTip.SetToolTip(nudDisp12MaxDiff,
"如果设置为负值,则跳过左右差异检查");
toolTip.SetToolTip(nudUniquenessRatio,
"缺省为0,推荐值为5~15");
toolTip.SetToolTip(nudSpeckleWindowSize,
"缺省为0,推荐值为50~200");
toolTip.SetToolTip(nudSpeckleRange,
"缺省为0;如果指定则必须是能被16整除的正数,推荐值为16或者32");
//初始化图像
InitImage(true);
InitImage(
false);
}

//加载图像1
private void btnLoadLeftImage_Click(object sender, EventArgs e)
{
LoadImage(
true);
}

//加载图像2
private void btnLoadRightImage_Click(object sender, EventArgs e)
{
LoadImage(
false);
}

/// <summary>
/// 加载图像
/// </summary>
/// <param name="isLeft">是左边的图像吗?</param>
private void LoadImage(bool isLeft)
{
OpenFileDialog ofd
= new OpenFileDialog();
ofd.CheckFileExists
= true;
ofd.DefaultExt
= "jpg";
ofd.Filter
= "图片文件|*.jpg;*.png;*.bmp|所有文件|*.*";
if (ofd.ShowDialog(this) == DialogResult.OK)
{
if (ofd.FileName != "")
{
if (isLeft)
leftImageFileName
= ofd.FileName;
else
rightImageFileName
= ofd.FileName;
InitImage(isLeft);
}
}
ofd.Dispose();
}

/// <summary>
/// 初始化图像
/// </summary>
/// <param name="isLeft">是左边的图像吗?</param>
private void InitImage(bool isLeft)
{
if (isLeft)
{
Image
<Bgr, Byte> image = new Image<Bgr, byte>(leftImageFileName);
pbLeft.Image
= image.Bitmap;
if (leftImage != null)
leftImage.Dispose();
leftImage
= image.Convert<Gray, Byte>();
if (disparityImage != null)
disparityImage.Dispose();
disparityImage
= new Image<Gray, short>(leftImage.Size);
image.Dispose();
}
else
{
Image
<Bgr, Byte> image = new Image<Bgr, byte>(rightImageFileName);
pbRight.Image
= image.Bitmap;
if (rightImage != null)
rightImage.Dispose();
rightImage
= image.Convert<Gray, Byte>();
image.Dispose();
}
}

//开始计算
private void btnCalc_Click(object sender, EventArgs e)
{
if (leftImage.Size != rightImage.Size)
{
MessageBox.Show(
this, "两幅图像的尺寸不一致,不能比较。", "错误提示");
return;
}
if (tcStereo.SelectedTab == tpStereoSGBM)
{
StereoSGBM sgbm
= new StereoSGBM((int)nudMinDisparity.Value, (int)nudNumDisparities.Value, (int)nudSADWindowSize.Value, (int)nudP1.Value,
(
int)nudP2.Value, (int)nudDisp12MaxDiff.Value, (int)nudPreFilterCap.Value, (int)nudUniquenessRatio.Value,
(
int)nudSpeckleWindowSize.Value, (int)nudSpeckleRange.Value, chkFullDP.Checked);
sw.Stop();
sw.Start();
sgbm.FindStereoCorrespondence(leftImage, rightImage, disparityImage);
sw.Stop();
pbDisparity.Image
= disparityImage.Bitmap;
sgbm.Dispose();
lblStatus.Text
= string.Format("SGBM比较耗时{0:F04}毫秒。", sw.ElapsedMilliseconds);
}
else if (tcStereo.SelectedTab == tpStereoBM)
{
STEREO_BM_TYPE type
= cbBMType.Text == "BASIC" ? STEREO_BM_TYPE.BASIC : (cbBMType.Text == "FISH_EYE" ? STEREO_BM_TYPE.FISH_EYE : STEREO_BM_TYPE.NARROW);
StereoBM bm
= new StereoBM(type, (int)nudBMNumberOfDisparities.Value);
sw.Stop();
sw.Start();
bm.FindStereoCorrespondence(leftImage, rightImage, disparityImage);
sw.Stop();
pbDisparity.Image
= disparityImage.Bitmap;
bm.Dispose();
lblStatus.Text
= string.Format("BM比较耗时{0:F04}毫秒。", sw.ElapsedMilliseconds);
}
else if (tcStereo.SelectedTab == tpStereoGC)
{
StereoGC gc
= new StereoGC((int)nudGCNumberOfDisparities.Value, (int)nudGCMaxIters.Value);
Image
<Gray, Int16> rightDisparityImage = new Image<Gray, short>(leftImage.Size);
sw.Stop();
sw.Start();
gc.FindStereoCorrespondence(leftImage, rightImage, disparityImage, rightDisparityImage);
sw.Stop();
CvInvoke.cvConvertScale(rightDisparityImage.Ptr, rightDisparityImage.Ptr, 16d, 0d);
CvInvoke.cvConvertScale(disparityImage.Ptr, disparityImage.Ptr,
-16d, 0d);
pbDisparity.Image
= rightDisparityImage.Bitmap;
rightDisparityImage.Dispose();
gc.Dispose();
lblStatus.Text
= string.Format("GC比较耗时{0:F04}毫秒。", sw.ElapsedMilliseconds);
}
}

//关闭窗口时
private void FormStereoCorrespondence_FormClosed(object sender, FormClosedEventArgs e)
{
//释放资源
if (leftImage != null)
leftImage.Dispose();
if (rightImage != null)
rightImage.Dispose();
if (disparityImage != null)
disparityImage.Dispose();
}
}
}

 


设置窗口属性SetWindowProperty
    目前只能用SetWindowProperty来设置窗口的全屏属性——全屏或者普通窗口。其实OpenCV2.1中还增加了一个名为cvGetWindowProperty的函数,用于获取窗口的属性,更新说明中没有提到而已。由于目前还没有这个函数的相关文档,我就详细点说说。
1.函数原型、参数说明及提示
void cvSetWindowProperty(const char* name, int prop_id, double prop_value)
作用:设置窗口的属性
返回值:无
参数:
name——窗口名称,对应于用cvNamedWindow创建窗口时使用的名称;
prop_id——属性id,目前有两种属性:CV_WND_PROP_FULLSCREEN    (=0)和CV_WND_PROP_AUTOSIZE(=1),但是仅CV_WND_PROP_FULLSCREEN有用;
prop_value——属性值,如果设置全屏属性,则该值可能有:CV_WINDOW_NORMAL(=0)和CV_WINDOW_FULLSCREEN    (=1)。
备注:(1)cvSetWindowProperty目前只能用于设置窗口的全屏属性;(2)在设置该属性前,要求窗口不能是AUTOSIZE的,否则设置无效;(3)基于第2点原因,在创建窗口时不能省略flag参数(即不能使用其默认值CV_WINDOW_AUTOSIZE);(4)由于EmguCV封装的CvInvoke.cvNamedWindow强制使用了AUTOSIZE参数,因此不能使用它来创建窗口,需要自行进行P/Invoke调用;(5)OpenCV2.1更新文档中的使用示例是错误的,不要模仿。

double cvGetWindowProperty(const char* name, int prop_id)
作用:获取窗口的属性
返回值:返回窗口的属性值
参数:同cvSetWindowProperty

2.示例
您可以按如下所示使用cvSetWindowProperty:

cvSetWindowProperty(windowName, CV_WND_PROP_FULLSCREEN, CV_WINDOW_FULLSCREEN);

完整的示例请看:

完整的cvSetWindowProperty示例
//全屏窗口
private void btnSetWindowProperty_Click(object sender, EventArgs e)
{
Image
<Bgr, Byte> image = new Image<Bgr, byte>("wky_qiao_2272x1704.jpg");
string windowName = "stereoGC left disparity";
cvNamedWindow(windowName,
0);
cvResizeWindow(windowName,
640, 480);
cvMoveWindow(windowName,
100, 100);
cvSetWindowProperty(windowName, CV_WND_PROP_FULLSCREEN, CV_WINDOW_FULLSCREEN);
CvInvoke.cvShowImage(windowName, image.Ptr);
CvInvoke.cvWaitKey(
0);
CvInvoke.cvDestroyWindow(windowName);
image.Dispose();
}

//定义跟窗口相关的常量
public const int CV_WND_PROP_FULLSCREEN = 0;
public const int CV_WND_PROP_AUTOSIZE = 1;
public const double CV_WINDOW_NORMAL = 0;
public const double CV_WINDOW_FULLSCREEN = 1;
public const int CV_WINDOW_AUTOSIZE = 1;
//跟窗口有关的P/Invoke调用
//设置窗口属性,目前只能设置CV_WND_PROP_FULLSCREEN
[System.Runtime.InteropServices.DllImportAttribute("highgui210.dll", EntryPoint = "cvSetWindowProperty")]
public static extern void cvSetWindowProperty([System.Runtime.InteropServices.InAttribute()] [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.LPStr)] string name, int prop_id, double prop_value);
//调整窗口的尺寸
[System.Runtime.InteropServices.DllImportAttribute("highgui210.dll", EntryPoint = "cvResizeWindow")]
public static extern void cvResizeWindow([System.Runtime.InteropServices.InAttribute()] [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.LPStr)] string name, int width, int height);
//移动窗口
[System.Runtime.InteropServices.DllImportAttribute("highgui210.dll", EntryPoint = "cvMoveWindow")]
public static extern void cvMoveWindow([System.Runtime.InteropServices.InAttribute()] [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.LPStr)] string name, int x, int y);
//创建指定名称的窗口
[System.Runtime.InteropServices.DllImportAttribute("highgui210.dll", EntryPoint = "cvNamedWindow")]
public static extern int cvNamedWindow([System.Runtime.InteropServices.InAttribute()] [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.LPStr)] string name, int flags);
//获取窗口对应的句柄HWnd
[System.Runtime.InteropServices.DllImportAttribute("highgui210.dll", EntryPoint = "cvGetWindowHandle")]
public static extern System.IntPtr cvGetWindowHandle([System.Runtime.InteropServices.InAttribute()] [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.LPStr)] string name);
//获取指定句柄对应的窗口名称
[System.Runtime.InteropServices.DllImportAttribute("highgui210.dll", EntryPoint = "cvGetWindowName")]
public static extern System.IntPtr cvGetWindowName(System.IntPtr windowHandle);
//获取窗口的属性
[System.Runtime.InteropServices.DllImportAttribute("highgui210.dll", EntryPoint = "cvGetWindowProperty")]
public static extern double cvGetWindowProperty([System.Runtime.InteropServices.InAttribute()] [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.LPStr)] string name, int prop_id);

}

 

感谢您耐心看完本文,希望对您有所帮助。
欢迎转载,但是请注明出处,保留作者。

posted @ 2010-04-29 09:33 Wuya 阅读(5879) 评论(24) 编辑 收藏

 回复 引用 查看   
#1楼 2010-04-29 22:03 大海的家      
你好,楼主,

最近准备论文,老师说OpenCV新版本有个新功能,就是对两个图片进行比较,看是否一样。

要用到VISUAL STUDIO 和C++,和OpenCV.在此先请教几个问题:

1,这个比较功能是不是StereoSGBM?

2,目前我需要比较的就是黑白图,可能以后是彩图,请问这之间,有没有什 么区别?

3,我刚把VS 2008 的21天学习了12天,对OpenCV 将来怎样和VS2008结合,还没有概念。

先谢谢了!

 回复 引用 查看   
#2楼[楼主] 2010-04-30 10:22 Wuya      
不用客气 -.-
1.不清楚你具体要比较两幅图片的什么方面。不过OpenCV中的StereoSGBM, StereoBM和StereoGC可以对两副图片进行非常细致的比较,并生成差异图。需要注意的是,它们都有点慢,如果你不需要这么详尽的比较,可以自己试试别的办法。
2.黑白图是指只有黑色和白色两种颜色的图,我估计你指的是灰度图像。彩色图像可以用cvCvtColor函数很方便的转换成灰度图像。彩色转换成灰度再进行处理能提高处理速度,但是会丢失一些信息。
3.如果你准备用C/C++语言,www.opencv.org.cn上有怎么在vs2008里配置及使用opencv的文章,论坛里有怎么在vs2010里使用的文章。
加油,祝你成功。

 回复 引用 查看   
#3楼 2010-04-30 16:44 大海的家      
首先非常感谢你的回复!对于确有指导意义,呵呵

正如你所说,首先我想的是从灰度图像入手,如果成功了,可以继续比较彩色图像。所以你所提到的这个cvCvtColor函数,也非常重要。

我刚接到题目,目前还在准备。具体比较图片的什么内容,过程设想是,用设想头照一张图片,存储,然后再照一张相同的图片和一张不同景色的,跟已存在电脑里的那张进行比较。

另外一个实例就是,在生产中,比如给罐头贴标签,假设应该都是贴在相同的位置,这样就可以用图片比较的方式,检查是否所有的标签贴的位置都一样。

我目前所想象的最大障碍是,这种比较的方式的精度问题,比如贴的标签,它歪了多少可以算做正常?还是说歪一点,系统就会反馈。

因为博文上的例子中,你用的是同一张图片,对其一张进行了修改,如果我是用摄像头照相的话,两次的照的时候稍微不同,会不会有所影响呢

谢谢,希望能交流交流

 回复 引用 查看   
#4楼[楼主] 2010-04-30 17:32 Wuya      
@大海的家
哈哈,我只是体验和介绍新特性,并没有深入,很多参数可以对结果进行调整,你不妨试试。

 回复 引用 查看   
#5楼 2010-04-30 19:00 大海的家      
好的。。。。。。。。。。。。。。。。。


 回复 引用 查看   
#6楼 2010-05-21 14:49 lwqiama      
你好,能否把你的对比的那个程序发给我看一下,我毕设在做两个图像的对比,已经觉得毕不了业了。我的图像中有畸变(小的角度和尺度的畸变)。我想装2.1可是按2.0的配置,怎么也不对,也想同时请教一下,谢谢加息
 回复 引用 查看   
#7楼[楼主] 2010-05-21 17:51 Wuya      
@lwqiama
文章中已经有源代码了呀,
你点一下“+”号就可以展开了。
http://www.opencv.org.cn中的论坛里有篇文章比较详细的介绍了如何配置opencv2.1;其实opencv2.1和2.0的配置基本一样的;另外opencv的英文wiki也有这方面的介绍。

 回复 引用 查看   
#8楼 2010-05-23 21:23 lwqiama      
@Wuya
你好,我想问一下这个函数在VC2008里面能用么
它老是报错This application has requested the Runtime to terminate it in an unus
Please contact the application's support team for more information.
谢谢回复

 回复 引用 查看   
#9楼[楼主] 2010-05-23 23:45 Wuya      
@lwqiama
不知道你说的具体是哪一个函数,不过文中的所有函数和类在我的windows xp + Visual Studio2008,以及Windows 7 + Visual Studio2010下运行都没问题的。

 回复 引用 查看   
#10楼 2010-05-24 08:08 lwqiama      
@Wuya
你好,我想问一下,对比两图像找出其中差异,您能给些什么建议么?上面的那个函数不行

 回复 引用 查看   
#11楼[楼主] 2010-05-24 14:03 Wuya      
@lwqiama
没做过,不知道。

 回复 引用 查看   
#12楼 2010-05-25 13:42 lwqiama      
@Wuya
好的,谢谢

 回复 引用 查看   
#13楼 2010-06-03 02:32 风儿的驾驭者      
现在已经凌晨两点半,不过仍然在为看到楼主的博客而兴奋~最近在做一个EmguCV和OSG三维建模的程序~一直苦于没有这方面的资料,楼主这些博文真的是让我受益匪浅~在此深表谢意!!!(注:我还是大三学生,楼主放心,不会将楼主的成果用于任何商业用途!)能留个QQ或邮箱吗?期待能和楼主做更多的交流!
 回复 引用 查看   
#14楼[楼主] 2010-06-03 08:08 Wuya      
@风儿的驾驭者
谢谢。
我的QQ是:xrwang2@qq.com(不过几乎不用),
我的email是:xrwang@126.com
如果有问题的话可以直接在这里提,不一定能解答,不过我会尽量试试。

 回复 引用 查看   
#15楼 2010-06-04 01:06 风儿的驾驭者      
@Wuya
非常感谢~-~
向楼主致敬!!!

 回复 引用 查看   
#16楼 2010-06-08 03:35 Oliver_      
楼主您好,现在看到楼主您的博客真的很开心您这么用心!!想请教楼主,如果我要侦测的物体是有颜色特征的,可是他是不运动的,不像有些可以用背景相减以及光流等等侦测物体,另外我的摄像机试会持续在移动中的,物体一开始不一定在画面中,请问楼主,我该怎么侦测及分割出我的物体呢??请楼主赐教!!小弟研究好久了,到现在也没多大头绪!!感谢您了!!
 回复 引用 查看   
#17楼[楼主] 2010-06-09 18:53 Wuya      
@Oliver_
(1)最近一段时间在忙一个数据库方面的项目,暂时没继续学习了。
(2)既然摄象机是运动的,那么您要跟踪的物体就可能会有缩放、旋转、平移之类的可能;或许您需要试试使用SIFT这样的特征进行跟踪。
(3)如果物体从不同的方向看起来差别太大的话,也许需要建立多个SIFT特征摸板。
(4)有了初始特征之后,您可以模仿OpenCv示例代码中的find_object*.*这几个文件中的方法去尝试。不过我暂时没看懂这些例子。
加油,祝你成功。记得分享成功经验。

 回复 引用 查看   
#18楼 2010-11-19 15:36 garyliu2008      
先荣,看到你的这些资料和做过的工作,感觉你很专业。目前我也开始充实机器视觉开发,但是基本是从零开始,之前是学火箭发动机的。正好可以向你学习请教。
两个问题:
你的背景建模与前景检测之四,没有简单可以阅览或下载的地方;
第二,你开发的OPEN cv案例,是基于VC 2010?还是?是用的几DIALOG模版?我的qq:272787490
MSN:garyliu2008@live.cn

 回复 引用 查看   
#19楼[楼主] 2010-11-21 07:48 Wuya      
@garyliu2008
引用你的背景建模与前景检测之四,没有简单可以阅览或下载的地方;

实际上今年上半年已经写出来,并且发布了一段时间,后来因为论文的原因,暂时被我删除了;等论文刊出之后,会放出来的,并且会很详细。

引用第二,你开发的OPEN cv案例,是基于VC 2010?还是?是用的几DIALOG模版?

用的Visual Studio 2008和2010,图像库用的是OpenCV和EmguCv,界面用的是WinForm。

引用看到你的这些资料和做过的工作,感觉你很专业

我瞎写的,不要当真,看看就行了 -_-

引用我的qq:272787490
MSN:garyliu2008@live.cn

现在几乎不用聊天工具,我们可以写电子邮件,我的地址是:xrwang#126.com

 回复 引用 查看   
#20楼 2011-03-12 14:04 hzw咸蛋      
楼主 ,您好啊,我是刚入门的学生,下载了你的程序,可是VS老是报错:“using Emgu.CV.Structure;” 错误命名空间“Emgu.CV”中不存在类型或命名空间名称“Structure”(是缺少程序集引用吗?)
我装了OpenCV2.1,也下载了Emgu.CV.Windows.Binary-1.3.0.0.zip将文件放在了OpenCV目录下!这是怎么回事呀?谢谢

 回复 引用 查看   
#21楼[楼主] 2011-03-12 14:13 Wuya      
@hzw咸蛋
建议您用EmguCV2.1,因为我当时就用的这个版本。还有就是您的项目中引用了EmguCV的相关文件吗?

如果您有空闲时间,麻烦您去我老婆的淘宝店里花0.1元买个东西,并记得给我一个好评,多谢。
淘宝地址是:http://item.taobao.com/auction/item_detail.htm?item_num_id=9495154832

 回复 引用 查看   
#22楼 2011-03-12 14:27 hzw咸蛋      
谢谢楼主这么及时的回复,我先试试,我一定会抽空去你老婆淘宝里买的!!!!
 回复 引用 查看   
#23楼[楼主] 2011-03-12 14:30 Wuya      
@hzw咸蛋
哈哈,平时要上班,晚上要参加魔兽世界的RAID,一般都没有这么迅速就回复的。
刚才正好在电脑前给老婆上货,顺手就回复了。
得益于139邮箱的免费短信提醒 ^_^

 回复 引用 查看   
#24楼 2011-03-12 22:48 hzw咸蛋      
EmguCV2.1在哪有呢?