首页 > 解决方案 > 如何正确地将自由类型位图缓冲区转换为 opencv Mat?

问题描述

我正在尝试将 freetype 位图缓冲区转换为cv::Mat. 这是我到目前为止得到的(我只是把代码的相关部分放在一起)

struct glyph_t
{
    uchar character;
    cv::Mat mat;
    b2PolygonShape shape;
    unsigned char* bitmap_buffer;
};

// ...

// Initialize freetype library 
if (FT_Init_FreeType(&m_library))
    // ... error handling here

if (FT_New_Face(m_library, R"(C:\Windows\Fonts\Arial.ttf)", 0, &m_face))
    // ... error handling here

FT_Set_Pixel_Sizes(m_face, 0, 48);

// ...

// only capital letters
for (auto c = 65; c <= 90; c++)
{
    if (FT_Load_Char(m_face, c, FT_LOAD_RENDER))
        // ... error handling here

    glyph_t g;

    g.bitmap_buffer = m_face->glyph->bitmap.buffer;
    g.character = c;
    g.mat = cv::Mat(
        m_face->glyph->bitmap.rows,
        m_face->glyph->bitmap.width,
        CV_8UC1,
        m_face->glyph->bitmap.buffer);

    m_glyphs.push_back(g); // std::vector<glyph_t>
}

<<如果我现在像这样输出带有重载的 Mat :

for (auto m_glyph : m_glyphs)
{
    std::cout << m_glyph.mat << std::endl;
    std::cout << static_cast<uint>(m_glyph.bitmap_buffer[0]) << std::endl;
}

例如,这封信的输出L如下所示。对于字母A,Mat 仅包含 221 的值......所以我将位图缓冲区转换为cv::Mat. 我在这里做错了什么?

请注意:我添加了第二个输出以进行快速检查,因此我可以比较数组的第一个值是否与 Mat 的第一个匹配

[  0,   0,  12, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 144,   0;
   0,   0,  12, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 144,   0;
   0,   0,  12, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 144,   0;
   0,   0,  12, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 144,   0;
   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  84, 253, 255, 255, 255, 247,  51,   0;
   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  62, 248, 255, 255, 255, 255,  97,   0,   0;
   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  34, 237, 255, 255, 255, 255, 152,   0,   0,   0;
   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  11, 210, 255, 255, 255, 255, 200,   6,   0,   0,   0;
   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 170, 255, 255, 255, 255, 233,  28,   0,   0,   0,   0;
   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 114, 255, 255, 255, 255, 251,  64,   0,   0,   0,   0,   0;
   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  61, 251, 255, 255, 255, 255, 114,   0,   0,   0,   0,   0,   0;
   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  24, 231, 255, 255, 255, 255, 169,   0,   0,   0,   0,   0,   0,   0;
   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   4, 194, 255, 255, 255, 255, 212,  11,   0,   0,   0,   0,   0,   0,   0;
   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 142, 255, 255, 255, 255, 241,  37,   0,   0,   0,   0,   0,   0,   0,   0;
   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  85, 255, 255, 255, 255, 254,  79,   0,   0,   0,   0,   0,   0,   0,   0,   0;
   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  40, 243, 255, 255, 255, 255, 132,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0;
   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  12, 214, 255, 255, 255, 255, 184,   2,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0;
   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 169, 255, 255, 255, 255, 223,  18,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0;
   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 112, 255, 255, 255, 255, 246,  49,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0;
   0,   0,   0,   0,   0,   0,   0,   0,   0,  60, 251, 255, 255, 255, 255,  95,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0;
   0,   0,   0,   0,   0,   0,   0,   0,  23, 230, 255, 255, 255, 255, 149,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0;
   0,   0,   0,   0,   0,   0,   0,   4, 193, 255, 255, 255, 255, 198,   6,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0;
   0,   0,   0,   0,   0,   0,   0, 140, 255, 255, 255, 255, 232,  26,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0;
   0,   0,   0,   0,   0,   0,  83, 255, 255, 255, 255, 251,  62,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0;
   0,   0,   0,   0,   0,  39, 242, 255, 255, 255, 255, 112,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0;
   0,   0,   0,   0,  11, 213, 255, 255, 255, 255, 166,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0;
   0,   0,   0,   0, 167, 255, 255, 255, 255, 210,  10,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0;
   0,   0,   0, 111, 255, 255, 255, 255, 240,  36,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0;
   0,   0,  59, 250, 255, 255, 255, 253,  75,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0;
   0,  23, 229, 255, 255, 255, 255, 115,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0;
   1, 192, 255, 255, 255, 255, 156,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0;
   8, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,  32;
   8, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,  32;
   8, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,  32;
   8, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,  32]
0

编辑

当像这样手动填充垫子时,它可以工作......所以我创建垫子的方式一定有问题......

cv::Mat m = cv::Mat(m_face->glyph->bitmap.rows, m_face->glyph->bitmap.width, CV_8UC1);

for (uint row = 0; row < m_face->glyph->bitmap.rows; row++)
{
  for (uint i = 0; i < m_face->glyph->bitmap.width; i++)
  {
    auto value = m_face->glyph->bitmap.buffer[row*m_face->glyph->bitmap.width+i];
    m.at<uchar>(row, i) = value;
  }
}

标签: c++opencvbufferfreetype

解决方案


我想到了。OpenCV 有它自己的内存管理和引用计数机制。这意味着一旦 cv::Mat 对象超出范围,它的内存就会被释放。

所以我构造对象的方式没有任何问题。但是我在分配之前忘记克隆了。

glyph_t g;

g.bitmap_buffer = m_face->glyph->bitmap.buffer;
g.character = c;

cv::Mat m(
  m_face->glyph->bitmap.rows,
  m_face->glyph->bitmap.width,
  CV_8UC1,
  m_face->glyph->bitmap.buffer);

g.mat = m.clone();           // This made the trick...
m_glyphs.push_back(g);

推荐阅读