59471


200fps[frame per second]で取得した値を、24fpsにダウンサンプリングしたいです。

24/200=0.12なので

[code]

    0.12*1=0.12
    .
    .
    .
    0.12*8=0.96
    0.12*9=1.08
    
[/code]

と、0.96から1.08など、小数点以下を切り捨てた値が前後で異なった時に  
前後どちらかのループ回数の時に値を取得すれば良いのではないかと思いました。

つまり

[code]

    if not int((loop_count)*(low_fps/high_fps)) == int((loop_count+1)*(low_fps/high_fps)) 
    
[/code]

となれば良いのではと思い、以下のように200回forループを回してprintをしてみたのですが  
なぜか値が25回出力されてしまいます。(本当は24回出力されるのが正しいはず？)

[code]

    loop_count=1
    high_fps=200
    low_fps=24
    for num in range(200):
        if loop_count == 1 or not int((loop_count)*(low_fps/high_fps)) == int((loop_count+1)*(low_fps/high_fps)) :
            print(loop_count)
    
        loop_count=loop_count+1
    
[/code]


CC BY-SA 4.0
2019-10-04T09:33:36.830
59463
2019-10-05T06:30:08.943
2019-10-05T06:30:08.943
3060
34471
question
python 数学
200回/1秒の頻度で取得した値を、24回/1秒の頻度のデータに落とすダウンサンプリングをするには


専門家ではないのですが、追加されている条件loop_count==1が悪さをしているのかな、と思います。


CC BY-SA 4.0
2019-10-04T10:21:28.010
59464
2019-10-04T10:21:28.010
35281
59463
answer


2000 : 24
のような大きな比でのダウンサンプリングであれば、線形補間など考慮する必要がありませんし、基本的な考え方はあなたのやり方であっているように思うのですが、浮動小数点を含む計算や切り捨てが絡んでくると話がややこしくなってきて、どこで差の1が出てくるのか検証するのは大変そうです。

例えば、以下のようにしてみてはどうでしょうか。

[code]

    high_fps=200
    low_fps=24
    # 時間を測る単位
    pitch = high_fps * low_fps
    last_sample_number = -1
    for num in range(200):
      # `num`は`high_fps`でのサンプル番号を表している
      # それを`period`単位での時間に変換する
      time_in_period = num * pitch/high_fps
      # 時間を`low_fps`でのサンプル番号に変換する
      sample_number_in_low_fps = time_in_period // (pitch/low_fps)
      # `low_fps`でのサンプル番号に変化があったら、その時点でサンプルを取る
      if sample_number_in_low_fps != last_sample_number:
        last_sample_number = sample_number_in_low_fps
        print(num)
    
[/code]

[code]

    0  1  2  3  4  5  6  7  8  9  10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25…
    |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  | …
    |                        |                        |                        | …
    0  0  0  0  0  0  0  0  0  1  1  1  1  1  1  1  1  2  2  2  2  2  2  2  2  3 …
    
[/code]

上段から順に、

  * 2000 Hzでサンプリングした時のサンプル番号
  * 2000 Hzでサンプリングした時のサンプル時刻
  * 24 Hzでサンプリングする時のサンプル時刻
  * 24 Hzでサンプリングする時のその時刻のサンプル番号

と言う感じですね。

ある時刻のデータが「24 Hzなら何番目のサンプルになるか」を求めて、その「何番目」の値が変化する時のデータを「24 Hzでのサンプル値」とします。

この例で言うと「2000 Hzでサンプリングした時のサンプル番号」が0, 9, 17, 25, ...の時の値を「24
Hzでのサンプル値」として拾えばいいと言うことになります。

上記のコード、`high_fps`と`low_fps`の値を変えながら試してみて、所望の結果になるか確認してみてください。

* * *

あまり本質的ではないですが、`for num in
range(200)`で、`num`には0〜199の値が入るのだから、`loop_count`なんてものを別に用意するのは、あまり意味がないように思います。


CC BY-SA 4.0
2019-10-05T02:23:25.107
59470
2019-10-05T02:23:25.107
13972
59463
answer


間引くだけで良いなら、`high_fps`の回数を回す必要は無いのでは？  
間引いて取得するための位置(添え字)は計算で求められるでしょう。  
以下で`low_fps`の回数回せば、1秒分の添え字のリストが出来ます。

[code]

    high_fps = 200.0
    low_fps = 24.0
    interval = high_fps / low_fps
    
    sample_index = []
    for i in range(int(low_fps)):
        # 例として0から始まって四捨五入とする。
        # 好みで切り上げ/切り捨て等に変えたり、開始位置を調整する
        sample_index.append(round(float(i) * interval))
    
[/code]

そして`high_fps`のデータが`data`というリストに入っているものとすれば、  
上記`sample_index`を以下のように適用すれば、間引いたデータが`new_data`に取得出来るでしょう。

[code]

    data_count = len(data)
    high_fps_int = int(high_fps)
    data_seconds = data_count // high_fps_int
    
    new_data = []
    for sec in range(data_seconds):
        base_index = sec * high_fps_int
        for work_index in sample_index:
            curr_index = base_index + work_index
            if curr_index >= data_count:
                break
            new_data.append(data[curr_index])
    
[/code]


CC BY-SA 4.0
2019-10-05T04:43:26.843
59471
2019-10-05T04:43:26.843
26370
59463
answer