6

Windows 上の C++ で動作する単純な OpenCV サンプルを取得しようとしていますが、私の 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 がそれぞれ 2 バイトを使用していることがわかります。

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]);

しかし、結果のメモリはめちゃくちゃです。もちろん、ASCII 文字列としての「opencv-logo.jpg」ではありません。

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

どの変換手法、関数、またはマクロを使用する必要がありますか?

(NBこれは関連する質問かもしれませんが、ここで回答を適用する方法がわかりません。)

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、つまりTCHAR、プロジェクトの設定に依存するタイプです。wchar_t(Unicode を使用する場合) またはchar(マルチバイトを使用する場合) のいずれかです。これはProject Properties - Generalにあります。設定Character Setがあります。

おそらく、あなたができる最も簡単なことは、マルチバイトオプションを使用_TCHAR*し、型を単純なものとして扱い、それを使用してできるだけ早くオブジェクトchar*を構築することです:std::string

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

std::wstringしかし、特殊文字を大量に扱う場合は、可能な限りUnicode を使用して文字列をオブジェクトの形式で保持する方が合理的だと思います。その場合は、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[] ) 

いくつかのセキュリティ機能を使用していない限り、同じように機能します....そして、文字セットプロパティでユニコードにすることはできません...何らかの方法でマルチスレッド化しない限り、ファイル管理機能でCreateFile機能を使用する場合

于 2017-12-11T06:48:32.040 に答える