【问题标题】:How to convert Cairo Image surface to opencv Mat in c++如何在 C++ 中将 Cairo 图像表面转换为 opencv Mat
【发布时间】:2013-11-13 07:54:29
【问题描述】:

我在 cairomm 库中有一个 cairo 图像表面

开罗::RefPtr cropSurface = Cairo::ImageSurface::create(Cairo::FORMAT_ARGB32, Width,Height);

如何在 c++ 中将其转换为 Opencv Mat?

【问题讨论】:

    标签: c++ opencv type-conversion cairo pangocairo


    【解决方案1】:

    这是一个cairo + opencv使用的简短例子,希望对你有用:

    #include <iostream>
    #include <vector>
    #include <stdio.h>
    #include "opencv2/opencv.hpp"
    
    #include "cairo/cairo-win32.h"
    #include "cairo/cairo-pdf.h" 
    #include "cairo/cairo-ps.h"
    #include "cairo/cairo-svg.h"
    using namespace std;
    using namespace cv;
    //-----------------------------------------------------------------------------------------------------
    //
    //-----------------------------------------------------------------------------------------------------
    void MatToCairo(Mat &MC3,cairo_surface_t *surface)
    {
            Mat MC4 = Mat(cairo_image_surface_get_width(surface),cairo_image_surface_get_height(surface),CV_8UC4,cairo_image_surface_get_data(surface),cairo_image_surface_get_stride(surface));
            vector<Mat> Imgs1;
            vector<Mat> Imgs2;
            cv::split(MC4,Imgs1);
            cv::split(MC3,Imgs2);
            for(int i=0;i<3;i++)
            {
            Imgs1[i]=Imgs2[i];
            }
            // Alpha - прозрачность
            Imgs1[3]=255; 
            cv::merge(Imgs1,MC4);
    }
    //-----------------------------------------------------------------------------------------------------
    //
    //-----------------------------------------------------------------------------------------------------
    void CairoToMat(cairo_surface_t *surface,Mat &MC3)
    {
            Mat MC4 = Mat(cairo_image_surface_get_width(surface),cairo_image_surface_get_height(surface),CV_8UC4,cairo_image_surface_get_data(surface),cairo_image_surface_get_stride(surface));
            vector<Mat> Imgs1;
            vector<Mat> Imgs2;
            cv::split(MC4,Imgs1);
            cv::split(MC3,Imgs2);
            for(int i=0;i<3;i++)
            {
            Imgs2[i]=Imgs1[i];
            }
            cv::merge(Imgs2,MC3);
    }
    //-----------------------------------------------------------------------------------------------------
    //
    //-----------------------------------------------------------------------------------------------------
    int main( int argc, char** argv )
    {
        int m_spcount;
        double m_compactness(0);
        int width;
        int height;
        Mat Img=imread("D:\\ImagesForTest\\lena.jpg");
        namedWindow("Image");
        width=Img.cols;
        height=Img.rows;
    
            cairo_surface_t *surface;
            cairo_t *cr;
            surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
            cr = cairo_create(surface);
    
            MatToCairo(Img,surface);
    
            cairo_select_font_face (cr, "serif", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
            cairo_set_font_size (cr, 32.0);
            cairo_set_source_rgb (cr, 0.0, 0.0, 1.0);
            cairo_move_to (cr, 10.0, 50.0);
            cairo_show_text (cr, "Hello, world");
    
            cairo_surface_write_to_png (surface, "hello.png");
    
            CairoToMat(surface,Img);
    
            imshow("Image", Img);
    
            waitKey(0);
            cairo_destroy (cr);
            cairo_surface_destroy (surface);
            destroyAllWindows();
        return 0;
    }
    

    【讨论】:

    • 谢谢斯莫罗多夫先生。我觉得你的回答是对的。但是当代码到达 cairoToMat 函数中的cv::split(MC4,Imgs1); 时,会导致分段错误。你为什么我有这个问题?
    • 刚刚添加了一些小修正并对其进行了测试,它对我来说很好用。我在这里使用了 cairo 二进制文件、头文件和库(对于 win7x64):gtk.org/download/win64.php 您还需要来自该站点的其他 dll 并将它们放入 exe 的路径。还要确保您的图片加载正确。
    【解决方案2】:

    我使用 cairomm,一个 cairo 的 C++ 包装器,而不是 cairo,但事情应该是相似的。一旦为 opencv Mat 分配内存,只需将内存从 cairo 表面复制到 Mat 即可。

    #include <opencv2/opencv.hpp>
    #include <cairommconfig.h>
    #include <cairomm/context.h>
    #include <cairomm/surface.h>
    
    int main()
    {
        Cairo::RefPtr<Cairo::ImageSurface> surface =
            Cairo::ImageSurface::create(Cairo::FORMAT_ARGB32, 600, 400);
    
        Cairo::RefPtr<Cairo::Context> cr = Cairo::Context::create(surface);
    
        cr->save(); // save the state of the context
        cr->set_source_rgb(0.86, 0.85, 0.47);
        cr->paint(); // fill image with the color
        cr->restore(); // color is back to black now
    
        cr->save();
        // draw a border around the image
        cr->set_line_width(20.0); // make the line wider
        cr->rectangle(0.0, 0.0, surface->get_width(), surface->get_height());
        cr->stroke();
    
        cr->set_source_rgba(0.0, 0.0, 0.0, 0.7);
        // draw a circle in the center of the image
        cr->arc(surface->get_width() / 2.0, surface->get_height() / 2.0, surface->get_height() / 4.0, 0.0, 2.0 * M_PI);
        cr->stroke();
    
        // draw a diagonal line
        cr->move_to(surface->get_width() / 4.0, surface->get_height() / 4.0);
        cr->line_to(surface->get_width() * 3.0 / 4.0, surface->get_height() * 3.0 / 4.0);
        cr->stroke();
        cr->restore();
    
        cv::Mat m(surface->get_height(), surface->get_width(), CV_8UC4);
        memcpy(m.data, surface->get_data(), 4 * surface->get_width() * surface->get_height());
    
        cv::imshow("cairo", m);
        cv::waitKey(0);
    }
    

    【讨论】:

      猜你喜欢
      • 2017-02-10
      • 1970-01-01
      • 2020-09-15
      • 2014-09-22
      • 1970-01-01
      • 2022-06-25
      • 1970-01-01
      • 2015-10-09
      • 1970-01-01
      相关资源
      最近更新 更多