6

我试图让一个简单的 OpenCV 示例在 Windows 上的 C++ 中工作,而我的 C++ 不仅仅是生锈。

该示例相当简单:

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>

using namespace cv;
using namespace std;

int main( int argc, char** argv )
{
    if( argc != 2)
    {
        cout <<" Usage: display_image ImageToLoadAndDisplay" << endl;
        return -1;
    }
    Mat image;
    image = imread(argv[1], IMREAD_COLOR); // Read the file
    if(! image.data )                      // Check for invalid input
    {
        cout <<  "Could not open or find the image" << std::endl ;
        return -1;
    }
    namedWindow( "Display window", WINDOW_AUTOSIZE ); // Create a window for display.
    imshow( "Display window", image );                // Show our image inside it.
    waitKey(0); // Wait for a keystroke in the window
    return 0;
}

当我在 Visual Studio 2012 中创建一个新的简单 C++ 控制台应用程序(使用 ATL)时,我得到了一个不同的模板main

int _tmain( int argc, _TCHAR* argv[] )

因此,在将文件名发送到 OpenCV 的imread函数之前,我需要_TCHAR* arg[1]char*. 从内存窗口的内存中使用一个简单的文件名“opencv-logo.jpg”,我可以看到 _TCHAR 每个占用两个字节

o.p.e.n.c.v.-.l.o.g.o...j.p.g...
6f 00 70 00 65 00 6e 00 63 00 76 00 2d 00 6c 00 6f 00 67 00 6f 00 2e 00 6a 00 70 00 67 00 00 00

按照另一个答案中的转换建议,我尝试通过插入以下代码来使用ATL 7.0 字符串转换类和宏:

char* filename = CT2A(argv[1]);

但是生成的内存是一团糟,当然不是 'opencv-logo.jpg' 作为 ascii 字符串:

fe fe fe fe fe fe fe fe fe fe ...
þþþþþþþþþþ ...

我应该使用哪种转换技术、函数或宏?

(注意可能是一个相关的问题,但我看不到如何在这里应用答案。)

4

3 回答 3

20

最快的解决方案是将签名更改为标准签名。代替:

int _tmain( int argc, _TCHAR* argv[] )

int main( int argc, char *argv[] )

这确实意味着在 Windows 上,命令行参数被转换为系统的语言环境编码,并且由于 Windows 不支持 UTF-8,因此并非所有内容都能正确转换。但是,除非您确实需要国际化,否则可能不值得您花时间做更多的事情。

于 2013-10-10T17:03:32.237 回答
7

_TCHAR, ieTCHAR是一种取决于你的项目设置的类型。它可以是wchar_t(当您使用 Unicode 时)或char(当您使用多字节时)。您将在Project Properties - General中找到它,有一个设置Character Set

可能您可以做的最简单的事情就是使用多字节选项并将_TCHAR*类型视为简单char*并使用它尽快构造std::string对象:

std::string filename(argv[1]);

但是,如果您要使用很多特殊字符,那么我发现使用 Unicode 并std::wstring尽可能以对象的形式保存字符串更为合理。如果是这种情况,那么只需使用std::wstring' 构造函数:

std::wstring filename(argv[1]);

如果您最终使用宽字符串,有时您需要在宽字符串和多字节字符串之间进行转换,这些帮助程序可能会帮助您:

// multi byte to wide char:
std::wstring s2ws(const std::string& str)
{
    int size_needed = MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), NULL, 0);
    std::wstring wstrTo(size_needed, 0);
    MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), &wstrTo[0], size_needed);
    return wstrTo;
}

// wide char to multi byte:
std::string ws2s(const std::wstring& wstr)
{
    int size_needed = WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), int(wstr.length() + 1), 0, 0, 0, 0); 
    std::string strTo(size_needed, 0);
    WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), int(wstr.length() + 1), &strTo[0], size_needed, 0, 0); 
    return strTo;
}
于 2013-10-10T16:54:02.300 回答
-1

除了阅读没有太大变化的 26,000 页 cpp 2003 VS 手册...... std::string test(print); 测试 = "";

int _tmain( int argc, _TCHAR* argv[] )  

int main( int argc, char *argv[] ) 

除非您使用某些安全功能,否则工作方式相同....并且在字符集属性中不能是 unicode ...如果您要在文件管理功能中使用 CreateFile 功能,除非您以某种方式对其进行多线程处理

于 2017-12-11T06:48:32.040 回答