c++ - 如何正确地将自由类型位图缓冲区转换为 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;
}
}
解决方案
我想到了。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);
推荐阅读
- c# - Xamarin MvvmCross 如何将 NLog 用于 IMvxLogProvider?
- javascript - 导入与需要节点问题。我们不能使用导入来要求任何模块吗?
- c++ - 在 C++ 中调用辅助类的重写方法
- reactjs - 如何遍历 Axios 对 React 中表的响应
- pointers - 插件包中的 Lookup 返回什么?
- android - AndroidStudio 中的 ARCore 元数据错误
- csv - .CSV 中的重复记录 - 如何在重复中忽略 Hash 中的相似值并仅针对 Perl 中的不同值发出警告
- reactjs - 在 DropzoneDialog 中添加一个复选框
- git - 导出 git 登录 excel 或 CSV 文件保存原始评论格式
- opencv-contour - OpenCV Python 轮廓逼近