VS2017配置opencv3.2在MFC单文档中显示图片

转载:https://blog.csdn.net/qq_22636145/article/details/70185561

最近微软发布了VS2017,增加了很多更实用的功能,其中让笔者兴奋不已的GPU加速功能。只需要切换一个按键便能享受GPU的加速,让程序的速度几何倍数的加快。

可是vs2017比较刚刚发布很多的第三方库和第三方的工具都没有更新过来。其中包括笔者在标题上提到的Opencv3.2以及笔者以前一直使用的C++第三方GUI库QT。可是笔者着实不想放弃这令人着迷的VS2017。于是千方百计,到处翻资料终于在MFC单文档下显示出了opencv的图片。

一,首先要配置好opencv

因为opencv官网中编译的.dll文件并不支持VS2017。所以我们自己要编译opencv的dll文件。这方面网络上有很多资料,主要的过程是在CMake的软件下用vs2017的编译工具编译opencv的源文件再生成其特定的dll文件便可以直接在VS2017下直接使用opencv了。

二,在MFC单文档下先显示图片

VC++的单文档可以直接显示VC++库里面的CImgae类,首先我们在***View.h中添加一个变量CImage image;这里笔者在private下创建的该变量。然后我们在资源文件中添加一个事件处理将它创建在**View.cpp文件中,函数名任意取。

[cpp]  view plain  copy
  1. void CMFCApplication1View::OnOpenImage()  
  2. {  
  3.     // TODO: 在此添加命令处理程序代码  
  4.     CFileDialog dlg(TRUE/*, _T(".bmp"), _T("*.bmp"), OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, _T("位图文件(*.bmp)|*.bmp | JEPG文件(*.jpg) | *.jpg || ")*/);  
  5.     if (dlg.DoModal() == IDOK)  
  6.     {  
  7.         if (!image.IsNull())  
  8.         {  
  9.             image.Destroy();  
  10.         }  
  11.         image.Load(dlg.GetPathName());  
  12.         //CString cstr = dlg.GetPathName();  
  13.         str = CStringA(dlg.GetPathName());  
  14.         pic = imread(str, CV_LOAD_IMAGE_COLOR);  
  15.         Invalidate();  
  16.     }  
  17. }  

上面便是该函数的全部实现,然后修改OnDraw()函数,如下:

[cpp]  view plain  copy
  1. void CMFCApplication1View::OnDraw(CDC* pDC)  
  2. {  
  3.     CMFCApplication1Doc* pDoc = GetDocument();  
  4.     ASSERT_VALID(pDoc);  
  5.     if (!pDoc)  
  6.         return;  
  7.   
  8.     // TODO: 在此处为本机数据添加绘制代码  
  9.     if (!image.IsNull())  
  10.     {  
  11.         image.Draw(pDC->GetSafeHdc(), 0, 0);  
  12.     }  
  13. }  


修改完成后便可以运行程序点击按钮便可以显示出图片。

三,实现Mat和CImgae之间的转换。

[cpp]  view plain  copy
  1. #include"CImageMat.h"  
  2.   
  3. void Mat2CImage(Mat & mat, CImage & cimage)  
  4. {  
  5.     if (0 == mat.total())  
  6.     {  
  7.         return;  
  8.     }  
  9.   
  10.     int nChannels = mat.channels();  
  11.     if ((1 != nChannels) && (3 != nChannels))  
  12.     {  
  13.         return;  
  14.     }  
  15.     int nWidth = mat.cols;  
  16.     int nHeight = mat.rows;  
  17.   
  18.     cimage.Destroy();  
  19.     cimage.Create(nWidth,nHeight,8*nChannels);  
  20.   
  21.     uchar *pucRow;  
  22.     uchar *pucImage = (uchar*)cimage.GetBits();  
  23.   
  24.     int nStep = cimage.GetPitch();  
  25.   
  26.     if (1 == nChannels)  
  27.     {  
  28.         RGBQUAD* rgbquadColorTable;  
  29.         int nMaxColors = 256;  
  30.         rgbquadColorTable = new RGBQUAD[nMaxColors];  
  31.         cimage.GetColorTable(0, nMaxColors, rgbquadColorTable);  
  32.         for (int nColor = 0; nColor < nMaxColors; nColor++)  
  33.         {   
  34.             rgbquadColorTable[nColor].rgbBlue = (uchar)nColor;  
  35.             rgbquadColorTable[nColor].rgbGreen = (uchar)nColor;       
  36.             rgbquadColorTable[nColor].rgbRed = (uchar)nColor;  
  37.         }  
  38.         cimage.SetColorTable(0, nMaxColors, rgbquadColorTable);  
  39.         delete[]rgbquadColorTable;  
  40.     }  
  41.     for (int nRow = 0; nRow < nHeight; nRow++)  
  42.     {   
  43.         pucRow = (mat.ptr<uchar>(nRow));   
  44.         for (int nCol = 0; nCol < nWidth; nCol++)  
  45.         {   
  46.             if (1 == nChannels)  
  47.             {   
  48.                 *(pucImage + nRow * nStep + nCol) = pucRow[nCol];  
  49.             } else if (3 == nChannels)   
  50.             {   
  51.                 for (int nCha = 0; nCha < 3; nCha++)   
  52.                 {   
  53.                     *(pucImage + nRow * nStep + nCol * 3 + nCha) = pucRow[nCol * 3 + nCha];   
  54.                 }   
  55.             }   
  56.         }   
  57.     }  
  58. }  
  59.   
  60. void CImage2Mat(CImage & cimage, Mat & mat)  
  61. {  
  62.     if (true == cimage.IsNull())  
  63.     {   
  64.         return;   
  65.     }     
  66.     int nChannels = cimage.GetBPP() / 8;   
  67.     if ((1 != nChannels) && (3 != nChannels))   
  68.     {   
  69.         return;   
  70.     }     
  71.     int nWidth = cimage.GetWidth();   
  72.     int nHeight = cimage.GetHeight();   //重建mat       
  73.     if (1 == nChannels)   
  74.     {         
  75.         mat.create(nHeight, nWidth, CV_8UC1);  
  76.     }   else if(3 == nChannels)   
  77.     {         
  78.         mat.create(nHeight, nWidth, CV_8UC3);     
  79.     }   //拷贝数据    
  80.     uchar* pucRow;    
  81.     //指向数据区的行指针       
  82.     uchar* pucImage = (uchar*)cimage.GetBits();     //指向数据区的指针    
  83.     int nStep = cimage.GetPitch();                  //每行的字节数,注意这个返回值有正有负      
  84.     for (int nRow = 0; nRow < nHeight; nRow++)   
  85.     {         
  86.         pucRow = (mat.ptr<uchar>(nRow));   
  87.         for (int nCol = 0; nCol < nWidth; nCol++)      
  88.         {             
  89.             if (1 == nChannels)       
  90.             {                 
  91.                 pucRow[nCol] = *(pucImage + nRow * nStep + nCol);   
  92.             }             
  93.             else if (3 == nChannels)          
  94.             {                 
  95.                 for (int nCha = 0 ; nCha < 3; nCha++)   
  96.                 {                     
  97.                     pucRow[nCol * 3 + nCha] = *(pucImage + nRow * nStep + nCol * 3 + nCha);       
  98.                 }                         
  99.             }         
  100.         }         
  101.     }  
  102. }  

上面的代码是我在一位大神的博客中找到的,实现了Mat和CImage之间的转换,这和QT中显示opencv的图片原理不谋而合,先以opencv的方式读取图片然后将其转换为CImage在显示到单文档上。如下图:



[cpp]  view plain  copy
  1. // MFCApplication1View.h : CMFCApplication1View 类的接口  
  2. //  
  3.   
  4. #pragma once  
  5. #include<atlimage.h>  
  6. #include"CImageMat.h"  
  7. #include"PI.h"  
  8.   
  9. class CMFCApplication1View : public CView  
  10. {  
  11. protected// 仅从序列化创建  
  12.     CMFCApplication1View();  
  13.     DECLARE_DYNCREATE(CMFCApplication1View)  
  14.   
  15. // 特性  
  16. public:  
  17.     CMFCApplication1Doc* GetDocument() const;  
  18.   
  19. // 操作  
  20. public:  
  21.   
  22. // 重写  
  23. public:  
  24.     virtual void OnDraw(CDC* pDC);  // 重写以绘制该视图  
  25.     virtual BOOL PreCreateWindow(CREATESTRUCT& cs);  
  26. protected:  
  27.     virtual BOOL OnPreparePrinting(CPrintInfo* pInfo);  
  28.     virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo);  
  29.     virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo);  
  30.   
  31. // 实现  
  32. public:  
  33.     virtual ~CMFCApplication1View();  
  34. #ifdef _DEBUG  
  35.     virtual void AssertValid() const;  
  36.     virtual void Dump(CDumpContext& dc) const;  
  37. #endif  
  38.   
  39. private:  
  40.     CImage image;  
  41.     Mat pic;  
  42.     std::string str;  
  43.   
  44. protected:  
  45.   
  46. // 生成的消息映射函数  
  47. protected:  
  48.     DECLARE_MESSAGE_MAP()  
  49. public:  
  50.     afx_msg void OnOpenImage();  
  51.     afx_msg void OnImageGray();  
  52.     afx_msg void Onrefresh();  
  53.     afx_msg void OnHelp();  
  54.     afx_msg void OnSaveImgae();  
  55.     afx_msg void OnAuthor();  
  56.     afx_msg void OnThreshold();  
  57.     afx_msg void OnSplit();  
  58. };  
  59.   
  60. #ifndef _DEBUG  // MFCApplication1View.cpp 中的调试版本  
  61. inline CMFCApplication1Doc* CMFCApplication1View::GetDocument() const  
  62.    { return reinterpret_cast<CMFCApplication1Doc*>(m_pDocument); }  
  63. #endif  


[cpp]  view plain  copy
  1. // MFCApplication1View.cpp : CMFCApplication1View 类的实现  
  2. //  
  3.   
  4. #include "stdafx.h"  
  5. // SHARED_HANDLERS 可以在实现预览、缩略图和搜索筛选器句柄的  
  6. // ATL 项目中进行定义,并允许与该项目共享文档代码。  
  7. #ifndef SHARED_HANDLERS  
  8. #include "MFCApplication1.h"  
  9. #endif  
  10.   
  11. #include "MFCApplication1Doc.h"  
  12. #include "MFCApplication1View.h"  
  13.   
  14. #ifdef _DEBUG  
  15. #define new DEBUG_NEW  
  16. #endif  
  17.   
  18.   
  19. // CMFCApplication1View  
  20.   
  21. IMPLEMENT_DYNCREATE(CMFCApplication1View, CView)  
  22.   
  23. BEGIN_MESSAGE_MAP(CMFCApplication1View, CView)  
  24.     // 标准打印命令  
  25.     ON_COMMAND(ID_FILE_PRINT, &CView::OnFilePrint)  
  26.     ON_COMMAND(ID_FILE_PRINT_DIRECT, &CView::OnFilePrint)  
  27.     ON_COMMAND(ID_FILE_PRINT_PREVIEW, &CView::OnFilePrintPreview)  
  28.     ON_COMMAND(ID_32771, &CMFCApplication1View::OnOpenImage)  
  29.     ON_COMMAND(ID_32772, &CMFCApplication1View::OnImageGray)  
  30.     ON_COMMAND(ID_32773, &CMFCApplication1View::Onrefresh)  
  31.     ON_COMMAND(ID_32775, &CMFCApplication1View::OnHelp)  
  32.     ON_COMMAND(ID_32776, &CMFCApplication1View::OnSaveImgae)  
  33.     ON_COMMAND(ID_32777, &CMFCApplication1View::OnAuthor)  
  34.     ON_COMMAND(ID_Menu, &CMFCApplication1View::OnThreshold)  
  35.     ON_COMMAND(ID_32779, &CMFCApplication1View::OnSplit)  
  36. END_MESSAGE_MAP()  
  37.   
  38. // CMFCApplication1View 构造/析构  
  39.   
  40. CMFCApplication1View::CMFCApplication1View()  
  41. {  
  42.     // TODO: 在此处添加构造代码  
  43.   
  44. }  
  45.   
  46. CMFCApplication1View::~CMFCApplication1View()  
  47. {  
  48. }  
  49.   
  50. BOOL CMFCApplication1View::PreCreateWindow(CREATESTRUCT& cs)  
  51. {  
  52.     // TODO: 在此处通过修改  
  53.     //  CREATESTRUCT cs 来修改窗口类或样式  
  54.   
  55.     return CView::PreCreateWindow(cs);  
  56. }  
  57.   
  58. // CMFCApplication1View 绘制  
  59.   
  60. void CMFCApplication1View::OnDraw(CDC* pDC)  
  61. {  
  62.     CMFCApplication1Doc* pDoc = GetDocument();  
  63.     ASSERT_VALID(pDoc);  
  64.     if (!pDoc)  
  65.         return;  
  66.   
  67.     // TODO: 在此处为本机数据添加绘制代码  
  68.     if (!image.IsNull())  
  69.     {  
  70.         image.Draw(pDC->GetSafeHdc(), 0, 0);  
  71.     }  
  72. }  
  73.   
  74.   
  75. // CMFCApplication1View 打印  
  76.   
  77. BOOL CMFCApplication1View::OnPreparePrinting(CPrintInfo* pInfo)  
  78. {  
  79.     // 默认准备  
  80.     return DoPreparePrinting(pInfo);  
  81. }  
  82.   
  83. void CMFCApplication1View::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)  
  84. {  
  85.     // TODO: 添加额外的打印前进行的初始化过程  
  86. }  
  87.   
  88. void CMFCApplication1View::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)  
  89. {  
  90.     // TODO: 添加打印后进行的清理过程  
  91. }  
  92.   
  93.   
  94. // CMFCApplication1View 诊断  
  95.   
  96. #ifdef _DEBUG  
  97. void CMFCApplication1View::AssertValid() const  
  98. {  
  99.     CView::AssertValid();  
  100. }  
  101.   
  102. void CMFCApplication1View::Dump(CDumpContext& dc) const  
  103. {  
  104.     CView::Dump(dc);  
  105. }  
  106.   
  107. CMFCApplication1Doc* CMFCApplication1View::GetDocument() const // 非调试版本是内联的  
  108. {  
  109.     ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CMFCApplication1Doc)));  
  110.     return (CMFCApplication1Doc*)m_pDocument;  
  111. }  
  112. #endif //_DEBUG  
  113.   
  114.   
  115. // CMFCApplication1View 消息处理程序  
  116.   
  117.   
  118. void CMFCApplication1View::OnOpenImage()  
  119. {  
  120.     // TODO: 在此添加命令处理程序代码  
  121.     CFileDialog dlg(TRUE/*, _T(".bmp"), _T("*.bmp"), OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, _T("位图文件(*.bmp)|*.bmp | JEPG文件(*.jpg) | *.jpg || ")*/);  
  122.     if (dlg.DoModal() == IDOK)  
  123.     {  
  124.         if (!image.IsNull())  
  125.         {  
  126.             image.Destroy();  
  127.         }  
  128.         image.Load(dlg.GetPathName());  
  129.         //CString cstr = dlg.GetPathName();  
  130.         str = CStringA(dlg.GetPathName());  
  131.         pic = imread(str, CV_LOAD_IMAGE_COLOR);  
  132.         Invalidate();  
  133.     }  
  134. }  
  135.   
  136.   
  137. void CMFCApplication1View::OnImageGray()  
  138. {  
  139.     // TODO: 在此添加命令处理程序代码  
  140.     //CImage2Mat(image, pic);  
  141.     if (pic.channels() == 1) {  
  142.         AfxMessageBox(_T("怕是已经灰度化过了"));  
  143.         return;  
  144.     }  
  145.     //cvtColor(pic, pic, CV_BGR2GRAY);  
  146.     pi_gray(pic, pic);  
  147.     Mat2CImage(pic, image);  
  148.     Invalidate();  
  149. }  
  150.   
  151.   
  152. void CMFCApplication1View::Onrefresh()  
  153. {  
  154.     // TODO: 在此添加命令处理程序代码  
  155.     pic = imread(str, CV_LOAD_IMAGE_COLOR);  
  156.     Mat2CImage(pic, image);  
  157.     Invalidate();  
  158. }  
  159.   
  160.   
  161. void CMFCApplication1View::OnHelp()  
  162. {  
  163.     // TODO: 在此添加命令处理程序代码  
  164.     AfxMessageBox(_T("VS2017下的单文档基于Opencv3.2的基本图形处理!"));  
  165. }  
  166.   
  167.   
  168. void CMFCApplication1View::OnSaveImgae()  
  169. {  
  170.     // TODO: 在此添加命令处理程序代码  
  171.     CFileDialog dlg(FALSE);  
  172.     {  
  173.         if (dlg.DoModal() == IDOK)  
  174.         {  
  175.             string savePath = CStringA(dlg.GetPathName());  
  176.             imwrite(savePath, pic);  
  177.             string info = "图片已存储到:" + savePath + "了!";  
  178.             CString cstr(info.c_str());  
  179.             AfxMessageBox(cstr);  
  180.         }  
  181.     }  
  182. }  
  183.   
  184.   
  185. void CMFCApplication1View::OnAuthor()  
  186. {  
  187.     // TODO: 在此添加命令处理程序代码  
  188.     AfxMessageBox(_T("作者:pedro\n时间:2017.4.15"));  
  189. }  
  190.   
  191.   
  192. void CMFCApplication1View::OnThreshold()  
  193. {  
  194.     if (pic.channels() > 1)  
  195.     {  
  196.         AfxMessageBox(_T("怕是没有输入单通道图像!"));  
  197.         return;  
  198.     }  
  199.     // TODO: 在此添加命令处理程序代码  
  200.     threshold(pic, pic, 0, 255, THRESH_OTSU);  
  201.     Mat2CImage(pic, image);  
  202.     Invalidate();  
  203. }  
  204.   
  205.   
  206. void CMFCApplication1View::OnSplit()  
  207. {  
  208.     // TODO: 在此添加命令处理程序代码  
  209.     if (pic.channels() < 3)  
  210.     {  
  211.         AfxMessageBox(_T("怕是没有输入彩色图像!"));  
  212.         return;  
  213.     }  
  214.     vector<Mat> mats;  
  215.     split(pic, mats);  
  216.     imshow("Blue", mats[0]);  
  217.     imshow("Green", mats[1]);  
  218.     imshow("Red", mats[2]);  
  219. }  

猜你喜欢

转载自blog.csdn.net/fangyan90617/article/details/80493807
今日推荐