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

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

ただいまの
回答率

91.36%

  • Python

    3863questions

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

  • Python 3.x

    2438questions

    Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

KivyのFBOを使う事でのフレームバッファー

解決済

回答 1

投稿 2017/12/02 17:59

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

こんにちは、KivyのFBO(Framebuffer)についてです。
このFBOを利用する事で、フレームバッファ機能を作れるとのことですが、
実際どのように作成するのかわかりません。

私の目標はiOSのナビゲーションバーで使われている、ブラー効果を作る事です。
わたしの考えでは、表示した画面の一部をFBOでフレームバッファーとして再利用し、effectモジュールでブラー効果をつければ出来るのではと考えています。

ですが、その足がかりとなりそうなFBOがよくわからないのです。
下記のようなコードを書きました。

(...Pythonファイルの方は本家サイトのリファレンスそのままです。...)

私の気がかりな部分は

self.fbo = Fbo(size=(256, 256))

with self.fbo:

の二つです。
とりあえずself.fboがカンバスと同じ用量なのは理解しました。
ただ、Fbo関数がなんのためにあって、何をする関数なのかがわかりません。

もしkivyの言うフレームバッファというものが、Rectangleなどを使っての図形描画でしか表示することができないのであれば私の目標は達せないことになります。

この、Fbo関数が何かを教えて下さい。

もしわかれば、iOSブラーをどう作るかを教えて下さい。

from kivy.app import App
from kivy.lang import Builder
from kivy.core.window import Window
from kivy.graphics import Fbo, Color, Rectangle
from kivy.uix.widget import Widget


Window.clearcolor = (1, 1, 1, 1)

class FboTest(Widget):
    def __init__(self, **kwargs):
        super(FboTest, self).__init__(**kwargs)

        # first step is to create the fbo and use the fbo texture on other
        # rectangle

        with self.canvas:
            # create the fbo
            self.fbo = Fbo(size=(256, 256))

            # show our fbo on the widget in different size
            Color(1, 1, 1, 1)
            Rectangle(size=(500, 500), texture=self.fbo.texture)

        # in the second step, you can draw whatever you want on the fbo
        with self.fbo:

            Color(0, 0, 1, 1)
            Rectangle(size=(256, 64))
            Color(0, 1, 0, 1)
            Rectangle(size=(256, 64), pos=(0, 64))


class FboApp(App):

    def build(self):
        pass

if __name__ == '__main__':
    FboApp().run()
#kvfile
#ファイル名は fbo.kv

ScreenManager:
    sca: sca
    Screen:
        id: sca
        name: "ScreenA"
        ScrollView:
            size_hint_y: 1
            pos_hint: {'top': 1}
            GridLayout:
                cols: 1
                size_hint: 1, None
                height: self.minimum_height
                padding: 0, sp(50), 0, sp(50)
                FboTest:
                    transitions: transitions
                Label:
                    id: transitions
                    text: "Pellentesque"
                    font_size: 150
                    text_size: self.width, None
                    size_hint: 1, None
                    height: self.texture_size[1]
                    color: 0.000  ,0.4784  ,1.000, 1

        RelativeLayout:
            size_hint: 1, None
            height: sp(100)
            canvas.before:
                Color:
                    rgba: 1,1,1,.8
                Rectangle:
                    size: self.size
                    pos: self.pos
  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 1

checkベストアンサー

+1

この、Fbo関数が何かを教えて下さい。

その関数を呼び出すことでフレームバッファを作ってます。
「with self.canvas:」内で呼ぶことに違和感があるかもしれませんが、個人的にはそうすることでself.canvasと同じ形式(色深度やピッチとか色々)のフレームバッファを作っていると思ってます。

もしわかれば、iOSブラーをどう作るかを教えて下さい。

EffectWidgetが使えるかと。

from kivy.app import runTouchApp
from kivy.lang import Builder


root = Builder.load_string(r'''
#:import ew kivy.uix.effectwidget
<Label>:
    font_size: 50
    bold: True
    canvas.before:
        Color:
            rgb: 0, 0, 0,
        Rectangle:
            pos: self.pos
            size: self.size

BoxLayout:
    orientation: 'vertical'
    Label:
        text: 'NoEffect'
    EffectWidget:
        effects: [ew.PixelateEffect(), ]
        Label:
            text: 'Pixelate'
    EffectWidget:
        effects: [ew.HorizontalBlurEffect(size=30.0), ]
        Label:
            text: 'HorizontalBlur'
    EffectWidget:
        effects: [ew.VerticalBlurEffect(size=30.0), ]
        Label:
            text: 'VerticalBlur'
    EffectWidget:
        effects: [ew.VerticalBlurEffect(size=30.0), ew.HorizontalBlurEffect(size=30.0), ]
        Label:
            text: 'VerticalBlur + HorizontalBlur'
''')

runTouchApp(root)


screenshot

もし希望のEffectが無い場合は自分で作る事になると思います。ソースコードを見る限りはGLSLを書かないといけないようなので難易度は高そうですが。

投稿 2017/12/02 21:43

編集 2017/12/03 23:34

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/12/02 22:21

    ありがとうございます^^
    すいません、EffectWidgetについては知っていました。
    例えば、iOSのようにウィジェットの背景をブラーする場合はどういった工夫を講じれば良いのか、もしわかれば教えて下さい。

    キャンセル

  • 2017/12/02 22:24

    ちなみにそのEffectwidgetですが、特定の範囲内のみをBlurするなどはできますか?
    self.widgetやidsなどから取得したウィジェットからではなく、例えばcollidepointをうまく工夫して座標を取得し、その部分のみにEffectwidgetを当てるような?

    キャンセル

  • 2017/12/02 22:26

    希望のEffectが無いのならやっぱり自分でEffectBaseを継承したclassを作ってGLSL葬るしかないんじゃないかと、ちょっと他の方法は今の所思いつかないですね。

    キャンセル

  • 2017/12/02 22:29

    gottadiveintopyさん、ありがとうございます。
    やはりがんばって実装しなきゃダメみたいですねGLSLでなんとか^^;
    あと、趣旨違いですがkivyユーザーってどのくらいなんですかね?

    キャンセル

  • 2017/12/03 01:10 編集

    > ちなみにそのEffectwidgetですが、特定の範囲内のみをBlurするなどはできますか?

    ドキュメントを読む限りEffectWidget自体にはそのような機能はなさそうです。GLSLにできるのかまではわからなないですが。

    > self.widgetやidsなどから取得したウィジェットからではなく、例えばcollidepointをうまく工夫して座標を取得し、その部分のみにEffectwidgetを当てるような?

    EffectWidgetは自分の子にしかEffectをかけれないので、ぼかしたい部分を参照するImageウィジットをEffectWidgetの子にしてやればできそうです。

    私はiOS持ってなくでkevinさんの求める物の細かい部分がわからないのですが、 ぼかす前の背景はどのぐらいの頻度で変わりますか?又ぼかす位置はリアルタイムで変わりますか?
    背景の変更頻度が少ないなら背景全体をぼかしたTextureを非GLSLでもいいので作っておけばEffectWidgetを使わずともやりたい事は実現できると思いますよ。

    キャンセル

  • 2017/12/03 15:14

    gottadiveintopyさん
    ありがとうございます!
    ボカシ位置についてですが、すりガラスのようなイメージです。
    下記にイメージの参考になりそうな動画のURLを添付しておきます。
    この動画投稿者の方はkivyで実装しているようです。
    https://www.youtube.com/watch?v=KwIRVxVITEw
    この方のやっていることと同じことをやりたいのです。

    この方は別なkivyuserが制作したウィジェッとにマスクをかけるコードを利用して、ブラーを実現しているようです。
    そのコード自体にはGLSLでマスク効果を実現してるっぽいのです。


    >> 背景の変更頻度が少ないなら背景全体をぼかしたTextureを非GLSLでもいいので作っておけばEffectWidgetを使わずともやりたい事は実現できると思いますよ。

    ですよね^^;
    私もGLSL使わない線で考えてみたものがあります。

    要素を画像化し、それにブラー効果をかけてスクロールした時に同じスクロール量で移動させると言うものでした。
    しかし、これにはkivyで撮影した際、画面内(ウィンドウ内)のスクリーンショットのみしか取れず、その描画領域全体を撮影することは困難でした。

    自分はこんな感じしか考えつきませんでした。
    もし、gottadiveintopyさんが別にアイデアがあれば少し伺う事は可能ですか?

    キャンセル

  • 2017/12/03 15:16

    gottadiveintopyさん

    >> EffectWidgetは自分の子にしかEffectをかけれないので、ぼかしたい部分を参照するImageウィジットをEffectWidgetの子にしてやればできそうです。

    すいません、できればこの部分などももう少しお聞かせいただきたいので、合わせてコメントお願いできますか?

    キャンセル

  • 2017/12/03 23:11

    > すいません、できればこの部分などももう少しお聞かせいただきたいので、合わせてコメントお願いできますか?

    背景のTextureが取得できるのなら

    部分Texture = 背景のTexture.get_region(...)
    image = Image(texture=部分Texture)
    effectwidget.add_widget(image)

    みたいにできるかと思ったのですが、やりたいことは動画のようなScrollViewの一部にBlurをかけることだったんですね。だったらやっぱりScrollViewをEffectWidgetの子にしてEffectかけてやるのが最適なような気がします。私自身はGLSLを扱った事が無いためあくまで予想ですが。

    > これにはkivyで撮影した際、画面内(ウィンドウ内)のスクリーンショットのみしか取れず、その描画領域全体を撮影することは困難でした。

    撮影がどんな方法かわかりませんが、ScrollViewは自身の大きさで描画を切り抜いてしまうのでScrollViewの子から直接描画結果をもらえば切り抜かれる前の物が得られますよ。やり方はWidgetクラスのexport_to_png()のソースコードが参考になるかと。ただいずれにしてもGLSLを用いたものよりプログラムが複雑になりそうな気がします。

    キャンセル

  • 2017/12/03 23:20

    gottadiveintopyさん

    ありがとうございます。
    今まで色々試してみましたが、EffectWidgetのBlur系を直に使用しようとしたらまったくうまくいきませんでした。
    gottadiveintopyさんの言うようにやはり、GLSLしかないのかなと踏んでます。
    なんとか早めに習得して早めに作っていきます。
    また、コメントを残そうと思います。

    キャンセル

  • 2017/12/03 23:40 編集

    あまり力になれずごめんなさい。
    私の載せたSampleコードですが、Labelの背景を塗ってなかったためにEffectの範囲が文字の部分に限定されて正しいEffectの効果の確認ができていなかったので、修正しました。少しだけiOSのもに近づいたと思います。

    キャンセル

  • 2017/12/04 00:09

    ご協力に感謝します。
    ありがとうございます。

    キャンセル

  • 2017/12/04 00:13 編集

    すいません、ついでに教えていただければ幸いなのですが、
    FBO関数はフレームバッファーを作ることでしたよね。
    例えば他のクラスのウィジェットをフレームバッファとしてもってくることは可能ですか?
    フレームバッファ自体がcanvasのような特性があるならば、あるウィジェットの背景にcanvasとして他クラスのウィジェットをFBOとして持ってこれないかと思っているのですが?

    キャンセル

  • 2017/12/04 10:47

    それが正にexport_to_png()が内部で行っている事なので、ソースコードを読む事をお薦めします。
    短いコードなのですぐに解ると思いますよ :-)

    キャンセル

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

ただいまの回答率

91.36%

関連した質問

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

  • Python

    3863questions

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

  • Python 3.x

    2438questions

    Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。