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

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

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

Jupyter (旧IPython notebook)は、Notebook形式でドキュメント作成し、プログラムの記述・実行、その実行結果を記録するツールです。メモの作成や保存、共有、確認などもブラウザ上で行うことができます。

Python

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

Q&A

解決済

1回答

270閲覧

フラクタル次元を求めるプログラミングコードがどのように動作しているか詳しく知りたい

2xy

総合スコア1

Jupyter

Jupyter (旧IPython notebook)は、Notebook形式でドキュメント作成し、プログラムの記述・実行、その実行結果を記録するツールです。メモの作成や保存、共有、確認などもブラウザ上で行うことができます。

Python

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

0グッド

0クリップ

投稿2023/10/11 13:30

実現したいこと

下に示すプログラミングがどのように動いているのかを知りたいです。
まず、画像を読み込んで、その後からどのような順番で処理をしているのかプログラミング初心者なのであまりよくわかりません。

できれば、この関数がこのような働きをしているというところまで
教えて頂けたら幸いです。

該当のソースコード

#!/usr/bin/env python # -*- coding: utf-8 -*- import sys import math from PIL import Image Image.MAX_IMAGE_PIXELS = 1000000000 def count(img, x, y, b): """ img: 対象画像、x,y: 画像のサイズ、b: ボックスのサイズ """ i = 0 j = 0 c = 0 while i < x and j < y: flag = False for k in range(0, b): for l in range(0, b): if i+k < x and j+l < y: if img.getpixel((i+k,j+l)) == 0: """ ボックスに図形が含まれていたらカウントして次の図形へ """ c += 1 flag = True break if flag: break i += b if i >= x: """ ボックスが右端に達したら左端に戻す """ i = 0 j += b return c # 図形が含まれていたボックスの数を返す img = Image.open('test.png').convert('1') # 画像を読み込んで二値化 x, y = img.size # 画像サイズを取得 i = int(x/10) while i > int(x/1000): n = count(img, x, y, i) print(math.log(i), math.log(n)) i = int(i / 2)

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

Python 3.11.4、jupyternotebookを使用しています。

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

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

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

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

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

guest

回答1

0

ベストアンサー

あまり細かくやるのも大変なので、かいつまんで。

フラクタル次元の計算はボックスカウント法を使っています。詳細がわからなければ、このソースを持ってきたサイトの説明とか、インターネットで調べてみてください。
図形を格子(ボックス)に分割して図形が含まれているボックスの数を数えることでフラクタル次元を算出する方法です。

この関数がこのような働きをしている

この関数というのが count関数だとすると、コメントにあるとおり、「図形が含まれていたボックスの数を返」しています。(関数の動きは後で解説)

フラクタル次元を求めている場所は以下のところですね。

python

1 i = int(x/10) 2while i > int(x/1000): 3 n = count(img, x, y, i) 4 print(math.log(i), math.log(n)) 5 i = int(i / 2)

ボックスのサイズの初期値は画像の横幅の1/10です。
そのときの、図形が入っているボックスの数をcountで算出し、そのときのフラクタル次元を計算するために必要な値を1つ計算して表示しています。
実際の算出は極限が必要なので、ループ毎にボックスのサイズを1/2にして値を算出しています。 横幅な1/1000以下になったらループは終了です。

count関数について。
i, j は それぞれ x, y方向のボックスの左上のインデックス(座標)を示します。

python

1 while i < x and j < y: 2 # (ボックスの中身チェック) 3 i += b 4 if i >= x: 5 """ ボックスが右端に達したら左端に戻す """ 6 i = 0 7 j += b

この構造で、全てのボックスを左から右、上から下に順にチェックしています。

ボックスの中身チェックのところでは、ボックスの中の全てのピクセルを2重ループでチェックしています。
画像は2値化(白黒)しているので、図形があるところは黒です。

python

1 for k in range(0, b): 2 for l in range(0, b): 3 if i+k < x and j+l < y: 4 if img.getpixel((i+k,j+l)) == 0: 5 """ ボックスに図形が含まれていたらカウントして次の図形へ """ 6 c += 1 7 flag = True 8 break 9 if flag: 10 break

あるかどうかのチェックなので、1つでも見付かれば、他のピクセルのチェックは不要なので、 フラグを立てて1重ループからbreakで抜けます。

ざっと書いたらこんな感じですね。


python

1for divisor in [30, 45, 50, 75, 90, 150, 225, 450]: 2 box_size = int(x / divisor) 3 n = count(img, x, y, box_size) 4 print(math.log(box_size), math.log(n))

投稿2023/10/11 14:20

編集2023/11/16 04:54
TakaiY

総合スコア14307

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

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

2xy

2023/11/09 01:21

ご丁寧にありがとうございます。 ただ、2重ループでチェックするところがまだあまり分かってないです。 「あるかどうかのチェックなので、1つでも見付かれば、他のピクセルのチェックは不要なので、 フラグを立てて1重ループからbreakで抜けます。」というところがよく理解できていません。 もう一度教えて頂けますでしょうか。 すみません。
TakaiY

2023/11/09 02:56

そのままなのですが、その説明の上にあるコードの部分で小分けにされたボックスの中のピクセルを2つのループで縦横にチェックしています。 その後は書いているとおりで、チェックしたいのは、そのボックスの中に黒(白?)のピクセルが「あるかどうか」だけなので、1つでもみつかればあることになるので、それ以降のピクセルはチェックする必要がありません。
2xy

2023/11/15 15:11

理解力が無くて申し訳ないのですが、つまり一つのボックスで黒または白のピクセルがあるかどうかをチェックして、あればそれ以降はチェックをしない。その後次のボックスで同じように行う。の繰り返しという認識で合っていますでしょうか? また、前述した内容と異なるのですが、現在のプログラムでは元の画像サイズの1/10からボックスのサイズを小さくしていき1/1000で終了することになっていると思うのですが、縮小サイズを任意の数字にした時の値を算出することは可能でしょうか。 求めたい値は、最初の画像サイズからそれぞれ1/30, 1/45, 1/50, 1/75, 1/90, 1/150, 1/225, 1/450にした8つです。 可能ならばそのプログラムも教えて頂けたら幸いです。
TakaiY

2023/11/16 01:03

> という認識で合っていますでしょうか はい。 合っています。 チェックは `img.getpixel((i+k,j+l)) == 0`としているので、黒を判定していますね。 > 縮小サイズを任意の数字にした時の値を算出すること 求める関数の仕様は、 def count(img, x, y, b): """ img: 対象画像、x,y: 画像のサイズ、b: ボックスのサイズ """ こうなので、bのところにサイズ(ピクセル数)(例えば1/30 にした値)を入れてやればいいのですが、どのあたりがわからないのですか?
2xy

2023/11/16 04:02 編集

えっとbを変えればよいのはわかっているんですが、8回変えて出力するのが面倒なので一気に8つの値を求めることができないかなと思い、質問しました。 追記 元のプログラムの話に戻るのですが、画像を入力したところ、6つの値が出てきました。1/10からボックスのサイズを1/2にするということは、最初の横幅から 1/10、1/20、1/40、1/80、1/160、1/320、1/640、1/1000(1/1280)までの8つの値が出てくると思うのですが、どこが間違っているでしょうか...
TakaiY

2023/11/16 02:32

30, 45, 50, 75, 90, 150, 225, 450 をリストに入れてfor文に入れて回し、中で b の値を計算して 関数を呼べばいいでしょう。
2xy

2023/11/16 04:17

ちなみに、そのプログラムコードもできれば教えてほしいです…
TakaiY

2023/11/16 04:55

pythonの基本的な動作のコードなので、ご自分で書けるようになっておいたほうがいいと思いますよ。
2xy

2023/12/02 14:07 編集

ご丁寧にありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.31%

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

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

質問する

関連した質問