GetOpenFileName对话框和opencv的奇怪行为

时间:2015-03-11 03:39:10

标签: c++ windows winforms opencv dialog

我尝试使用打开文件对话框,允许我的程序用户选择一个图像,然后使用opencv进行处理。

我有一个功能,我打开对话框并尝试加载图像:

Mat load_image()
{

OPENFILENAME ofn;       // common dialog box structure
TCHAR szFile[260];       // buffer for file name
HWND hwnd;              // owner window
HANDLE hf;              // file handle

// Initialize OPENFILENAME
ZeroMemory(&ofn, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = hwnd;
ofn.lpstrFile = szFile;
// Set lpstrFile[0] to '\0' so that GetOpenFileName does not 
// use the contents of szFile to initialize itself.
ofn.lpstrFile[0] = '\0';
ofn.nMaxFile = sizeof(szFile);
ofn.lpstrFilter = L"All\0*.*\0Text\0*.TXT\0";
ofn.nFilterIndex = 1;
ofn.lpstrFileTitle = NULL;
ofn.nMaxFileTitle = 0;
ofn.lpstrInitialDir = NULL;
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;

// Display the Open dialog box. 
if (GetOpenFileName(&ofn)==TRUE) 
    hf = CreateFile(ofn.lpstrFile, 
                    GENERIC_READ,
                    0,
                    (LPSECURITY_ATTRIBUTES) NULL,
                    OPEN_EXISTING,
                    FILE_ATTRIBUTE_NORMAL,
                    (HANDLE) NULL);
char filepath[260];
wcstombs(filepath, ofn.lpstrFile, 260);
cout << filepath << endl;
Mat src = imread(filepath);
//imshow("src", src);
return src;
}

您在此处看到的代码可以使用,打开对话框并允许用户选择文件。然后将文件路径转换为字符串(将传递给imread)。当我尝试与图像src交互时,会出现问题。

例如,如果我取消注释&#39; imshow&#39; line,GetOpenFileName将返回0并且对话框甚至不会打开。这种情况发生的比较多,我实际上无法访问图像,因为我尝试的一切都会导致这种情况发生。

为了使函数起作用,它被调用如下:

load_image();

但如果我尝试分配图像,即:

img = load_image(); 

出现同样的问题。救命!可能导致这种情况的原因是什么?

2 个答案:

答案 0 :(得分:1)

这些只是我在你的代码中注意到的事情......所以我不希望这会有用,但也许会有所帮助。

imread可能失败了。您使用CreateFile打开了文件,并在打开文件时将其锁定(无共享属性。有关详细信息,请参阅CreateFile)。 imread尝试打开文件,因此您不需要创建自己的句柄!只需使用收到的文件路径,然后拨打imread,而不是使用CreateFile

Mat src;
if (GetOpenFileName(&ofn)==TRUE)
{
    // Succeeded in choosing a file
    char filepath[260];
    wcstombs(filepath, ofn.lpstrFile, 260);
    cout << filepath << endl;
    src = imread(filepath);
}

如果你没有hwnd,那么你应该设置ofn.hwndOwner=NULL而不是任意设置它。

如果您选择使用CreateFile(可能您希望在OpenCV之外为自己的目的打开它以进行手动读取访问),那么请确保在再次打开文件之前调用文件句柄上的CloseHandle( HANDLE h )

答案 1 :(得分:1)

正如上一条评论中所提到的,CreateFile方法锁定了图像文件,因此cv::imread()无法访问/读取其内容。

尽量避免使用CreateFile,我认为没有理由在您的代码中使用它,以下代码运行良好:

cv::Mat load_image()
{
    cv::Mat outMat;
    OPENFILENAME ofn;       // common dialog box structure
    TCHAR szFile[260];      // buffer for file name

    // Initialize OPENFILENAME
    ZeroMemory(&ofn, sizeof(ofn));
    ofn.lStructSize = sizeof(ofn);
    ofn.hwndOwner = NULL;
    ofn.lpstrFile = szFile;
    ofn.lpstrFile[0] = '\0';
    ofn.nMaxFile = sizeof(szFile);
    ofn.lpstrFilter = L"All\0*.*\0Text\0*.TXT\0";
    ofn.nFilterIndex = 1;
    ofn.lpstrFileTitle = NULL;
    ofn.nMaxFileTitle = 0;
    ofn.lpstrInitialDir = NULL;
    ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;

    // Display the Open dialog box. 
    if (GetOpenFileName(&ofn) == TRUE)
    {
        char filepath[260];

        wcstombs(filepath, ofn.lpstrFile, 260);
        cout << filepath << endl;

        outMat = cv::imread(filepath);
    }

    return outMat;
}

int main()
{
    cv::Mat image = load_image();

    cv::imshow("image", image);
    cv::waitKey(-1);

    return 0;
}