Как преобразовать поверхность Cairo Image в opencv Mat в Stack Overflow

У меня есть Каир Поверхность изображения в библиотеке Cairomm

Каир :: RefPtr cropSurface =
Cairo :: ImageSurface :: create (Cairo :: FORMAT_ARGB32, Ширина, Высота);

Как я могу преобразовать его в Opencv Mat в C ++?

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;
}
2

Другие решения

Я использую cairomm, оболочку C ++ от cairo вместо cairo, но все должно быть похоже. Как только выделите память для OpenCV Mat, просто скопируйте память с поверхности Каира в 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);
}

1