搜索
首页数据库mysql教程OPENCV+VS2008+SQLserver图片存储数据库开发

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

}

 

声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
将用户添加到MySQL:完整的教程将用户添加到MySQL:完整的教程May 12, 2025 am 12:14 AM

掌握添加MySQL用户的方法对于数据库管理员和开发者至关重要,因为它确保数据库的安全性和访问控制。1)使用CREATEUSER命令创建新用户,2)通过GRANT命令分配权限,3)使用FLUSHPRIVILEGES确保权限生效,4)定期审计和清理用户账户以维护性能和安全。

掌握mySQL字符串数据类型:varchar vs.文本与char掌握mySQL字符串数据类型:varchar vs.文本与charMay 12, 2025 am 12:12 AM

chosecharforfixed-lengthdata,varcharforvariable-lengthdata,andtextforlargetextfield.1)chariseffity forconsistent-lengthdatalikecodes.2)varcharsuitsvariable-lengthdatalikenames,ballancingflexibilitibility andperformance.3)

MySQL:字符串数据类型和索引:最佳实践MySQL:字符串数据类型和索引:最佳实践May 12, 2025 am 12:11 AM

在MySQL中处理字符串数据类型和索引的最佳实践包括:1)选择合适的字符串类型,如CHAR用于固定长度,VARCHAR用于可变长度,TEXT用于大文本;2)谨慎索引,避免过度索引,针对常用查询创建索引;3)使用前缀索引和全文索引优化长字符串搜索;4)定期监控和优化索引,保持索引小巧高效。通过这些方法,可以在读取和写入性能之间取得平衡,提升数据库效率。

mysql:如何远程添加用户mysql:如何远程添加用户May 12, 2025 am 12:10 AM

ToaddauserremotelytoMySQL,followthesesteps:1)ConnecttoMySQLasroot,2)Createanewuserwithremoteaccess,3)Grantnecessaryprivileges,and4)Flushprivileges.BecautiousofsecurityrisksbylimitingprivilegesandaccesstospecificIPs,ensuringstrongpasswords,andmonitori

MySQL字符串数据类型的最终指南:有效的数据存储MySQL字符串数据类型的最终指南:有效的数据存储May 12, 2025 am 12:05 AM

tostorestringsefliceflicyInmySql,ChooSetherightDataTypeBasedyOrneOrneEds:1)USEcharforFixed-LengthStstringStringStringSlikeCountryCodes.2)UseVarcharforvariable-lengtthslikenames.3)USETEXTCONTENT.3)

mysql blob vs.文本:为大对象选择正确的数据类型mysql blob vs.文本:为大对象选择正确的数据类型May 11, 2025 am 12:13 AM

选择MySQL的BLOB和TEXT数据类型时,BLOB适合存储二进制数据,TEXT适合存储文本数据。1)BLOB适用于图片、音频等二进制数据,2)TEXT适用于文章、评论等文本数据,选择时需考虑数据性质和性能优化。

MySQL:我应该将root用户用于产品吗?MySQL:我应该将root用户用于产品吗?May 11, 2025 am 12:11 AM

No,youshouldnotusetherootuserinMySQLforyourproduct.Instead,createspecificuserswithlimitedprivilegestoenhancesecurityandperformance:1)Createanewuserwithastrongpassword,2)Grantonlynecessarypermissionstothisuser,3)Regularlyreviewandupdateuserpermissions

MySQL字符串数据类型说明了:选择适合您数据的合适类型MySQL字符串数据类型说明了:选择适合您数据的合适类型May 11, 2025 am 12:10 AM

mySqlStringDatatatPessHouldBechoseBeadeDataCharacteristicsAndUsecases:1)USECHARFORFIXED LENGTHSTRINGSTRINGSLIKECOUNTRYCODES.2)USEDES.2)usevarcharforvariable-lengtthstringstringstringstringstringstringstringslikenames.3)usebinaryorvarrinaryorvarinarydatalbonydatalgebgeenfopical.4)

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

热工具

适用于 Eclipse 的 SAP NetWeaver 服务器适配器

适用于 Eclipse 的 SAP NetWeaver 服务器适配器

将Eclipse与SAP NetWeaver应用服务器集成。

Dreamweaver Mac版

Dreamweaver Mac版

视觉化网页开发工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

mPDF

mPDF

mPDF是一个PHP库,可以从UTF-8编码的HTML生成PDF文件。原作者Ian Back编写mPDF以从他的网站上“即时”输出PDF文件,并处理不同的语言。与原始脚本如HTML2FPDF相比,它的速度较慢,并且在使用Unicode字体时生成的文件较大,但支持CSS样式等,并进行了大量增强。支持几乎所有语言,包括RTL(阿拉伯语和希伯来语)和CJK(中日韩)。支持嵌套的块级元素(如P、DIV),

ZendStudio 13.5.1 Mac

ZendStudio 13.5.1 Mac

功能强大的PHP集成开发环境