byte配列に格納している画像データをMatに画像配列として保存します。この時、cv::imdecodeを使用しています。その後に画素値の変換をかけてcv::imencodeで再び画像データをbyte配列に戻そうとしたところ圧縮の影響で元々のbyte配列の画像データと異なる配列数になってしまいます。
imencode、imdecodeをかませても配列数を保ったままbyteの画像変換はできないでしょうか?
よろしくお願いいたします。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2016/03/04 13:06

回答3件
0
かなり遅い返信ですが、最近一部似たような状態に遭遇したので返信します。
私の場合は、生画像またはimencode()で圧縮した画像を、ソケット通信で送信→受信して、受信したBYTE配列(char *型)をMat型に復元したい。です。
ちょっとずれた回答かもしれませんが、どなたかの参考になれば幸い。
まず、PNG形式であれば可逆圧縮なので、imencode()前と、imdecode()後は同じになるはずです。
そしてBYTE配列から画像を取り出す件について。(申し訳ないのですが、いま手元に開発環境ないので、下記のコードは非検証です。方向性はあっているはずなので、ミスあれば指摘頂けると幸い。)
・圧縮されたBYTE配列があり、それをMat型にしたい場合
imdecode()の戻値がMat型なので復元できます。(ただしBYTE配列の長さはimencode()した時に決まるので、imencode()によりリサイズされたバッファの.size()を取得し、そのサイズを別途知る必要があります。)以下のような感じ。
C++
1// 受信側 2char *cBuf; // ←この先に受信した圧縮されたBYTE配列が既に入っているものとする 3int size = 10240; // ←このサイズは別途分かっているものとする 4vector<uchar> buf; 5buf.assign(cBuf, cBuf + size); 6cv::Mat m = cv::imdecode(cv::Mat(buf), -1);
・非圧縮の生画像のBYTE配列があり、それをMat型にしたい場合
imdecode()は使えないので、なんとかMat型のdatastart~dataendの領域にデータを入れてやればいいのですが、直接代入するとおかしなことになります。なので、単純にMat型の引数付きコンストラクタを使います。以下のような感じ。
C++
1// 受信側 2char *cBuf; // ←この先に受信した非圧縮BYTE配列が既に入っているものとする 3int rows = 480; // ←このサイズは別途分かっているものとする 4int cols = 640; // ←このサイズは別途分かっているものとする 5cv::Mat m(rows, cols, CV_8UC3, (void *)cBuf); // 透過ありだとCV_8UC4?
投稿2018/09/19 15:12
総合スコア78
0
ベストアンサー
imencode、imdecodeをかませても配列数を保ったままbyteの画像変換はできないでしょうか?
変換前の画像は今の所指定はしておらず(pngやjpgを使うことが多い)、変換後の画像の形式はjpgで吐き出すようにしています。
入力が1000byteのデータだとしたら出力も1000byteで得たいです。
実際問題として実現不可能です。若干条件を緩和して、入力データサイズ>出力データサイズ ならば、偶然上手くいくこともありますが、実効上は全くお勧めしません。
入出力データとして想定されているPNGやJPEGといったデータ形式は、一定のアルゴリズムにより「圧縮」されています。このような変換が行われたデータでは、圧縮された状態のデータサイズと、展開したオリジナルのデータサイズにほとんど相関がありません。
PNGとJPEGでは根底にある考え方(lossless vs. lossy)が大きく異なるのですが、JPEGだけをとってみても、N
バイトのデータをデコード(imdecode)して映像を加工、エンコード(imencode)した後の出力バイト数を制御することは現実的には不可能です。JPEGの場合はかなり古い規格ということもあり、その仕様上も出力バイト数を細かく制御できません(荒い制御は可能です)。また、データサイズを小さくすればするほど、画像としては汚く(劣化)します。
投稿2016/03/04 14:17
総合スコア6191
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。

0
こんにちは。
記述ミスかも知れませんが、生画像をデコードできないですよ。生画像をエンコードしてjpegやpngへ変換します。jpegやpngをデコードして生画像を出来るだけ回復します。
【追記】
そのjpgをデコードして生画像をエンコード前と同じbyte配列数で復元したいのですが無理ですかね?
私はimencode, imdecodeを使ったことはないのでずか、復元する画像のサイズやピクセル情報のバイト数を元の画像と同じになるよう指定すればできる筈ですよ。
ここにサンプルがありました。
jpegに変換して戻す部分は下記ですね。
C++
1 Mat src = imread("lenna.png"); 2 3 //(1) jpeg compression 4 vector<uchar> buff;//buffer for coding 5 vector<int> param = vector<int>(2); 6 param[0]=CV_IMWRITE_JPEG_QUALITY; 7 param[1]=95;//default(95) 0-100 8 9 imencode(".jpg",src,buff,param); 10 cout<<"coded file size(jpg)"<<buff.size()<<endl;//fit buff size automatically. 11 Mat jpegimage = imdecode(Mat(buff),CV_LOAD_IMAGE_COLOR);
このsrcとjpegimageの画像サイズや色深度が異なってしまうと言うことでしょうか?
サンプルを見る限り画像サイズの指定はないようですね。
ピクセル情報のバイト数は、CV_LOAD_IMAGE_COLORの部分で指定するようです。
imread()と同じ指定をすれば同じに出来るはずです。imread()でのデフォルトはCV_LOAD_IMAGE_COLORです。
投稿2016/03/04 00:52
編集2016/03/04 09:44総合スコア23274
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。

あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。