我正试图让a simple OpenCV sample在Windows上使用C ++,而我的C ++不仅仅是生锈。
The sample非常简单:
#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
根据another answer中的转换建议,我尝试使用ATL 7.0 String Conversion Classes and Macros插入以下代码:
char* filename = CT2A(argv[1]);
但由此产生的内存是一团糟,当然不是'opencv-logo.jpg'作为ascii字符串:
fe fe fe fe fe fe fe fe fe fe ...
þþþþþþþþþþ ...
我应该使用哪种转换技术,功能或宏?
(N.B。This可能是一个相关问题,但我在这里看不到如何应用the answer。)
答案 0 :(得分:18)
最快的解决方案是将签名更改为标准签名。替换:
int _tmain( int argc, _TCHAR* argv[] )
用
int main( int argc, char *argv[] )
这在Windows上意味着命令行参数转换为系统的语言环境编码,并且由于Windows不支持UTF-8,因此并非所有内容都能正确转换。但是,除非你真的需要国际化,否则你可能不值得花时间去做更多的事情。
答案 1 :(得分:7)
_TCHAR
,即TCHAR
是一种取决于项目设置的类型。它可以是wchar_t
(当您使用Unicode时)或char
(当您使用多字节时)。你会在 项目属性 - 常规 中找到这个,有一个设置 字符集< / EM> 强>
你可以做的最简单的事情就是使用多字节选项并将_TCHAR*
类型视为一个简单的char*
并使用它来尽快构造std::string
对象:
std::string filename(argv[1]);
但是如果您打算使用特殊字符A LOT,那么我发现使用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;
}
答案 2 :(得分:-1)
除了阅读26,000页cpp 2003 VS手册之外没有太大变化.... std :: string test(print); test =“”;
int _tmain( int argc, _TCHAR* argv[] )
int main( int argc, char *argv[] )
工作相同,除非你使用一些安全功能....并且在字符集属性中不能是unicode ...如果你在文件管理功能中使用CreateFile函数,除非你以某种方式多线程