teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

1

d

2020/01/27 08:37

投稿

tiitoi
tiitoi

スコア21960

answer CHANGED
@@ -2,4 +2,50 @@
2
2
 
3
3
  この場合、画素ごとにヒストグラムを持っておけばいいので、計算に必要な配列の大きさは (画像の高さ, 幅, 256) で済みます。
4
4
 
5
- [ヒストグラムが与えられたデータから,中央値を求める方法|数学|苦手解決Q&A|進研ゼミ高校講座|ベネッセコーポレーション](https://kou.benesse.co.jp/nigate/math/a13m0401.html)
5
+ [ヒストグラムが与えられたデータから,中央値を求める方法|数学|苦手解決Q&A|進研ゼミ高校講座|ベネッセコーポレーション](https://kou.benesse.co.jp/nigate/math/a13m0401.html)
6
+
7
+ ## 追記
8
+
9
+ 最初に書いたヒストグラムの案もそのサイズだと厳しいので、「ブロックごとに中央値を直接計算する」または「ブロックごとにヒストグラムを計算して、中央値をあとから計算する (枚数が256枚以上ならこちらのが省メモリ)」になるかと思います。
10
+
11
+ ## コード
12
+
13
+ OpenCV のサンプル動画 [vtest.avi](https://github.com/opencv/opencv/raw/master/samples/data/vtest.avi) をフレームごとに切り出して保存した画像で試しました。
14
+
15
+ ```python
16
+ from pathlib import Path
17
+
18
+ import cv2
19
+ import matplotlib.pyplot as plt
20
+ import numpy as np
21
+
22
+ # 画像のパス一覧を取得する。
23
+ input_dir = Path("input") # 画像があるディレクトリ
24
+ img_paths = list(input_dir.glob("*.png"))
25
+
26
+ # 1枚だけ読み込み画像の幅、高さを取得する。
27
+ img = cv2.imread(str(img_paths[0]))
28
+ h, w = img.shape[:2]
29
+
30
+
31
+ median_img = np.empty_like(img)
32
+
33
+ stride_y, stride_x = 300, 300 # ブロックの大きさ
34
+ for y in range(0, h, stride_y):
35
+ for x in range(0, w, stride_x):
36
+ # ブロックごとに中央値を計算する。
37
+ values = []
38
+ for path in img_paths:
39
+ img = cv2.imread(str(path))
40
+ values.append(img[y : y + stride_y, x : x + stride_x])
41
+ median = np.median(values, axis=0).astype(np.uint8)
42
+ median_img[y : y + stride_y, x : x + stride_x] = median
43
+
44
+ # 結果を可視化する。
45
+ fig, ax = plt.subplots()
46
+ ax.imshow(median_img[..., ::-1])
47
+
48
+ plt.show()
49
+ ```
50
+
51
+ ![イメージ説明](5369190f3da4b70921e6eb4324a94e28.png)