1. 程式人生 > >C++開發人臉性別識別教程(8)——搭建MFC框架之讀取目錄信息

C++開發人臉性別識別教程(8)——搭建MFC框架之讀取目錄信息

tail 分享 itemid readdir 文件路徑 alloc tle word 運行

  在上一篇博客中我們已經繪制了MFC界面,在這篇博客中我們將加入響應代碼,為MFC框架加入一個最主要的功能:打開一個目錄。

  一、加入相關頭文件

  這裏頭文件主要包括三類:opencv頭文件、批量讀取文件相關的頭文件、CvvImage。這裏須要強調CvvImage這個頭文件,這個是用來關聯OpenCv和picture控件,而且這個頭文件是隸屬於OpenCv1.x的,在2.x版本號中已經將這個類移除。因此須要手動下載這兩個文件(CvvImage.h和CvvImage.cpp),下載地址:CvvImage。下載後將這兩個文件放在project文件夾下:

技術分享

  然後在VS的解決方式資源管理器窗體中,右擊該project,在快捷菜單中選擇“加入->現有項”:

技術分享

  將這兩個文件加入到當前project中:

技術分享

  加入完畢後,能夠在代碼中加入響應的頭文件了,建議將include命令加入在GenderRecognitionMFCDlg.h頭文件裏:

#include <iostream>
#include <sstream>
#include <fstream>
#include <opencv2\opencv.hpp>
#include "CvvImage.h"

using namespace std;
using namespace cv;

  這裏有兩點須要強調:

  (1)#include語句包括兩種形式,“ #include<> ”和“ #include“” ”。這兩種格式的差別在於優先搜索路徑的不同。“ #include<> ”默認優先依照系統路徑進行搜索,“ #include“” ”默認優先搜索當前的project文件夾。

  (2)include語句的位置。大型project中的include語句要註意避免一個反復包括的問題,即要保證每條include語句僅僅運行一次,否則就會出現重定義類型的錯誤。C++提供兩種機制來確保include語句運行的唯一性。一是通過“ifndef”宏來包圍include代碼塊,二是通過“#pragma once”宏來實現,這裏默認使用另外一種,因此全部的include語句應該位於“#pragma once”語句之後。

  二、加入控件響應函數

  因為讀取顯示圖片的操作是通過“圖像目錄”button來控制的,因此須要為這個button加入響應的事件響應函數。方法很easy,在資源視圖窗體中雙擊相應控件就可以,VS將自己主動加入響應函數:

技術分享

  三、打開目錄。讀取圖片路徑

  接下來為OnBnClickedButtonImagefile()函數加入批量讀取圖片的代碼。我們這裏選用SHBrowseForFolder方法。關於這種方法我之前曾寫過一篇博客來專門介紹,詳細參見一種批量讀取文件的方法——SHBrowseForFolder。註意一點,在SHBrowseForFolder方法中須要用到dir文件夾相關的操作函數(如opendir等),這算是Linux的移植版,因此須要借用dirent.h頭文件,只是我們已經在之前下載的資源中提供了這個文件,僅僅需根據之前CvvImage文件的配置方法,加入到當前project中就可以:

技術分享

  接下來,向CGenderRecognitionMFCDlg類中加入若幹成員變量,用以記錄讀取的文件夾以及文件的路徑及屬性,詳細須要加入下面四個成員變量,各自是CString m_Path(圖像文件路徑)、char* m_ImageDir(文件結構)、DIR *m_pDir(文件夾結構)、struct dirent *m_pEnt(文件夾結構)。這裏以m_pEnt為例。介紹VS中加入類成員變量的方法。

在類視圖中,右擊CGenderRecognitionMFCDlg類。在快捷菜單中選擇“加入->加入變量”:

技術分享

  在彈出的向導窗體中。指定變量的屬性。然後單擊“完畢”button:

技術分享

  同理,加入其它三個成員變量(註意變量類型):

技術分享

  變量加入完畢後,就可以向OnBnClickedButtonImagefile()函數中加入對應代碼:

    /**********初始化變量**********/
    CString str;                                      //存儲圖像路徑
    BROWSEINFO bi;                                    //用來存儲用戶選中的文件夾信息
    TCHAR name[MAX_PATH];                             //存儲路徑
    ZeroMemory(&bi,sizeof(BROWSEINFO));               //清空文件夾相應的內存
    bi.hwndOwner      = GetSafeHwnd();                //得到窗體句柄
    bi.pszDisplayName = name;

    /**********設置對話框並讀取文件夾信息**********/
    BIF_BROWSEINCLUDEFILES;
    bi.lpszTitle     = _T("Select folder");           //對話框標題
    bi.ulFlags       = 0x80;                          //設置對話框形式
    LPITEMIDLIST idl = SHBrowseForFolder(&bi);        //返回所選中文件夾的ID
    SHGetPathFromIDList(idl,str.GetBuffer(MAX_PATH)); //將文件信息格式化存儲到相應緩沖區中
    str.ReleaseBuffer();                              //與GerBuffer配合使用,清空內存
    m_Path=str;                                       //將路徑存儲在m_path中
    if(str.GetAt(str.GetLength()-1)!=\\)
        m_Path += "\\";
    UpdateData(FALSE);
 
    IMalloc * imalloc = 0;
    if (SUCCEEDED(SHGetMalloc(&imalloc)))
    {
        imalloc->Free (idl);
        imalloc->Release();
    }

    /**********獲取該路徑下的第一個文件**********/
    m_ImageDir = (LPSTR)(LPCTSTR)m_Path;
    m_pDir     = opendir(m_ImageDir);
    for (int i = 0; i < 1; i ++)                     //過濾文件夾 ..   和  .
    {
        m_pEnt = readdir(m_pDir);
    }

  有關SHBrowseForFolder的方法介紹,除了之前給出的那篇博客之外,這裏再推薦兩篇更為具體的博客:文件夾瀏覽(SHBrowseForFolder)以及使用SHBrowseForFolder函數打開文件文件夾對話框。

  四、簡單調試

  完畢上面那段代碼之後,進行一下簡單調試。首先按下F7對project進行編譯,在編譯過程中註意將調試器版本號設置為X64(64位)。編譯通過後,設置斷點,按下F5進行調試執行。此時單擊“圖像目錄”button,將彈出打開目錄對話框:

技術分享

  選擇一個目錄,然後查看各個變量的情況:

技術分享

  可見。m_Path保存了當前選擇的目錄路徑。

在下一篇博文中我們將通過這個變量來完畢相應目錄目錄下圖像文件的遍歷和顯示。

C++開發人臉性別識別教程(8)——搭建MFC框架之讀取目錄信息