添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

在gtkmm中显示opencv cv::Mat图像

3 人关注

我想在一个由gtkmm编写的Gui中显示一个cv::Mat。所以我做了一个测试。

我有一个小部件 Gtk::Image image ,我想用以下两种方法来设置图片。

// first method, display from file
void displayImage1()
    Glib::RefPtr<Gdk::Pixbuf> pixbuf = Gdk::Pixbuf::create_from_file("gtk.png");
    image.set(pixbuf);
// second method, display from cv::Mat
void displayImage2()
    cv::Mat outImage = cv::imread("gtk.png");
    cv::cvtColor(outImage, outImage, CV_BGR2RGB);
    Glib::RefPtr<Gdk::Pixbuf> pixbuf = Gdk::Pixbuf::create_from_data(outImage.data, Gdk::COLORSPACE_RGB,false, 8, outImage.cols, outImage.rows, outImage.step);
    image.set(pixbuf);

The first method works well.

然而,第二种方法效果并不好,我在屏幕上得到了一个被破坏的图像,如图所示。

如果我把has_alpha参数设置为true,结果也很奇怪(见下图)。

类似的测试是通过使用Gtk::DrawingArea完成的。使用了不同的IDE(但都是linux下的g++编译器)。所有的结果都一样。

我测试了很多图像。有时图像被破坏了,有时程序崩溃了,而

该计划意外地完成了。

5 个评论
你是否检查过该图像实际上不包含一个alpha通道?在我看来是这样的,除非灰色背景是图像的一部分。
@KjMag 谢谢,但has_alpha为 "true "的结果也不正确,我更新了问题中的结果。
Miki
24而不是8作为 "bits_per_sample"?
@Miki也试了一下,然后就没有显示了(没有创建正确的图像)。谢谢你
Miki
转换代码似乎是正确的。我认为这可能是由于在函数结束时 outImage 一出范围,数据缓冲区就被释放。你需要一种方法来实际复制gtk图像中的数据
c++
linux
opencv
gtk
gtkmm
Summer Fang
Summer Fang
发布于 2017-10-12
7 个回答
liberforce
liberforce
发布于 2022-08-23
0 人赞同

通常情况下,这种 "破损 "的图像会在我的头脑中引发警告。"错误的rawstride!"。rawstride在 Gdk::Pixbuf 中是指一行数据的字节长度。这是因为你可能有一些字节对齐的限制,所以在一行的最后可能有一些填充。

我检查了这个 step 的参数是什么,是的,这在OpenCV中和Gdk::Pixbuf的rawstride是一样的。直到我意识到 outImage.step 是一个 cv:MatStep 对象,而 Gdk::Pixbuf::create_from_data 期望的是一个int。我认为你应该使用 outImage.step[0] 来代替。

请阅读 https://docs.opencv.org/2.4/modules/core/doc/basic_structures.html#mat

Miki
一个 cv::MatStep 被隐含地转换为一个 size_t ,所以像这样使用 outImage.step 是可以的。
谢谢你的善意回答。是的,我同意@Miki 的观点。不过我试着用outImage.step[0],没有变化。
The Moisrex
The Moisrex
发布于 2022-08-23
0 人赞同

here we go:

auto lenna = imread("Lenna.png");
Image image;
cvtColor(lenna, lenna, COLOR_BGR2RGB);
auto size = lenna.size();
auto img = Gdk::Pixbuf::create_from_data(lenna.data, Gdk::COLORSPACE_RGB, lenna.channels() == 4, 8, size.width, size.height, (int) lenna.step);
image.set(img);
    
谢谢你的代码,但我认为它与我的代码基本上是一样的。我试了一下,结果是一样的。如果它在你那边有效,那一定是我的编译器、系统或我的库的版本问题,我不知道:(
我认为问题在于OpenCV和GTKmm的版本不一样。
YUT
YUT
发布于 2022-08-23
0 人赞同

这就是我所做的,它在图像显示上显示了良好的效果

cvtColor(resize_image, resize_image, COLOR_BGR2RGB);
Pixbuf = Gdk::Pixbuf::create_from_data(resize_image.data, Gdk::COLORSPACE_RGB, false, 8, resize_image.cols, resize_image.rows, resize_image.step);
    
Stewe79
Stewe79
发布于 2022-08-23
0 人赞同

所以我测试了这个(添加scale_simple),对我来说是成功的。

From: http://orobotp.blogspot.com/2014/01/opencv-with-gtkmm3.html

Version: Gtkmm 3.22.2-2, OpenCV 4.4.0-dev, g++ 7.5.0

void displayImage2()
    cv::Mat outImage;
    outImage = cv::imread("gtk.png");
    cv::cvtColor(outImage, outImage, cv::COLOR_RGB2BGR);
    Glib::RefPtr<Gdk::Pixbuf> pixbuf = Gdk::Pixbuf::create_from_data(outImage.data, Gdk::COLORSPACE_RGB,false, 8, outImage.cols, outImage.rows, outImage.step)->scale_simple( outImage.cols, outImage.rows, Gdk::INTERP_BILINEAR );
    image.set(pixbuf);
    
ntd
ntd
发布于 2022-08-23
0 人赞同

IMO,正如@Miki在评论中已经建议的那样,这只是一个寿命问题。

我遇到了非常相同的问题,有类似的代码。

cv::Mat rgb; cv::cvtColor(src, rgb, cv::COLOR_GRAY2RGB); pixbuf = gdk_pixbuf_new_from_data(rgb.data, GDK_COLORSPACE_RGB, FALSE, 8, rgb.cols, rgb.rows, rgb.step, NULL, NULL);

上面的片段根本无法工作(或断断续续地工作),因为,引用了 gdk_pixbuf_new_from_data documentation , "数据是由函数的调用者拥有的"。

问题是在图像被渲染的时候, rgb 已经被销毁。在 pixbuf 之前添加一个 rgb.addref() 可以解决这个问题,尽管会引入一个内存泄漏。

一个解决方案是利用destroy回调来取消对 Mat 对象的引用,例如。

static void
unref_mat(guchar *data, gpointer user_data)
    ((cv::Mat *) user_data)->release();
    cv::Mat rgb;
    cv::cvtColor(src, rgb, cv::COLOR_GRAY2RGB);
    rgb.addref()
    pixbuf = gdk_pixbuf_new_from_data(rgb.data,
                                      GDK_COLORSPACE_RGB, FALSE, 8,
                                      rgb.cols, rgb.rows, rgb.step,
                                      unref_mat, &rgb);
    
ERic
ERic
发布于 2022-08-23
0 人赞同

尝试添加一个对outimage的引用,比如 outimage.addref() 我所有的问题都与此有关,源图像在被取消参考之前就被删除了。 gdk_pixbuf_new_from_data 导致segfaults、损坏等等。只要确保稍后释放它,或者使用提供的回调 gdk_pixbuf_new_from_data