OPENCV+VS2008+SQLserver图片存储数据库开发
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图片存储数据库开发相关推荐
- SQLServer数据库开发
SQLServer数据库开发 1.T-SQL编程 1变量 局部变量 局部变量是用户可自定义的变量,它的作用范围仅在程序内部.在程序中通常用来储存从表中查询到的数据,或当作程序执行过程中暂存变量使用.局 ...
- sqlserver跟踪数据库_说说被遗忘的数据库开发职业 - 数据库测试
数据库测试,似乎是被人遗忘的数据库职业,但依然是不错的选择.底下是我在某站找的招聘启事,就连蚂蚁金服都在积极寻找数据库测试人: 要说我经历的项目,大大小小也有几十个,从 C/S, B/S, 再到 B/ ...
- 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数据库 ...
- !!! SQL 数据库开发基础 传智!
SQL数据库开发和ADO.net DBMS 数据库管理系统 1.分类 Database(不同类放到不同的数据库里) 2,表table (列名(人的字段) 每一行就是一个对象(人)) 主键(Primar ...
- DB2数据库开发工具:DBVisualizer
DB2数据库开发工具:DBVisualizer 介绍一款操作DB2数据库的工具,它虽不及PL/SQL Developer那样强大,但用于开发要比QuestCentralForDB2好,使用过PLSQL ...
- java研发工程师、数据库开发
一.java研发工程师 职位描述 岗位职责: 1.参加基于Java技术的企业级服务器应用或互联网产品开发: 2.参与系统分析与设计,并负责完成代码编写: 3.根据开发规范与流程独立完成模块的设计.编码 ...
- 【SQL Server】数据库开发指南(三)面向数据分析的 T-SQL 编程技巧与实践
本系列博文还在更新中,收录在专栏:#MS-SQL Server 专栏中. 本系列文章列表如下: [SQL Server] Linux 运维下对 SQL Server 进行安装.升级.回滚.卸载操作 [ ...
- 【SQL Server】数据库开发指南(五)T-SQL 高级查询综合应用与实战
本系列博文还在更新中,收录在专栏:#MS-SQL Server 专栏中. 本系列文章列表如下: [SQL Server] Linux 运维下对 SQL Server 进行安装.升级.回滚.卸载操作 [ ...
- MS-SQL数据库开发常用汇总
MS-SQL数据库开发常用汇总 转自: http://www.cnblogs.com/ghd258/archive/2006/03/20/354147.html 0.把长日期转换为短日期 ...
最新文章
- 【哲学】形而上学具体指什么?metaphysics
- 就地链表反转_数据结构与算法系列之链表操作全集(二)(GO)
- iOS 面试题分析(二)
- 还在手写 Nginx 配置?试试这款可视化配置神器,太强了!
- swiper控件(回调函数)
- php存库,php – 使用Laravel实现存储库模式
- 光敏传感器实验报告_光敏电阻传感器实验报告.doc
- 软件项目设计文档分类
- linux sed 替换 斜杠,sed命令替换字符包含斜杠\,引号的处理方法
- 不改变像素尺寸怎么压缩图片
- java将pdf旋转(亲测有效)
- 在主动要求涨工资这事上,不要学我!从第一份工资800开始说起
- 习惯三:要事第一--自我管理的原则
- 2022江苏省职业院校技能大赛(中职)网络搭建与应用赛项
- 单片机(Arduino)+FLASH+MIC+喇叭自制录音、播放器(二)
- 未分配利润与利润表不一致_资产负债表中的未分配利润和利润表中的净利润肯定是一致的吗?...
- java实现冒泡排序 (2012-05-23 10:18:22)
- 如何理解 ssh 三大框架
- vvic、lazada等国内小众电商平台商品详情API调用展示
- 计算机技术应用体验,2018教师信息技术应用体验学习个人心得体会2篇
热门文章
- 小程序源码:端午送粽子祝福微信小程序源码下载支持打赏模式带背景音乐
- 【Oracle之AWR报告解析】
- 区块链基本概念和名词解释
- java swing 简单计算器_java用swing写了一个简单的计算器
- 国服和平精英服务器维护,和平精英辅助免费使用绝地求生12月19日正式服维护公告 今天维护要多久...
- 宅男福利!爬虫实战,爬取原神真人c图片并保存,谁的老婆快抱走
- 《72个促成交易的经典技巧:…
- Warshall‘s algorithm 算法的实现及优化(修改版)
- 树和二叉树的基本概念及性质
- ★电车难题的n个坑爹变种