0

0

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

php中文网

php中文网

发布时间:2016-06-07 15:51:38

|

1614人浏览过

|

来源于php中文网

原创

OPENCV+VS2008+SQLserver 图片存储数据库开发 本人是做图像处理方向的,图像存储的数据库开发是一次尝试,开发平台用的是 OPENCV+VS2008+SQLserver , OPENCV 对图片的读取比较方便,而且支持 bmp , jpg , tiff , png 等多种图像格式,数据库访问技术采用

opencv+vs2008+sqlserver图片存储数据库开发

本人是做图像处理方向的,图像存储的数据库开发是一次尝试,开发平台用的是OPENCV+VS2008+SQLserverOPENCV对图片的读取比较方便,而且支持bmpjpgtiffpng等多种图像格式,数据库访问技术采用的是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。安装SQL2005VS2008.

第二步:SQL2005里新建一个新的数据库,名字为management,在management数据库中添加一个表,名字为personalmessage,字段有namesexstudent_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需要用户名和密码登陆的话,里面的IDpassword要对应你自己的SQL登录名和密码,Data Source也要特别注意,代表你数据库注册的服务器名,我的是WIDOWSXP-CC3F79。以后在程序中就可以直接调用GetRecordset来获得命令对象指针,从而可以方便的对数据库进行操作。

第四步:图片存入数据库

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

由于VCbmp格式的图片处理比较方便,因此我用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_tCString互转,我的程序里都有体现,另外一篇文章我也做了说明。

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);

}

 

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
Golang 测试体系与代码质量保障:工程级可靠性建设
Golang 测试体系与代码质量保障:工程级可靠性建设

Go语言测试体系与代码质量保障聚焦于构建工程级可靠性系统。本专题深入解析Go的测试工具链(如go test)、单元测试、集成测试及端到端测试实践,结合代码覆盖率分析、静态代码扫描(如go vet)和动态分析工具,建立全链路质量监控机制。通过自动化测试框架、持续集成(CI)流水线配置及代码审查规范,实现测试用例管理、缺陷追踪与质量门禁控制,确保代码健壮性与可维护性,为高可靠性工程系统提供质量保障。

6

2026.02.28

Golang 工程化架构设计:可维护与可演进系统构建
Golang 工程化架构设计:可维护与可演进系统构建

Go语言工程化架构设计专注于构建高可维护性、可演进的企业级系统。本专题深入探讨Go项目的目录结构设计、模块划分、依赖管理等核心架构原则,涵盖微服务架构、领域驱动设计(DDD)在Go中的实践应用。通过实战案例解析接口抽象、错误处理、配置管理、日志监控等关键工程化技术,帮助开发者掌握构建稳定、可扩展Go应用的最佳实践方法。

6

2026.02.28

Golang 性能分析与运行时机制:构建高性能程序
Golang 性能分析与运行时机制:构建高性能程序

Go语言以其高效的并发模型和优异的性能表现广泛应用于高并发、高性能场景。其运行时机制包括 Goroutine 调度、内存管理、垃圾回收等方面,深入理解这些机制有助于编写更高效稳定的程序。本专题将系统讲解 Golang 的性能分析工具使用、常见性能瓶颈定位及优化策略,并结合实际案例剖析 Go 程序的运行时行为,帮助开发者掌握构建高性能应用的关键技能。

8

2026.02.28

Golang 并发编程模型与工程实践:从语言特性到系统性能
Golang 并发编程模型与工程实践:从语言特性到系统性能

本专题系统讲解 Golang 并发编程模型,从语言级特性出发,深入理解 goroutine、channel 与调度机制。结合工程实践,分析并发设计模式、性能瓶颈与资源控制策略,帮助将并发能力有效转化为稳定、可扩展的系统性能优势。

14

2026.02.27

Golang 高级特性与最佳实践:提升代码艺术
Golang 高级特性与最佳实践:提升代码艺术

本专题深入剖析 Golang 的高级特性与工程级最佳实践,涵盖并发模型、内存管理、接口设计与错误处理策略。通过真实场景与代码对比,引导从“可运行”走向“高质量”,帮助构建高性能、可扩展、易维护的优雅 Go 代码体系。

17

2026.02.27

Golang 测试与调试专题:确保代码可靠性
Golang 测试与调试专题:确保代码可靠性

本专题聚焦 Golang 的测试与调试体系,系统讲解单元测试、表驱动测试、基准测试与覆盖率分析方法,并深入剖析调试工具与常见问题定位思路。通过实践示例,引导建立可验证、可回归的工程习惯,从而持续提升代码可靠性与可维护性。

2

2026.02.27

漫蛙app官网链接入口
漫蛙app官网链接入口

漫蛙App官网提供多条稳定入口,包括 https://manwa.me、https

130

2026.02.27

deepseek在线提问
deepseek在线提问

本合集汇总了DeepSeek在线提问技巧与免登录使用入口,助你快速上手AI对话、写作、分析等功能。阅读专题下面的文章了解更多详细内容。

8

2026.02.27

AO3官网直接进入
AO3官网直接进入

AO3官网最新入口合集,汇总2026年可用官方及镜像链接,助你快速稳定访问Archive of Our Own平台。阅读专题下面的文章了解更多详细内容。

208

2026.02.27

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
R 教程
R 教程

共45课时 | 7.3万人学习

Bootstrap 5教程
Bootstrap 5教程

共46课时 | 3.5万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号