SQlite3 二进制数据(BLOB)的存取【基于wxSqlite3的封装的操作】

前端之家收集整理的这篇文章主要介绍了SQlite3 二进制数据(BLOB)的存取【基于wxSqlite3的封装的操作】前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。


问题描述:

由于需要,把一张图片加载到cv::Mat对象中(image),并调用算法计算出一个特征向量(feature) 和一些关键点(std::vector<cv::KeyPoint> keyPoints ),把以上这三个对象写入sqlite3数据库(BLOB类型), 之后如果需要又重新从数据库中读出来,并还原成对应的类型。

  1. cv::Mat image = imread(...);
  2. cv::Mat feature = algorithm.Calc(...);
  3. std::vector<cv::KeyPoint> ps = algorithm.Calc(...);


部分代码

1. 写入:

  1. int MTemplateFactory::New(const MTemplateFeature& feature)
  2. {
  3. MDatabaseArchive* archive = MDatabaseManager::getSingleton().GetArchive();
  4. if (archive)
  5. {
  6. MString sql;
  7. if (feature.GetColor() <= 0)
  8. sql = MString::Format("insert into tabTemplate (name,branch_id,feature,image,keypoints) values ('%s',%d,?,?)",feature.GetName(),feature.GetBranchId());
  9. else
  10. sql = MString::Format("insert into tabTemplate (name,color,feature.GetBranchId(),feature.GetColor());
  11.  
  12. try
  13. {
  14. //- Prepare data
  15. cv::Mat img = feature.GetImage();
  16. cv::Mat f = feature.GetFeature();
  17. std::vector<cv::KeyPoint> ps = feature.GetKeyPoints();
  18.  
  19. //- Image.
  20. wxMemoryBuffer buf1;
  21. buf1.AppendData(&img.rows,4); int type1 = img.type();
  22. buf1.AppendData(&img.cols,4); buf1.AppendData(&type1,4);
  23. buf1.AppendData(img.data,img.cols * img.rows * img.elemSize());
  24. //- Feature.
  25. wxMemoryBuffer buf2;
  26. buf2.AppendData(&f.rows,4); int type2 = img.type();
  27. buf2.AppendData(&f.cols,4); buf2.AppendData(&type2,4);
  28. buf2.AppendData(f.data,f.cols * f.rows * f.eleSize());
  29. //- keyPoints.
  30. wxMemoryBuffer buf3;
  31. int eleSize = sizeof(cv::KeyPoint);
  32. for (auto point : ps)
  33. {
  34. buf3.AppendData(&point,eleSize);
  35. }
  36.  
  37. wxsqlite3Statement stmt = archive->PrepareStatement(sql);
  38. stmt.Bind(1,buf2);
  39. stmt.Bind(2,buf1);
  40. stmt.Bind(3,buf3);
  41. if (stmt.ExecuteUpdate() > 0)
  42. return archive->ExecuteScalar("select MAX(id) from tabTemplate");
  43. }
  44. catch (wxsqlite3Exception& e)
  45. {
  46. throw MException(e.GetMessage());
  47. }
  48. catch (cv::Exception& e)
  49. {
  50. throw MException(e.msg);
  51. }
  52. }
  53. return 0;
  54. }<span style="font-weight: bold;">
  55. </span>

2. 读取:
  1. MTemplateArray MTemplateFactory::List()
  2. {
  3. MTemplateArray arr;
  4. MDatabaseArchive* archive = MDatabaseManager::getSingleton().GetArchive();
  5. if (archive)
  6. {
  7. try
  8. {
  9. wxsqlite3ResultSet res = archive->ExecuteQuery("select * from tabTemplate");
  10. while (res.NextRow())
  11. {
  12. int id = res.GetInt(0);
  13. MString name = res.GetString(1);
  14. int branch_id = res.GetInt(2);
  15. int colorId = res.GetInt(3);
  16.  
  17. wxMemoryBuffer f1,f2,f3;
  18. res.GetBlob("image",f1);
  19. res.GetBlob("feature",f2);
  20. res.GetBlob("keypoints",f3);
  21.  
  22. if (f1.IsEmpty() == true || f2.IsEmpty() == true || f3.IsEmpty() == true)
  23. {
  24. throw MException(_("特征模版保存数据为空,无法创建对象!"));
  25. }
  26. cv::Mat&& img = MakeMat(f1);
  27. cv::Mat&& feature = MakeMat(f2);
  28.  
  29. //- Parse keypoints data.
  30. uchar* data = (uchar*)f3.GetData();
  31. int len = f3.GetDataLen();
  32. std::vector<cv::KeyPoint> ps;
  33. int eleSize = sizeof(cv::KeyPoint);
  34. int cnt = len / eleSize;
  35. for (int i = 0; i < cnt; i++)
  36. {
  37. cv::KeyPoint* p = (cv::KeyPoint*)(data + i * eleSize);
  38. ps.push_back(cv::KeyPoint(*p));
  39. }
  40.  
  41. //- Construct template feature object...
  42. arr.push_back(MTemplateFeature(id,name,colorId,img.clone(),feature.clone(),ps));
  43. }
  44.  
  45. }
  46. catch (cv::Exception &e)
  47. {
  48. throw MException(e.msg);
  49. }
  50. catch (wxsqlite3Exception& e)
  51. {
  52. throw MException(e.GetMessage());
  53. }
  54. }
  55. return arr;
  56. }
  57.  
  58. cv::Mat MTemplateFactory::MakeMat(const wxMemoryBuffer& buf )
  59. {
  60. assert(buf.IsEmpty() == false);
  61. void* data = buf.GetData();
  62. int len = buf.GetDataLen();
  63.  
  64. int* p = (int*)data;
  65. int h = p[0];
  66. int w = p[1];
  67. <span style="white-space:pre"> </span>int _type = p[2]; int offset = sizeof(int) * 3;
  68. return cv::Mat(h,w,_type,(uchar*)data + offset);
  69. }

说明几点注意的地方:

sqlite3 存取二进制的文章很多,不记录了。wxsqlite3对blob的操作在wxsqlite3Statement类中,有类似绑定数据(Bind...)和提交操作(ExecuteUpdate...)的函数,具体查看相应的文档或者看源码有注释的。关于KeyPoint的保存,由于cv::KeyPoint这个类的所有数据成员全部都是实体数据,比如int,float 这样的数据,那么直接可以把每个cv::KeyPoint对象的地址加上长度( int len = sizeof(cv::KeyPoint) )存入即可,读数据库还原的时候只需 获取当该片内存,强制转换成 cv::KeyPoint* 就行了,但是如果某些情况,比如对象的成员变量里面有指针指向了另外的地址上的数据,那么这样行不通,强转后的这些指针因为环境变化而无效,如果操作程序会崩溃掉的。

猜你在找的Sqlite相关文章