OpenCV中读取jpg文件与C# Bitmap的区别

4
经过多次实验,我发现用C ++(OpenCV)读取彩色jpg文件的方式与使用C#位图读取同一文件的方式不同。如果在它们上面都应用了一些算法,如GoodFeatureToTrack,那么它们之间有明显的差异。
问题是:如何在OpenCV中采用C#位图加载方式,以便在直接从本机部分加载图像或从C#包装器加载图像时获得相同的结果。
谢谢!
编辑:
此代码是一个C++函数,它接受一些包含在托管程序(C#)中加载的图像的结构,然后在OpenCV中加载相同的图像并进行比较。它们之间是有区别的!
    extern "C" _declspec (dllexport) void test_diff(authenticator_reference_structure* referecnces){
    auto image(cv::imread("white.jpg"));

    cv::imshow("opencv", image);
    auto wrpped(referecnces->references->images->image.getMat());

    cv::imshow("C#", wrapped);
    cv::Mat ss;
    cv::absdiff(image, wrapped, ss);

    cv::threshold(ss, ss, 1, 255, CV_THRESH_BINARY);
    cv::imshow("Diff", ss);
    cv::waitKey();

}

the thresholded diffrences image


1
什么类型的图像?灰度?彩色?您尝试过向 imread 传递不同的标志吗? - Roger Rowland
1
您可以使用CV_LOAD_IMAGE_ANYDEPTH来处理16或32位图像,或者使用CV_LOAD_IMAGE_GRAYSCALE将其转换为灰度图像。默认值是CV_LOAD_IMAGE_COLOR,这将生成一个3通道的图像。您的图像可能有alpha通道吗? - Roger Rowland
我不认为它包含alpha通道...但是我将尝试CV_LOAD_IMAGE_ANYDEPTH。 - Humam Helfawi
我尝试过了,它没有返回三通道。我需要结果是三通道(彩色)。 - Humam Helfawi
最坏的情况下:怎么样写一个封装器,在 OpenCV 中加载图像并在 C# 中使用它,你可以创建一个位图,或者在 C# 中使用位图加载图像,然后从 C++ 中访问其数据以创建一个 OpenCV Mat。这样,你将在两个部分中使用同一加载库,结果应该是相同的。我想你的最终目标是比较一些代码在C++或C#中的性能,因此图像加载机制不是问题。 - rkachach
显示剩余2条评论
2个回答

3

你可以单独安装Emgu,包含头文件并链接它。你的项目中也没有包含OpenCV吧?请参考http://www.emgu.com/wiki/index.php/Main_Page#Architecture_Overview——在许多情况下,你需要调用它而不是OpenCV(请参见http://www.emgu.com/wiki/index.php/Tutorial)。 - alle_meije
抱歉,我还在编辑中。但是C##也将出现在本地部分(它是Windows特定的),因此不应更改托管依赖项,对吧? - alle_meije
啊,OpenCV也有一个getMat()函数,我以为是那个。这让我想到,要么你的getMat()有一个错误(没有代码,无法评论),要么你看到的差异来自JPEG压缩。如果这些条纹是8x8方块的倍数(JPEG的特征),我不会感到惊讶。 - alle_meije
1
问题解决了吗?你可以通过将质量设置为100%,从PNG生成JPEG来进行测试。我认为这仍然会进行DCT,但不会丢弃任何系数。除此之外,JPEG解码会产生像你的“Diff”图片中那样的伪影。 - alle_meije
@HumamHelfawi:你可能想要阅读一下这个帖子的一些内容:https://groups.google.com/forum/#!topic/rec.photo.digital/yAxoW9HyHPQ/discussion - Amro
显示剩余6条评论

3

正如其他人所指出的,如果你想在OpenCV中读取未修改的图像,请在C++函数中将标志设置为-1,例如:

cv::Mat img = cv::imread("xxx.jpg", -1);

或者使用已定义的枚举值:

cv::Mat img = cv::imread("xxx.jpg", cv::IMREAD_UNCHANGED);

同时请注意,不同解码器不能保证完全相同地解码JPEG图像!最好使用无损格式,如PNG(参见#4148#4046等)。


是的,我试过了。但是改变整个编码不是一个选项,甚至在我的当前项目中我也没有权限这样做。 - Humam Helfawi
我的意思是,当您想比较算法的不同实现时,请在测试中使用PNG图像(它们是无损的,就像ZIP文件一样)。 - Amro
我明白了,看来没有简单的解决方案...我必须改变编码或者添加一个库到托管部分...无论如何,谢谢:) - Humam Helfawi
1
如果我理解正确,您已经在C#中开发了一个算法(某种特征检测),并想将其与C++实现进行比较。我的意思是,在比较时您应该使用PNG而不是JPEG图像,仅为了排除可能性,以防您在两种实现之间看到差异。显然,将1M组图像转换没有意义,因为这些图像已经以有损格式存储和压缩,我只是在谈论测试阶段。 - Amro
1
@HumamHelfawi: 啊哈,这正是我一开始怀疑的 :) 不同的库会以稍微不同的方式对JPEG图像进行解码.. 你无法改变这个。如果你想要精确度,你必须考虑其他编解码器。此外,如果你开发的算法在输入这些有差异的图像时给出非常不同的结果,那么我认为这是一个问题.. 你应该放宽参数(比如平滑输入图像,或者在进行图像滤波时使用略大的窗口大小,等等...) - Amro
显示剩余6条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接