2010-04-01

OPENCV+VS2008+SQLserver图片存储数据库开发

本人是做图像处理方向的,图像存储的数据库开发是一次尝试,开发平台用的是OPENCV+VS2008+SQLserver,OPENCV对图片的读取比较方便,而且支持bmp,jpg,tiff,png等多种图像格式,数据库访问技术采用的是ADO,下面我将详细的介绍整个开发过程。

第一步:安装opencv2.0并把cv.lib,cxcore.lib,highgui.lib 这三个库加入到工程里面,具体操作步骤参照http://www.opencv.org.cn/index.php/VC_2008_Express%E4%B8%8B%E5%AE%89%E8%A3%85OpenCV2.0。安装SQL2005,VS2008.

第二步:在SQL2005里新建一个新的数据库,名字为management,在management数据库中添加一个表,名字为personalmessage,字段有name,sex,student_number,

Picture四个字段,前三个字段为字符型,后一个字段为image类型。

第三步:连接数据库,采用ADO方式

新建了一个类CADOConn,从Cobject派生,并增加以下四个成员函数:

_RecordsetPtr  GetRecordset(_bstr_t bstrSQL,_bstr_t DB_Name);//得到命令对象指针

void ExitConnect();         //退出连接

BOOL OnInitADOConn(_bstr_t DB_Name);   //初始化连接

BOOL Execute(_bstr_t bstrSQL,_bstr_t DB_Name);    //执行sql语言

BOOL CADOConn::Execute(_bstr_t bstrSQL,_bstr_t DB_Name)

{

try

{

if (m_pConnection==NULL)

OnInitADOConn(DB_Name);

m_pConnection->Execute(bstrSQL,NULL,adCmdText);

//   m_pConnection->Execute((LPCSTR)bstrSQL, NULL, adExecuteNoRecords);

}

catch (_com_error e)

{

AfxMessageBox(e.ErrorMessage());

return false;

}

return TRUE;

}

BOOL CADOConn::OnInitADOConn(_bstr_t DB_Name)

{

::CoInitialize(NULL);

try

{

m_pConnection.CreateInstance(__uuidof(Connection));

m_pConnection->PutCursorLocation(adUseClient);

_bstr_t connectionstring = "Provider=sqloledb;Data Source=";

connectionstring += _T("WIDOWSXP-CC3F79");

connectionstring += ";Initial Catalog=";

connectionstring += DB_Name;

connectionstring += ";User Id=sa";

connectionstring += ";Password=82877882";

connectionstring += ";";

m_pConnection->Open(connectionstring,"","",adConnectUnspecified);

/*   m_pConnection->ConnectionString="driver={SQL Server};server="";datebase="+DB_Name;

m_pConnection->Open("","","",NULL);*/

}

catch (...)

{

AfxMessageBox(_T("初始化出错"));

return false;

}

return TRUE;

}

void CADOConn::ExitConnect()

{

m_pConnection->Close();

::CoUninitialize();

}

_RecordsetPtr CADOConn::GetRecordset(_bstr_t bstrSQL,_bstr_t DB_Name)

{

try

{

if(m_pConnection==NULL)

OnInitADOConn(DB_Name);

m_pRecordset.CreateInstance(__uuidof(Recordset));

m_pRecordset->Open(bstrSQL, _variant_t( (IDispatch *) m_pConnection,true), adOpenKeyset,adLockOptimistic, adCmdText);

}

catch (_com_error e)

{

AfxMessageBox(e.ErrorMessage());

//return m_pRecordset=NULL;

}

return m_pRecordset;

}

值得注意的是,在OnInitADOConn函数中,如果你的SQL需要用户名和密码登陆的话,里面的ID和password要对应你自己的SQL登录名和密码,Data Source也要特别注意,代表你数据库注册的服务器名,我的是WIDOWSXP-CC3F79。以后在程序中就可以直接调用GetRecordset来获得命令对象指针,从而可以方便的对数据库进行操作。

第四步:图片存入数据库

图片存入数据库的原理就是:把图片转换成二进制形式,存入到image变量中。

由于VC对bmp格式的图片处理比较方便,因此我用opencv读取完之后先把图片转换成bmp格式,读取二进制一般都是以文件形式读取,这里我投机取巧了一下,先把图片以bmp格式存放到某个路径中,然后用CFile以文件形式读取,存储到数据库之后再删除掉,删除用的是:CFile::Remove。如果大家有什么好方法还请告知,谢谢!

位图的读取可以参照http://www.programbbs.com/bbs/tree20-5675-29114.htm。

我的代码如下:

void CadotestDlg::OnBnClickedadd()

{

UpdateData(TRUE);

if(m_name!="")

{

CString strSQL;

CADOConn m_CAdoConn;

_RecordsetPtr  m_pRecordset;

//重新添加一个新的记录

strSQL=_T("select * from personalmessage");

m_pRecordset=m_CAdoConn.GetRecordset((_bstr_t)strSQL,(_bstr_t)("management"));

m_pRecordset->AddNew();

m_pRecordset->PutCollect((_bstr_t)"name",(_bstr_t)m_name);

m_pRecordset->PutCollect((_bstr_t)"sex",(_bstr_t)m_sex);

m_pRecordset->PutCollect((_bstr_t)"student_number",(_bstr_t)m_student_number);

if(m_pic1)

{

cvSaveImage("D://SQL//adotest//adotest//1.bmp",m_pic1);

//保存在"management"数据库中的"personalmessage"表,字段名"picture"

CFile f;

// TODO: Add your control notification handler code here

CString  FilePathName("D://SQL//adotest//adotest//1.bmp");

CFileException e;

if(f.Open(FilePathName, CFile::modeRead | CFile::typeBinary, &e))

{

int nSize = f.GetLength();          //先得到文件长度

BYTE * pBuffer = new BYTE [nSize];  //按文件的大小在堆上申请一块内存

if (f.Read(pBuffer, nSize) > 0 )    //把文件读到pBuffer(堆上申请一块内存)

{

BYTE *pBuf = pBuffer;     ///下面这一大段是把pBuffer里的数据放到库中

VARIANT            varBLOB;

SAFEARRAY     *psa;

SAFEARRAYBOUND     rgsabound[1];

if(pBuf)

{

rgsabound[0].lLbound = 0;

rgsabound[0].cElements = nSize;

psa = SafeArrayCreate(VT_UI1, 1, rgsabound);

for (long i = 0; i < (long)nSize; i++)

SafeArrayPutElement (psa, &i, pBuf++);

varBLOB.vt = VT_ARRAY | VT_UI1;

varBLOB.parray = psa;

m_pRecordset->GetFields()->GetItem("picture")->AppendChunk(varBLOB);

}

delete [] pBuffer;     //删掉堆上申请的那一块内存

pBuf=0;                //以防二次乱用

}

f.Close();                //这里一定要记得先关闭文件,后面再Remove,否则会出现共享冲突

CFile::Remove( L"D://SQL//adotest//adotest//1.bmp" );

}

m_pRecordset->Update();

m_CAdoConn.ExitConnect();

}

MessageBox(L"添加成功");

}

else

{

MessageBox(L"无信息添加");

}

m_student_number=m_name=m_sex="";

m_pic1=0;

UpdateData(FALSE);

}

第五步:读取图片

代码如下:

long nSize = m_pRecordset->GetFields()->GetItem("picture")->ActualSize;

if(nSize > 0)

{

_variant_t    varBLOB;

varBLOB = m_pRecordset->GetFields()->GetItem("picture")->GetChunk(nSize);

if(varBLOB.vt == (VT_ARRAY | VT_UI1))

{

if(BYTE *pBuffer = new BYTE [nSize+1])         ///重新申请必要的存储空间

{

char *pBuf = NULL;

SafeArrayAccessData(varBLOB.parray,(void **)&pBuf);

memcpy(pBuffer,pBuf,nSize);               ///复制数据到缓冲区m_pBMPBuffer

SafeArrayUnaccessData (varBLOB.parray);

delete [] pBuffer;

pBuf=0;

}

//输出文件

_variant_t varChunk;

HRESULT hr;

BYTE *pBuf = NULL;

pBuf = (BYTE*)GlobalAlloc(GMEM_FIXED,nSize);

SafeArrayAccessData(varBLOB.parray,(void **)&pBuf);

CFile outFile(L"D://SQL//adotest//adotest//2.bmp",CFile::modeCreate|CFile::modeWrite);

LPSTR buffer = (LPSTR)GlobalLock((HGLOBAL)pBuf);

outFile.Write(buffer,nSize);

GlobalUnlock((HGLOBAL)pBuf);

outFile.Close();

SafeArrayUnaccessData (varBLOB.parray);

}

IplImage *img=cvLoadImage("D://SQL//adotest//adotest//2.bmp");

DrawPicToHDC(img,IDC_pic2);

m_pic2=img;

CFile::Remove( L"D://SQL//adotest//adotest//2.bmp" );

}

在整个过程中碰到的几个问题:

1. 在数据库读取过程中,如果某个记录为NULL的话,如果直接读取转换就会出错,所以得预先判断,代码如下:

VARIANT   var   =   m_pRecordset->Fields->Item["name"]->GetValue();

if   (   var.vt   !=   VT_NULL   )

{

m_showname=(LPCTSTR)(_bstr_t)m_pRecordset->GetCollect((_bstr_t)"name");

}

2. 文件打开之后要记得f.close(),否则就会出现共享冲突()

3. 图像显示在图像控件上的时候,定义的IplImage变量要记得初始化。

4. 载入的位图如果在文件中打开了rc就会出现opened in another editor,解决办法就是在文件视图中,把rc中的bmp关掉就OK了(这个问题因为我把一副图片设为了对话框的背景,然后把图片删除后造成的)

5. 还有就是几个变量类型转换的问题,像CString转 char*,_bstr_t与CString互转,我的程序里都有体现,另外一篇文章我也做了说明。

6. 图像的显示用的是

void CadotestDlg::DrawPicToHDC(IplImage *img, UINT ID)        //用于在ID所指定的窗口上显示图片

{

CDC *pDC = GetDlgItem(ID)->GetDC();

HDC hDC= pDC->GetSafeHdc();

CRect rect;

GetDlgItem(ID)->GetClientRect(&rect);

CvvImage cimg;

cimg.CopyOf(img);

cimg.DrawToHDC(hDC,&rect);

ReleaseDC(pDC);

}

OPENCV+VS2008+SQLserver图片存储数据库开发相关推荐

  1. SQLServer数据库开发

    SQLServer数据库开发 1.T-SQL编程 1变量 局部变量 局部变量是用户可自定义的变量,它的作用范围仅在程序内部.在程序中通常用来储存从表中查询到的数据,或当作程序执行过程中暂存变量使用.局 ...

  2. sqlserver跟踪数据库_说说被遗忘的数据库开发职业 - 数据库测试

    数据库测试,似乎是被人遗忘的数据库职业,但依然是不错的选择.底下是我在某站找的招聘启事,就连蚂蚁金服都在积极寻找数据库测试人: 要说我经历的项目,大大小小也有几十个,从 C/S, B/S, 再到 B/ ...

  3. php5.6 win2008 mssql,Php5.6.31连接sqlserver 2008R2数据库问题sqlsrv(php5.3及以上版本)与mssql(php5.3以前版本)②...

    Php5.6.31连接sqlserver2008R2数据库 1.环境配置 Win7(win8.1)  64 +Apache2.4 + PHP5.6.31 + SQL Server 2008 R2数据库 ...

  4. !!! SQL 数据库开发基础 传智!

    SQL数据库开发和ADO.net DBMS 数据库管理系统 1.分类 Database(不同类放到不同的数据库里) 2,表table (列名(人的字段) 每一行就是一个对象(人)) 主键(Primar ...

  5. DB2数据库开发工具:DBVisualizer

    DB2数据库开发工具:DBVisualizer 介绍一款操作DB2数据库的工具,它虽不及PL/SQL Developer那样强大,但用于开发要比QuestCentralForDB2好,使用过PLSQL ...

  6. java研发工程师、数据库开发

    一.java研发工程师 职位描述 岗位职责: 1.参加基于Java技术的企业级服务器应用或互联网产品开发: 2.参与系统分析与设计,并负责完成代码编写: 3.根据开发规范与流程独立完成模块的设计.编码 ...

  7. 【SQL Server】数据库开发指南(三)面向数据分析的 T-SQL 编程技巧与实践

    本系列博文还在更新中,收录在专栏:#MS-SQL Server 专栏中. 本系列文章列表如下: [SQL Server] Linux 运维下对 SQL Server 进行安装.升级.回滚.卸载操作 [ ...

  8. 【SQL Server】数据库开发指南(五)T-SQL 高级查询综合应用与实战

    本系列博文还在更新中,收录在专栏:#MS-SQL Server 专栏中. 本系列文章列表如下: [SQL Server] Linux 运维下对 SQL Server 进行安装.升级.回滚.卸载操作 [ ...

  9. MS-SQL数据库开发常用汇总

      MS-SQL数据库开发常用汇总  转自: http://www.cnblogs.com/ghd258/archive/2006/03/20/354147.html     0.把长日期转换为短日期 ...

最新文章

  1. 【哲学】形而上学具体指什么?metaphysics
  2. 就地链表反转_数据结构与算法系列之链表操作全集(二)(GO)
  3. iOS 面试题分析(二)
  4. 还在手写 Nginx 配置?试试这款可视化配置神器,太强了!
  5. swiper控件(回调函数)
  6. php存库,php – 使用Laravel实现存储库模式
  7. 光敏传感器实验报告_光敏电阻传感器实验报告.doc
  8. 软件项目设计文档分类
  9. linux sed 替换 斜杠,sed命令替换字符包含斜杠\,引号的处理方法
  10. 不改变像素尺寸怎么压缩图片
  11. java将pdf旋转(亲测有效)
  12. 在主动要求涨工资这事上,不要学我!从第一份工资800开始说起
  13. 习惯三:要事第一--自我管理的原则
  14. 2022江苏省职业院校技能大赛(中职)网络搭建与应用赛项
  15. 单片机(Arduino)+FLASH+MIC+喇叭自制录音、播放器(二)
  16. 未分配利润与利润表不一致_资产负债表中的未分配利润和利润表中的净利润肯定是一致的吗?...
  17. java实现冒泡排序 (2012-05-23 10:18:22)
  18. 如何理解 ssh 三大框架
  19. vvic、lazada等国内小众电商平台商品详情API调用展示
  20. 计算机技术应用体验,2018教师信息技术应用体验学习个人心得体会2篇

热门文章

  1. 小程序源码:端午送粽子祝福微信小程序源码下载支持打赏模式带背景音乐
  2. 【Oracle之AWR报告解析】
  3. 区块链基本概念和名词解释
  4. java swing 简单计算器_java用swing写了一个简单的计算器
  5. 国服和平精英服务器维护,和平精英辅助免费使用绝地求生12月19日正式服维护公告 今天维护要多久...
  6. 宅男福利!爬虫实战,爬取原神真人c图片并保存,谁的老婆快抱走
  7. 《72个促成交易的经典技巧:…
  8. Warshall‘s algorithm 算法的实现及优化(修改版)
  9. 树和二叉树的基本概念及性质
  10. ★电车难题的n个坑爹变种