質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

3回答

1517閲覧

c++でimageのshape(H, W, C)を(1, C, H, W)にする方法

trafalbad

総合スコア303

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2021/11/18 12:30

c++で画像のshape(256, 256, 3)をinput用に(1, 3, 256, 256)に変換したいです。

このサイトを参考にしたのですが上手くいきません。どこが原因か解決策を教えていただけないでしょうか?

よろしくお願いします。

試したC++コード

cpp

1#define W 256 2#define H 256 3void image_info(cv::Mat image){ 4 double min, max; 5 std::cout << "row: " << image.rows << "col " << image.cols << ", channels " << image.channels() << std::endl; 6 cv::minMaxLoc(image, &min, &max); 7 std::cout << "min: " << min << std::endl; 8 std::cout << "max: " << max << std::endl; 9} 10 11float hwc2chw(cv::Mat image){ 12 static const int channels= 3; 13 float total= H * W * channels; 14 float* hostInputBuffer= static_cast<float*>(total); 15 cv::Mat chw_image(H, W, CV_8UC3); 16 17 //Convert HWC to CHW 18 for (int c= 0; c < channels; ++c) 19 { 20 for (int h= 0; h < H; ++h) 21 { 22 for (int w= 0; w < W; ++w) 23 { 24 std::cout << "C: " << c << " H: " << h << " W: " << w << std::endl; 25 Vec3f bgrPixel= chw_image.at<Vec3f>(h, w); 26 int dstIdx= c * H * W + h * W + w; 27 hostInputBuffer[dstIdx]= bgrPixel[c]; 28 } 29 } 30 } 31 //chw_image.copy(output); 32 return hostInputBuffer; 33} 34 35cv::Mat normalization(std::string imageFilepath){ 36 cv::Mat chw_image; 37 cv::Mat image = cv::imread(imageFilepath); 38 cv::resize(image, image, cv::Size(H, W), cv::InterpolationFlags::INTER_CUBIC); 39 cv::cvtColor(image, image, cv::ColorConversionCodes::COLOR_BGR2RGB); 40 float hostInputBuffer = hwc2chw(image); 41 hostInputBuffer.convertTo(chw_image, CV_32FC3, 1.0/127.5, -1); 42 image_info(chw_image); 43 cv::dnn::blobFromImage(chw_image, chw_image); 44 return chw_image; 45}

エラー

/mnt/src/inference.cpp: In function ‘float hwc2chw(cv::Mat)’: /mnt/src/inference.cpp:43:54: error: invalid static_cast from type ‘float’ to type ‘float*’ float* hostInputBuffer= static_cast<float*>(total); ^ /mnt/src/inference.cpp:61:12: error: cannot convert ‘float*’ to ‘float’ in return return hostInputBuffer; ^~~~~~~~~~~~~~~ /mnt/src/inference.cpp: In function ‘cv::Mat normalization(std::string)’: /mnt/src/inference.cpp:70:21: error: request for member ‘convertTo’ in ‘hostInputBuffer’, which is of non-class type ‘float’ hostInputBuffer.convertTo(chw_image, CV_32FC3, 1.0/127.5, -1); ^~~~~~~~~ src/CMakeFiles/inference.dir/build.make:65: recipe for target 'src/CMakeFiles/inference.dir/inference.cpp.o' failed make[2]: *** [src/CMakeFiles/inference.dir/inference.cpp.o] Error 1 CMakeFiles/Makefile2:96: recipe for target 'src/CMakeFiles/inference.dir/all' failed make[1]: *** [src/CMakeFiles/inference.dir/all] Error 2 Makefile:86: recipe for target 'all' failed make: *** [all] Error 2

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

fana

2021/11/19 02:16

そもそも, > 画像のshape という語は,世間一般に通用する物なのですか? 言い換えれば,(256, 256, 3) とか (1, 3, 256, 256) とだけ言えば,それで伝わる物ですか? この2つの間で既に数値の個数が異なっているのですが, --- "画像のshape" という場合には, 「数値が3個の場合には1番目の数値は××で2番目の数値は▲▲で…」 「数値が4個の場合には…(略)」 --- みたいな定義がどこかに存在するのでしょうか? そうであれば,それを示していただきたいのですが.
fana

2021/11/19 02:25

> このサイトを参考にしたのですが上手くいきません リンク先を見ると, segmentation fault (core dumped) とかいうことになるコードである様子ですが,そんなのを参考にしてて大丈夫なんですか?
fana

2021/11/19 03:04

それはそれとして,OpenCVの話ならば,質問に OpenCVのタグ をつけた方が良い(CVを使っている人に見られやすくなる)かと.
guest

回答3

0

自己解決

pytorch のinput用です
cv::dnn::blobFromImage(image, CHWImage);

投稿2021/11/20 06:53

trafalbad

総合スコア303

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

(H, W, C)を(1, C, H, W)に

こういう話か?

C++

1int main() 2{ 3 const int H = 5; 4 const int W = 8; 5 const int C = 3; 6 cv::Mat Src( cv::Size(W,H), CV_8UC(C) ); 7 //※Srcにてきとーな値を入れておく 8 for( int row=0; row<H; ++row ) 9 { 10 for( int col=0; col<W; ++col ) 11 { 12 auto &Elem = Src.at< cv::Vec<unsigned char, C> >( row, col ); 13 for( int ch=0; ch<C; ++ch ) 14 {//※ row, col, ch それぞれの方向について値の変化量が異なるてきとーな値 15 Elem[ ch ] = row*10 + col*3 + ch; 16 } 17 } 18 } 19 20 //よくわからんが,{サイズが 1*C*H で,ch数がW}とかいうMatを作ってみる 21 const int Sizes[] = { 1, C, H }; 22 cv::Mat Dst( 3, Sizes, CV_8UC(W) ); 23 //Dst に Src の対応する値を入れてみる 24 for( int dim0=0; dim0<Sizes[0]; ++dim0 ) 25 { 26 for( int dim1=0; dim1<Sizes[1]; ++dim1 ) 27 { 28 for( int dim2=0; dim2<Sizes[2]; ++dim2 ) 29 { 30 auto &Elem = Dst.at< cv::Vec<unsigned char, W> >( dim0, dim1, dim2 ); 31 for( int ch=0; ch<W; ++ch ) 32 { 33 const int SrcRow = dim2; 34 const int SrcCol = ch; 35 const int SrcCh = dim1; 36 Elem[ch] = Src.at< cv::Vec<unsigned char, C> >( SrcRow, SrcCol )[ SrcCh ]; 37 } 38 } 39 } 40 } 41 //Dst の内容を表示してみる 42 for( int dim0=0; dim0<Sizes[0]; ++dim0 ) 43 { 44 for( int dim1=0; dim1<Sizes[1]; ++dim1 ) 45 { 46 for( int dim2=0; dim2<Sizes[2]; ++dim2 ) 47 { 48 std::cout 49 << "( " << dim0 << ", " << dim1 << ", " << dim2 << " ) : " 50 << Dst.at< cv::Vec<unsigned char, W> >( dim0, dim1, dim2 ) 51 << std::endl; 52 } 53 } 54 } 55 56 return 0; 57}

↑のコードの出力結果:

( 0, 0, 0 ) : [0, 3, 6, 9, 12, 15, 18, 21] ( 0, 0, 1 ) : [10, 13, 16, 19, 22, 25, 28, 31] ( 0, 0, 2 ) : [20, 23, 26, 29, 32, 35, 38, 41] ( 0, 0, 3 ) : [30, 33, 36, 39, 42, 45, 48, 51] ( 0, 0, 4 ) : [40, 43, 46, 49, 52, 55, 58, 61] ( 0, 1, 0 ) : [1, 4, 7, 10, 13, 16, 19, 22] ( 0, 1, 1 ) : [11, 14, 17, 20, 23, 26, 29, 32] ( 0, 1, 2 ) : [21, 24, 27, 30, 33, 36, 39, 42] ( 0, 1, 3 ) : [31, 34, 37, 40, 43, 46, 49, 52] ( 0, 1, 4 ) : [41, 44, 47, 50, 53, 56, 59, 62] ( 0, 2, 0 ) : [2, 5, 8, 11, 14, 17, 20, 23] ( 0, 2, 1 ) : [12, 15, 18, 21, 24, 27, 30, 33] ( 0, 2, 2 ) : [22, 25, 28, 31, 34, 37, 40, 43] ( 0, 2, 3 ) : [32, 35, 38, 41, 44, 47, 50, 53] ( 0, 2, 4 ) : [42, 45, 48, 51, 54, 57, 60, 63]

この解釈だと,結果のMatのch数はWになるわけだが,
元の Mat のサイズが普通な画像だったりすると,ch数はかなりでかい値になる(VGAだったら640だ).

で,おそらくOpenCVの多くの関数では,そういったch数のデータをサポートしないハズ.
(特に Mat を「画像」として扱うような関数群はサポートしないであろう)

なので,こんな変則的な次元とch数を持つMatを作ることにどれだけの意義があるのか? というのはかなり疑問.

投稿2021/11/19 03:00

fana

総合スコア11996

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

OpenCVはほとんどいじっていないので知りませんが、

shape(256, 256, 3)をinput用に(1, 3, 256, 256)に変換

という操作を変数の操作、変換式などで定義できますか? 少なくとも自分が「何が欲しいのか」をプログラムの次元で表現できないとプログラムができるわけないですからね。

とりあえず、文法エラーがあるということはそれは「プログラム未満のなんだかわからん文字列」でしかないということなので、文法エラーを潰したいのですがしかし、何が欲しいのかがわからないと、どう直したらいいかという方針も立ちません。

/mnt/src/inference.cpp:43:54: error: invalid static_cast from type ‘float’ to type ‘float*’
floatからfloat*へのキャストなんてできるわけないだろ!、と言っています。
/mnt/src/inference.cpp:70:21: error: request for member ‘convertTo’ in ‘hostInputBuffer’, which is of non-class type ‘float’
floatはクラスでもないのに、convetToなんていうメンバーがあるか!と言っています。

もしかすると、floatの配列を作ってそこにデータを詰め込んで行くことから話が始まるのでしょうか。
後者は前の質問もなにか絡んでいそうですが。とすると、covertToはcv::Matのメンバーのつもりだったんでしょうかね。とすると、作らなきゃいけないのはcv::Matということになりますが。

投稿2021/11/18 23:36

thkana

総合スコア7703

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問