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

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

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

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

Python

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

Q&A

解決済

2回答

4100閲覧

のりしろを考慮して分割した画像を結合する

sobajiro

総合スコア3

OpenCV

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

Python

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

0グッド

0クリップ

投稿2021/06/29 10:25

前提・実現したいこと

  1. 画像を分割してサブ画像を作る。(各サブ画像は同じ大きさ)
  2. サブ画像を処理する。
  3. サブ画像を再度1枚の画像に戻す。

このとき、ステップ3で生成された1枚の画像には、サブ画像の境界部に境界線ができてしまう。
ステップ1にてに境界部に余裕を持ってサブ画像を生成し、ステップ3では元画像で同じ箇所にあった部分をのりしろのようにして、境界線が生まれないように画像を生成したい。

ステップ1にて分割することは達成できているため、
ステップ3にて結合する際にのりしろを考慮して(重なっている部分は平均画素値をとる、等)結合するコードがあれば教えていただきたいです。

▼イメージ
イメージ説明

試したこと

のりしろを考えずにサブ画像を結合したコードは以下となります。

import os import glob # from PIL import Image # import pathlib # from pathlib import Path import cv2 import numpy as np seq = "SEQUENCE_NAME" res_before_concat = "SUB_IMAGE_DIRECTORY/" res_after_concat = "CONCAT_IMAGE_DIRECTORY/" frame_num = 300  # 処理する画像枚数 split_num = 64 # ここでは縦横8分割したサブ画像の結合を考える def concat_tile(im_list_2d): return cv2.vconcat([cv2.hconcat(im_list_h) for im_list_h in im_list_2d]) for i in range(1,frame_num+1): num_f ="{:03d}".format(i) frame_name = "Frame "+num_f+".png" for k in range(0,split_num): num_fk ="{:02d}".format(k) path_png = res_before_concat + seq + num_fk + '/'+ frame_name if k == 0: im0 = cv2.imread(path_png) elif k == 1: im1 = cv2.imread(path_png) elif k == 2: im2 = cv2.imread(path_png) elif k == 3: im3 = cv2.imread(path_png) elif k == 4: im4 = cv2.imread(path_png) elif k == 5: im5 = cv2.imread(path_png) elif k == 6: im6 = cv2.imread(path_png) elif k == 7: im7 = cv2.imread(path_png) elif k == 8: im8 = cv2.imread(path_png) elif k == 9: im9 = cv2.imread(path_png) elif k == 10: im10 = cv2.imread(path_png) elif k == 11: im11 = cv2.imread(path_png) elif k == 12: im12 = cv2.imread(path_png) elif k == 13: im13 = cv2.imread(path_png) elif k == 14: im14 = cv2.imread(path_png) elif k == 15: im15 = cv2.imread(path_png) elif k == 16: im16 = cv2.imread(path_png) elif k == 17: im17 = cv2.imread(path_png) elif k == 18: im18 = cv2.imread(path_png) elif k == 19: im19 = cv2.imread(path_png) elif k == 20: im20 = cv2.imread(path_png) elif k == 21: im21 = cv2.imread(path_png) elif k == 22: im22 = cv2.imread(path_png) elif k == 23: im23 = cv2.imread(path_png) elif k == 24: im24 = cv2.imread(path_png) elif k == 25: im25 = cv2.imread(path_png) elif k == 26: im26 = cv2.imread(path_png) elif k == 27: im27 = cv2.imread(path_png) elif k == 28: im28 = cv2.imread(path_png) elif k == 29: im29 = cv2.imread(path_png) elif k == 30: im30 = cv2.imread(path_png) elif k == 31: im31 = cv2.imread(path_png) elif k == 32: im32 = cv2.imread(path_png) elif k == 33: im33 = cv2.imread(path_png) elif k == 34: im34 = cv2.imread(path_png) elif k == 35: im35 = cv2.imread(path_png) elif k == 36: im36 = cv2.imread(path_png) elif k == 37: im37 = cv2.imread(path_png) elif k == 38: im38 = cv2.imread(path_png) elif k == 39: im39 = cv2.imread(path_png) elif k == 40: im40 = cv2.imread(path_png) elif k == 41: im41 = cv2.imread(path_png) elif k == 42: im42 = cv2.imread(path_png) elif k == 43: im43 = cv2.imread(path_png) elif k == 44: im44 = cv2.imread(path_png) elif k == 45: im45 = cv2.imread(path_png) elif k == 46: im46 = cv2.imread(path_png) elif k == 47: im47 = cv2.imread(path_png) elif k == 48: im48 = cv2.imread(path_png) elif k == 49: im49 = cv2.imread(path_png) elif k == 50: im50 = cv2.imread(path_png) elif k == 51: im51 = cv2.imread(path_png) elif k == 52: im52 = cv2.imread(path_png) elif k == 53: im53 = cv2.imread(path_png) elif k == 54: im54 = cv2.imread(path_png) elif k == 55: im55 = cv2.imread(path_png) elif k == 56: im56 = cv2.imread(path_png) elif k == 57: im57 = cv2.imread(path_png) elif k == 58: im58 = cv2.imread(path_png) elif k == 59: im59 = cv2.imread(path_png) elif k == 60: im60 = cv2.imread(path_png) elif k == 61: im61 = cv2.imread(path_png) elif k == 62: im62 = cv2.imread(path_png) elif k == 63: im63 = cv2.imread(path_png) im_tile = concat_tile([[im0, im1, im2, im3, im4, im5, im6, im7], [im8, im9, im10, im11, im12, im13, im14, im15], [im16, im17, im18, im19, im20, im21, im22, im23], [im24, im25, im26, im27, im28, im29, im30, im31], [im32, im33, im34, im35, im36, im37, im38, im39], [im40, im41, im42, im43, im44, im45, im46, im47], [im48, im49, im50, im51, im52, im53, im54, im55], [im56, im57, im58, im59, im60, im61, im62, im63] ]) cv2.imwrite(res_after_concat + seq + "/" +frame_name, im_tile) print(frame_name)

結果画像

上記コードの結果画像です。
境界線部分を拡大した結果画像となります。ピンクで囲ってあるところが境界線が見えてしまっている例としてわかりやすいかと思います。
イメージ説明

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

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

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

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

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

jbpb0

2021/06/29 22:32

境界線は、サブ画像をつなげたからできるのですか? すなわち、ステップ2によって、サブ画像間で明るさや色に微妙な違いが生じて、つなげたら段差のように感じる それとも、ステップ2をやったら、サブ画像の外周に線が付いてしまうのですか? 前者なら、質問に書いてるやり方が有効ですが、後者なら、サブ画像の外周をカットしてからつなげる方がいいと思います 質問の画像を見ると、後者に見えるのですが
ppaul

2021/06/29 22:44

もともとの分割にはのりしろがないのに、結合をするときにはのりしろの平均値をとりたいという質問でしょうか。どこでのりしろが発生するのでしょう?
fana

2021/06/30 02:00

> ステップ1にてに境界部に余裕を持ってサブ画像を生成し という話から推測するに, 各サブ画像は共通部を有している,という話なのかな,と思うのですが,そういう話ですかね. 例えば,100x100の画像を縦横共に2分割すると,単純には 50x50 の絵を4個作るんだけど,そうじゃなくて,各分割画像の範囲を(範囲の中心位置はそのままに)少し上下左右に膨らませて例えば 60x60 の絵を4個作る,みたいな. (これだと各分割画像の上下左右の幅5pixelの部分は他の分割画像も保有している)
sobajiro

2021/06/30 03:32

一旦ステップ2をはさまずに、ステップ1→ステップ3としたところ、境界線は生じませんでした。 そのため、ステップ2の処理によってサブ画像の外周に線がついてしまったと考えられます。 ご教授していただいた通り、サブ画像の外周をカットしてから結合しようと思います。ありがとうございました。 > 境界線は、サブ画像をつなげたからできるのですか?
jbpb0

2021/06/30 11:43

ステップ2無しだと、画像を切り離してそのままつなげるだけなので、元の画像を再現するだけだから、境界線はできませんので、それだとサブ画像の外周をカットするだけでいいのかは分かりません ステップ1でオーバーラップさせて(のりしろ有りで)サブ画像に分割して、ステップ2を行い、その後にオーバーラップがちょうど無くなるように各サブ画像の外周を切り取ってから、そのままつなげてみて、段差が見えないか確認してみてください
sobajiro

2021/07/02 03:34 編集

上記の手順で行ったところ(のりしろ&外周切り取りを行ったところ)、境界線は生じませんでした。 > ステップ1でオーバーラップさせて(のりしろ有りで)サブ画像に分割して、ステップ2を行い、その後にオーバーラップがちょうど無くなるように各サブ画像の外周を切り取ってから、そのままつなげてみて、段差が見えないか確認してみてください
fana

2021/07/02 03:42

「ステップ2」が何やってるのか知らんけど, 単にその処理の外縁部の処理方法の影響が見えてるってだけのオチ?
jbpb0

2021/07/02 05:10

fanaさん > その処理の外縁部の処理方法の影響が見えてる そのようですね
guest

回答2

0

境界線ができる原因によって、対処方法が変わります
・ステップ2によって、サブ画像間で明るさや色に微妙な違いが生じて、つなげたら段差のように感じる
・ステップ2をやったら、サブ画像の外周に線が付いてしまう
質問の画像を見ると、後者に見えます
前者なら、質問に書いてるやり方が有効ですが、後者なら、サブ画像の外周をカットしてからつなげる方がいいと思います

ステップ1でオーバーラップさせて(のりしろ有りで)サブ画像に分割して、ステップ2を行い、その後にオーバーラップがちょうど無くなるように各サブ画像の外周を切り取ってから、そのままつなげてみて、段差が見えないか確認してみてください

投稿2021/07/02 08:47

jbpb0

総合スコア7653

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

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

fana

2021/07/02 09:10

例えば 3x3 とかのフィルタを畳み込むような場合 外周部だと「隣接画素が無い」から,処理するためにはそこをどうにかしてごまかす必要がある. そのごまかし結果が今回,「境界線」として見えている,というだけの話ですね.きっと. だから,「隣接画素が無い」という状態での処理結果を最終的に用いないようにするために,サブ画像にフィルタ半径分くらいの「のりしろ」を設けておけば良いだけ,っていう.
guest

0

ベストアンサー

ステップ1にてに境界部に余裕を持ってサブ画像を生成し、ステップ3では元画像で同じ箇所にあった部分をのりしろのようにして、境界線が生まれないように画像を生成したい。

ステップ3にて結合する際にのりしろを考慮して(重なっている部分は平均画素値をとる、等)結合する

こんな話ですかね(コードはC++ですが)

てきとーな200*200サイズの元画像を用意して,
互いに重複する範囲を持つ4つの画像を切り出し,
ここに何か処理して,
最後にまたくっつける.重複部は平均値とする.

イメージ説明

結果画像バッファの上で各サブ画像を全部足し合わせて,最後に各画素の値を重複回数で除してます.

C++

1int main() 2{ 3 cv::Mat SrcImg( 200,200, CV_8UC3 ); 4 SrcImg = cv::Scalar(64,64,64); 5 cv::circle( SrcImg, cv::Point(100,100), 95, cv::Scalar(128,128,128), -1 ); 6 cv::imshow( "Src", SrcImg ); 7 8 //step1 : サブ画像群を境界に余裕をもって切り出し… 9 cv::Rect Regions[4] = 10 { //各サブ画像の切り出し範囲 11 cv::Rect(0,0,120, 120), 12 cv::Rect(80,0, 120,120), 13 cv::Rect(0,80, 120,120), 14 cv::Rect(80,80,120,120) 15 }; 16 17 cv::Mat SubImg[4]; 18 for( int i=0; i<4; ++i ) 19 { SubImg[i] = SrcImg( Regions[i] ).clone(); } 20 21 //step2 : なんか個々のサブ画像群に処理が加えられて… 22 cv::multiply( SubImg[0], cv::Scalar(2,1,1), SubImg[0] ); //青成分を2倍 23 cv::multiply( SubImg[1], cv::Scalar(1,2,1), SubImg[1] ); //緑成分を2倍 24 cv::multiply( SubImg[2], cv::Scalar(1,1,2), SubImg[2] ); //赤成分を2倍 25 26 //step3 : サブ画像群の重なる範囲が平均化される形で統合 27 cv::Mat WorkImg = cv::Mat::zeros( 200,200, CV_16UC3 ); 28 cv::Mat RefCountImg = cv::Mat::zeros( 200,200, CV_16UC3 ); 29 for( int i=0; i<4; ++i ) 30 { 31 cv::add( SubImg[i], WorkImg(Regions[i]), WorkImg(Regions[i]) ); 32 cv::add( RefCountImg(Regions[i]), cv::Scalar(1,1,1), RefCountImg(Regions[i]) ); 33 } 34 cv::divide( WorkImg, RefCountImg, WorkImg ); 35 36 cv::Mat ResultImg( 200,200, CV_8UC3 ); 37 WorkImg.convertTo( ResultImg, ResultImg.type() ); 38 cv::imshow( "Result", ResultImg ); 39 40 // 41 cv::waitKey(); 42 return 0; 43}

投稿2021/06/30 04:41

編集2021/06/30 04:44
fana

総合スコア11996

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問