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

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

ただいまの
回答率

90.35%

  • Python

    9119questions

    Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

  • OpenCV

    1224questions

    OpenCV(オープンソースコンピュータービジョン)は、1999年にインテルが開発・公開したオープンソースのコンピュータビジョン向けのクロスプラットフォームライブラリです。

python opencv 画像結合について

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 957

nekomami

score 4

 前提・実現したいこと

フォルダに入る画像(定期的に更新され、画像名も数も異なりますが同じサイズです)を、
横3列で結合したいと思います。
フォルダに入っている画像が6つなら、横3列縦2行、8つなら横3列縦3行、最後はblankの画像を入れて計9つで結合したいです。

リストに画像を入れて、concatで結合するのはどうかと思いましたが、
cv2.hconcat([ ]) の中にリストを入れて結合することはできないのでしょうか。

count = フォルダに入っているファイル数
filelist = ファイル名がリストで入っています

num = 0
img = []

while (num < count):
    img.append(num)
    img[num] = filelist[num]
    num += 1


↑これで画像名が入ると思うのですが、下から2行目を

img[num] = cv2.imread(filelist[num])

に書き換えて画像が読み込まれますか、、。
実行してもエラーはでませんが、読み込まれているかどうか
確認する方法がわかりません。
読み込まれているようでしたら、

image = cv2.hconcat([ この中にimg[0,1,2]を入れたい ])

↑こんなことはできないでしょうか。
hconcat([ の中にいろいろ書き込んでみましたが、エラーばかりです。
主にSyntaxErrorです。
実行できたとして、ここからどうするのか上記目的まで果てしないなと思っておりますが、
勉強がてら少しずつ理解していきたいと思っています。

初心者で不慣れなものですから、尋ねておきながら間違いや漏れがありましたらごめんなさい。
こんな方法でなくても、他に方法があるようでしたら教えていただけると嬉しいです。
どうぞよろしくお願いいたします。

 発生している問題・エラーメッセージ

SyntaxError: can't assign to operator

 該当のソースコード

ソースコード

 試したこと

ここに問題に対して試したことを記載してください。

 補足情報(FW/ツールのバージョンなど)

windows7
python-3.6.4
opencv-3.4.1

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+4

問題を少しずつ解きほぐしましょう。
註:思考の順序に沿って章立てしているので、実際の解決法と順番が前後します。

縦横に連結すること

こちらのコードを借りてみてはいかがでしょうか。

def concat_tile(im_list_2d):
    return cv2.vconcat([cv2.hconcat(im_list_h) for im_list_h in im_list_2d])

引用元: Python, OpenCVで画像を縦・横に連結 (hconcat, vconcat, np.tile)

例えばimg0からimg5を、横書きの方向に連結したいなら次のように呼べば良いです。

result = concat_tile(
    [[img0, img1, img2],
     [img3, img4, img5]]
)

しかし毎回このように書くのは随分面倒ですね。自動化しましょう。

呼び出しに合わせてリストを変形すること

次のようなイディオムが利用できるでしょう。

>>> print(my_list)
[0, 1, 2, 3, 4, 5]
>>>
>>> my_list_for_arg = [list(row) for row in zip(*[iter(my_list)]*3)]
>>> print(my_list_for_arg)
[[0, 1, 2], [3, 4, 5]]

このように書ける理由については、ちょっと煩雑なのでリンクに投げます。
気になるようなら読んでみてください。


さて、この時点で6画像の場合は連結できるはずです。
問題は空きマスが出る8画像のバージョンです。ダミーの画像を用意する必要があります。

結合可能な空画像を生成すること

結合可能にするためには、次の二条件に注意する必要があります。

  • 画像の形状 (shape)
  • 画素値を表現する数値型 (dtype)

モデル画像imgが既にあるとき、次のように真っ黒な画像を生成できます。

empty = np.zeros(img.shape, dtype=img.dtype)

次の問題は、空画像をどのように扱うか、です。

空画像を画像リストに追加すること

画像数が3の倍数になるまで、空画像をリストimgsに押し込んでやりましょう。

while len(imgs) % 3 != 0:
    imgs.append(empty)

ここまでやれば、8画像の場合にも対応できます。

結局どう書けばいいか?

処理の流れは次のとおりです。

  1. 画像名を取得し、リストimg_namesを作る。
  2. OpenCVを用いて各画像を読み込み、リストimgsを作る。
  3. imgs[0]をモデルに、空画像emptyを作っておく。
    上記『結合可能な空画像を生成すること』を参照のこと。
  4. imgsのリスト長が3の倍数になるまでemptyをimgsに押し込む。
    上記『空画像を画像リストに追加すること』を参照のこと。
  5. imgsの形状を適切に変形し、concat_tileに渡す。
    上記『呼び出しに合わせてリストを変形すること』を参照のこと。
  6. 返り値が目的の画像。

その他

画像が読み込まれますか、、。実行してもエラーはでませんが、読み込まれているかどうか確認する方法がわかりません。

OpenCVのPythonバインディングは、imreadに失敗するとNoneを返すというえげつない設計です。
個人的には次のように書いておくことが多いです。

img = cv2.imread(ファイル名)
assert img is not None

このように書いておけば、読み込みに失敗したときも早い段階でエラーに出来ます。


hconcat([ の中にいろいろ書き込んでみましたが、エラーばかりです。主にSyntaxErrorです。
...[中略]...

SyntaxError: can't assign to operator

こればっかりはコードを読んでみないとなんとも言えません。
見たことがないわけではないですが...

>>> b = 3
>>> a + b = 10
  File "<stdin>", line 1
SyntaxError: can't assign to operator

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/05/17 17:36

    ありがとうございます。
    ご丁寧に回答いただけてうれしいです。
    お返事いただいた内容を少しずつ調べて進めて理解していきます。
    長文でご親切にお返事いただけると思っておりませんでしたので、
    内容はまだ理解できておりませんが、取り急ぎお礼が言いたくてお返事しました。
    こちらの利用方法もあまり詳しく理解しないまま質問してしまいましたので
    何かアクションしないまま失礼があるのではと思いますが、
    お返事いただいた内容にまたつまづくことになるレベルまで理解が達しましたら、
    またコメントさせていただきます。(時間がかかりそうですがすみません)

    キャンセル

  • 2018/05/17 18:19

    よく練られている質問文だと思いました。
    ・各種バージョンが明記されている
    ・画像のサイズについての言及がある (非常に大事)
    ・なにを考えてなにを試したか、そしてその結果について言及がある
    ・実現したいことを具体的に記述しており、あいまいさが少ない

    キャンセル

  • 2018/05/22 14:49

    LouiS0616さん

    ご連絡遅くなりましてすみません。
    先日はありがとうございました。
    教えていただいた通り進めまして、画像結合まで至りました。
    本当にありがとうございました。
    プログラムそのものも初めて触るため、ひとつひとつを調べながらで時間がかかってしまいましたが、目的が達成できて嬉しいです。

    ご回答いただきました処理の、1.2.3までは理解できまして、
    3の空画像は、作成したjpgを読み込みました。

    4.imgsのリスト長が3の倍数になるまでemptyをimgsに押し込む。
    5.imgsの形状を適切に変形し、concat_tileに渡す。
    ↑この2つは理解できていないまま、使わせてもらいました。
     少しずつ勉強します。

    6.返り値が目的の画像。
    ↑これは、
    cv2.imwrite('result.jpg', concat_tile(im_list_2d))
    で、書き出されました。

    ご親切にしていただきありがとうございました。

    キャンセル

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

  • ただいまの回答率 90.35%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る

  • Python

    9119questions

    Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

  • OpenCV

    1224questions

    OpenCV(オープンソースコンピュータービジョン)は、1999年にインテルが開発・公開したオープンソースのコンピュータビジョン向けのクロスプラットフォームライブラリです。