ゼロから作るディープラーニング

ディープラーニングで画像分類やってるグループが近くにいます。今まで人間がやってた作業をコンピュータに置き換えようという試みです。ディープラーニングって、いわゆる官能評価に適用するのがまずはとっつきやすいみたいです。 人間の認知システムを模しただけあって、なかなかの精度で分類されます。ただし間違うことも当然あります。間違った時はどうするかというと、モデルを作り直します。モデルを作り直すというのはどういうことかと言うと、間違った画像を使って学習を重ねるのです。ここのところが今までと違っていて、間違った画像が何故間違えたのか検証しない、というかすることができない、というか、できないわけではないけど現実的ではありません。そうなると、y=f(x)のfの部分がもう完全にブラックボックスみたいなものなのですね。
ワタクシこのブラックボックスになかなか慣れることができなくて、どうもイマイチ、ディープラーニングとか機械学習とか、好きになれない自分がいるのです。モデルをいじってるのにモデルの中身が分からないってどういうことよ、と思うわけです。
ディープラーニングをツールとして使う分には、そういうものだと割り切ればいいのですが、それもなんだかシャクですね。ならばせめて、ディープラーニング自体の仕組みくらいはしっかり理解しておこうではないか。ブラックボックスなのはしょうがないとしても、ブラックボックスである理由は押さえておきたいではないか。

というわけで、『ゼロから作るDeep Learning Pythonで学ぶディープラーニングの理論と実装』はかなり良い本でした。「ゼロから作る」というのが良いですね。「理論を勉強して実装してみる」という流れで言うと、理論を勉強する機会は無いこともないのですが、いざ実装するのはなかなかハードル高いものです。ワタシのようにpython初心者とかなるとなおさらです。この本は、その実装の部分もかなり丁寧に解説してくれています。なので実装のところでつまずきにくく、まさに経験しながら理解を深めることができますね。なんでもそうですが、自らの経験に勝る近道はないと思います。
また、内容はディープラーニングですが、流行を追いかけるというより基礎をしっかり学ばせてくれるので、ディープラーニングに関係することでもしないことでも、さまざまな気付きを得ることが出来ました。
とはいえ、ゆっくりだった割には、結構コード書くの端折りながらサボりながら読んでしまったので、実装の部分はもうちょっと頑張ってみようかなと思います。
このシリーズはあと2冊刊行されてるのですね。自然言語処理フレームワークの実装ですって。これまた興味をそそられますね。いつか読みたいですねえ。

たかだかライブラリ欲しかっただけなのにネット情報のありがたみを再認識する

とあるライブラリを使いたくて、conda installしようとしたらプロキシ認証の壁に阻まれ、set HTTPS_PROXY=...やってもダメだ、どうやっても認証をかわせない、何故だ、と思ってたらとある橋渡しツールがあると知り、これで一安心と思ったらやっぱりダメで、どうやらanacondaは自分のフォルダにプロキシとか設定するファイル(.condarc)を置いとかないとダメらしい(なんじゃそれ)と言うことを知り、なんとかどうにかやっとこさ所望のライブラリをcondaするに至る。もうね、ハッキリ言いまして、ちょっといろんな仕様が冗長じゃない?
こっちは認証して欲しいだけなんだけど?
だいたい、そんな設定わざわざ持っとく必要ある??

となんだか無駄にストレスたまった気分。まさかこんなに時間をかけることになろうとは…。最初からドキュメント当たるべきだったのか…。(そりゃそうだ)

ネットの集合知というものは素晴らしいですね。「絶対何か方法あるはずなんだけど、どうすれば良いかサッパリわからん!」のときに、最短でただしいアンサーをゲットできる確率高いと思います。…ああ、それは悩み自体が大したことないからか。
QiitaにもはてなブログにもZennにも、大いにたすけていだきました。願わくば、この先何十年も残っていて欲しいものです。でないと次回同じところでハマったらもう進めない自信があります。

ディープラーニングの本

プログラミングって、一つか二つ言語を知ってれば、新しい言語でも、文法だけなら何となく理解して書けちゃうものだと思います。なんて言うとプロの方に怒られそうですが、ワタシはもうアマチュアの中のアマチュアですので、コードというものはエラーさえ出さなければカタチはどうでも良いと思って書いています。

そんななので、python言語も特に書籍を買うことなくなんとなく書いてました。インターネットの世界にはいくらでも参照できるコードがあります。pythonなんて超有名な言語なら尚更です。なんとなく検索して、なんとなく「お!」となるサンプルコードを見つけて、コピペ&中身をちょいと弄る、というパターンで遊んできました。
しかし、体系的に学べないので真の理解には程遠いのでしょう。応用が効かないというか、そのものズバリなサンプルコードがないとやりたいことになかなか手が届かないのです。これは良くない。ワタシもいつか自分オリジナルなソフト作成したいのに…。やはり、ここらで基本を学び直すべきか。体系的に学ぶためには、pythonの書籍を購入すべきか。
と、思ったのが書籍探しはじめた発端。

20年近く昔ですが、結城浩さんの本でCとJavaを学んだことがあるので、pythonの本も出されてないかなあと思いましたがありませんでした。残念。
となれば、初心者向けではなくても良いかなと思いました。
順番に読み進めることはなくても、末長く使えそうなクイックリファレンス的なものでも買おうかなと思っていました。
しかし、せっかくなら新しいことを学びたいと少し色気が出まして、購入したのはなんと『ゼロから作るディープラーニング』です。

ネット上の評判は滅茶苦茶良いです。内容も、「ワタシのために書かれたのでは?」と思わせるものでした。
ポイントは、pythonを使っているのはもちろんですが、やはり“ゼロから作る”という点です。ワタシまだ最後まで読み切ってないので偉そうには言えませんが、importしているライブラリはnumpyとmatplotlibくらいです。それで少しずつ丁寧に説明しながらディープラーニングを実装しようという、なかなかスパルタな内容です。今ドキ、ディープラーニングフレームワークなんて小慣れたものがいくらでもありますが、そこをわざわざ基本のキから学ぼうという心意気が素晴らしいと思います。
ちなみにワタクシ、シグモイド関数ニューラルネットの多層化が出てきたところ(めっちゃ序盤です)で懐かしさのあまり泣きそうになりました。「大学の人工知能の講義で習ったやつやわー」て思いました。あのときは人工知能なんて下火で、名前だけはカッコよくてもあんまり人気なかったですよね。隔世の感です。

最近の本ではないですが、内容は決して流行りを追いかけるものではないので、しっかり理解したいところです。pythonの勉強にもなるし、ディープラーニングの勉強にもなるし。

あとこれ、続刊が2冊もあります。どちらもとても面白そうです。いつになるかわかりませんが、読みたいですね。

雑記 PC編

最近思ってることなどを徒然なるままに。PC編。

POV-Rayが面白い

POV-Rayとは何かというと、レイトレーシングエンジンです。レイトレースとは何かというと、その名の通り「視線(レイ)追跡(トレース)」のことです。仮想空間に定義した物体をディスプレイに投影するために、実際の視線(レイ)を追跡(トレース)するレンダリングの手法です。
ワタシが学生の頃からあって今も使えるから、根強い人気なのかな。ただ、検索してでてくるページって、一昔前に作られた物が多い。今ドキはこういうの流行らないのかな。CGやっても金にならない、って昔は言われてたけど、今も同じなのかしら。よくなってたら良いな。
POV-Rayは結構楽しんでいるので、このブログにも残していきたいなと思っています。

Blender使っていない

Blenderとは何かというと、3DCGのモデリングソフトです。POV-Rayと同じタイミングでインストールしましたが、その後一回も立ち上げていません。検索した感じだと、POV-Rayよりはまだメジャーなのかな。
3Dのモデリングって、やればやるほど終わりが見えなくなって、いくらでも時間が吸い込まれていきます。昔は時間あったんだなあ、と思います。こんなこと言うと年寄りみたいでイヤすが。 まだ諦めていないので、そのうちやりたい。

プログラミングは面白い

pythonでもやってみるか、と思ってジワリジワリですが勉強してきました。あと、すごくたまにですが、Cでも遊んでいます。ネットのサンプルコードを弄ってる程度ですが。正直、Cの方がちょっと好きかも、と思います。特にかっこいいコトをやっているワケではなくて、単純に昔を懐かしんでいるだけです。思い出補正というやつかな。
pythonについてはチマチマですが勉強しているし、(勘違いかもしれませんが)なんとなくどんな言語かわかってきた気もするので、せっかくだから機械学習方面に進みたいなと思いました。
pythonといえばこれだよね」みたいなコトもやっておきたいなあ、と。

iPhoneアプリが欲しい

3DCGツールってスマホアプリではあんまりないですよね。3DCGのモデリングしたい、とかレンダリングしたい、とかなるとスマホではほぼ出来ないのかな。まあ確かに、入力の相性悪そう。ただ、効率悪くても面白かったら一定流行るんでは、と思うが…全体のパイが少ないんでしょうかね。
プログラミングのツールはいくつかありそうだから試してみようかなと思っています。なんでも良いからスマホで何か新しいことやりたいなという思いです。

ラズパイもできていない

これはもう、検索したらいくらでもでてきます。みなさん凄い!しびれる!!憧れる!!!
脳内プロジェクトはいくらでも立ち上がりますよね。頭の中にあることを、どのタイミングで何を指標に実行に移すか、というのはその人の特性をよく表すと思います。脳内プロジェクトで満足しているようではダメだ!
カタチを残してこそ価値が生まれるのです。諦めないぞ。

pythonでpngファイル入出力

はじめに

一人でチマチマやってると、どこまでも深掘りしたくなりますね。次のステップへも行きたいので、ここらでまとめておきます。

必要なpython 環境は、最低限でよいです。
今回のワタシの環境は以下記事のようなものです。

macに入っているソフト、pythonのPackageリストをメモっとく - 放心ラボラトリ

どういったものをつくるか

ざっくりとは以下のような感じ。

  1. 指定したpngファイルを開く
  2. ヘッダの諸情報をゲット
  3. イメージ情報をゲット
  4. イメージ情報を渡して新たなpngファイルを出力
  5. 上記をclassとして実装する
  6. OpenCVやPILは使わない

今回作成したソースは、本記事の後ろの方に載せています。
特記事項的なものを先に書いておきます。

pngファイルのフォーマット

次のような構造になっています。

名前 長さ 備考
signature 8byte 必ず最初に現れる
IHDR 25byte 必ずsignatureの次に現れる
PLE --byte なくても良い
IDAT **byte 複数OK
... ... ...
IEND 4byte 必ず最後に現れる

大事な事をメモします。

  • 最初はかならずsignature:8byte
  • signatureの次は必ずIHDRチャンク:25byte
    ここに色んな情報が入ってる
  • イメージデータはIDATチャンクに入ってる
    IDATは複数持てる。すなわち分割できるという事
  • ファイルの終わりは必ずIENDチャンク:4byte
  • 任意でその他様々なチャンクを持てる
    本記事ではそれらは無視します
    必要に応じてWEB検索

IHDRの構造

以下のようになっています。大事な情報なので全部読み出しておきます。

内容 長さ 備考
データ長 4byte 常に13
チャンクタイプ 4byte 常に'IHDR'が格納されている
画像幅 4byte
画像高さ 4byte
bit深度 1byte
カラータイプ 1byte
圧縮メソッド 1byte
フィルターメソッド 1byte
インタレースメソッド 1byte
crc 4byte チャンクタイプとデータから計算

各チャンクの構造

以下のようになっています。先に書いたIHDRも同じです。

名前 長さ 備考
データ長 2byte データ長を格納
チャンク名 4byte 『IHDR』とか『IDAT』など
データ --byte チャンクのデータ
crc 4byte 謝り検知用

チャンク名が出てくるまで順番に読んでいって、チャンク名がヒットしたら戻ってデータ長を確認、そのデータ長分データを読む、でいけそうです。crcはファイルに書き込むときは計算しないといけませんが、本日は標準ライブラリを使います。

import zlib
crc32 = zlib.crc32(data)

これでdataに対するcrcを得ることができます。

個別のメモ

1.指定したpngファイルを開く

open('filename','rb')で開いてread()していきます。signatureの2〜4byte目に必ず『png』があるので、これを目印にしてpngか否か判断します。

2.ファイルヘッダの諸情報をゲット
struct.unpack_from(">33s", bytedata, offset)

を使います。バイトデータの任意の場所から任意の長さを、任意の型で取り出すことができます。
逆にバイトデータにして書き込むときは

struct.pack(">I",data)

を使います。 バイトリテラルについて詳細やりだすとそれだけで長くなりそうなので別の機会にしますが、今回のような低レベル処理をしたい時には滅茶苦茶便利だと思います。

3.イメージ情報をゲット

'IDAT'を探しながらstruct.unpack_from()で読み出していきます。読み出すたびにどんどん連結させていきます。最終的にはひとつの大きなIDATが出来ます。今後のため、一つになったIDATをgetするメソッドも実装しておきます。

4. イメージ情報を渡して新たなpngファイルを出力

これは、読み出したものをそのまま書き込めばよいです。ただし必須チャンクであるIHDR,IDAT,IENDしか書き込みません。そしてIDATは一つしか持たせません。元ファイルによりますが、多少は容量軽くなります。

まずは結果

以下のようなpng.pyというファイルを作成します。

import struct
import zlib

class png_img:
    def __init__(self,inputfile):
        self.f = open(inputfile,'rb')
        self.imgdata = self.f.read()
        #書き込み用にsignatureとIHDRを読み出しておく
        self.head = struct.unpack_from(">33s", self.imgdata, 0)
        #PNG画像か否か判断。PNG画像であれば各種データ読み出し。
        if struct.unpack_from(">3s", self.imgdata, 1) == (b'PNG',):
            self.i_width = struct.unpack_from(">I", self.imgdata, 16)
            self.i_height = struct.unpack_from(">I", self.imgdata, 20)
            self.bit_depth = struct.unpack_from(">B", self.imgdata, 24)
            self.color_type = struct.unpack_from(">B", self.imgdata, 25)
            self.comp_method = struct.unpack_from(">B", self.imgdata, 26)
            self.filter_method = struct.unpack_from(">B", self.imgdata, 27)
            self.interlace_method = struct.unpack_from(">B", self.imgdata, 28)
            self.crc = struct.unpack_from(">B", self.imgdata, 29)
            #IDATの読み出し。複数ある場合全て連結する。はIENDが現れるまで繰り返す
            self.count = 30
            self.idata_type = struct.unpack_from(">4s", self.imgdata, self.count)
            self.img_length = 0 #IDATの合計データ長
            self.img_data = b'' #IDATのデータ部が入る
            self.cnt = 0        #IDATチャンクの数を数える
            while self.idata_type != (b'IEND',):
                self.idata_type = struct.unpack_from(">4s", self.imgdata, self.count)
                if self.idata_type == (b'IDAT',):
                    self.idata_length = struct.unpack_from(">I",self.imgdata,self.count-4)
                    self.img_length += self.idata_length[0]
                    self.img_subdata = struct.unpack_from(">"+str(self.idata_length[0])+"s",self.imgdata,self.count+4)
                    self.img_data += self.img_subdata[0]
                    self.cnt += 1
                self.count += 1
            print('read OK','This Image is',self.count,'byte')
        else:
            print('This file is not PNG image')
        self.f.close()
    def outputPNG(self,outputfile):
        self.ff=open(outputfile,'wb')
        self.ff.write(struct.pack(">33s",self.head[0]))
        self.ff.write(struct.pack(">I",self.img_length))
        self.ff.write(struct.pack(">4s",b'IDAT'))
        self.ff.write(struct.pack(">"+str(self.img_length)+"s",self.img_data))
        self.ff.write(struct.pack(">I",zlib.crc32(b'IDAT' + self.img_data)))
        self.ff.write(struct.pack(">I",0))
        self.ff.write(struct.pack(">4s",b'IEND'))
        self.ff.write(struct.pack(">I",zlib.crc32(b'IEND')))
        self.ff.close()
    def printDATA(self):
        print('bit_depth =',self.bit_depth[0],'color_type =',self.color_type[0],
            'comp_method =',self.comp_method[0],'filter_method =',self.filter_method[0],
            'interlace_method =',self.interlace_method[0],'crc =',self.crc[0])
        print('width =',self.i_width[0],', height =',self.i_height[0])
        print('image data length =',self.img_length,' byte','IDAT THUNK cnt =',self.cnt)
    def getIDAT(self):
        return self.img_data
    def searchTNK(self,thunk):
        self.dmy1 = 0
        self.dmy2 = 0
        self.thunk_type = (b'',)
        while self.thunk_type != (b'IEND',):
            self.thunk_type = struct.unpack_from(">4s", self.imgdata, self.dmy1)
            if self.thunk_type == (thunk,):
                self.thunk_length = struct.unpack_from(">I",self.imgdata,self.dmy1-4)
                self.thunk_value = struct.unpack_from(">B",self.imgdata,self.dmy1+4)
                print(self.thunk_type[0],'length=',self.thunk_length[0],'value=',self.thunk_value[0])
                self.dmy2 += 1
            self.dmy1 += 1
        if self.dmy2 == 0:
            print('no thunk',thunk)

指定したチャンクがあるか探して、あれば表示もしてくれるsearchTNKメソッドも実装してみました。 同階層に以下内容のファイル作成します。元ファイル『lenna.png』も準備しておきます。

import png

inputfile='/Users/home/ip/lenna.png'
outputfile='/Users/home/ip/out.png'
p=png.png_img(inputfile)
p.printDATA()
p.outputPNG(outputfile)
p.searchTNK(b'sRGB')
p.searchTNK(b'PLTE')

実行結果は、terminalに以下のような表示がなされます。同階層にout.pngも生成されます。

read OK This Image is 521897 byte
bit_depth = 8 color_type = 6 comp_method = 0 filter_method = 0 interlace_method = 0 crc = 244
width = 512 , height = 512
image data length = 521078  byte IDAT THUNK cnt = 64
b'sRGB' length= 1 value= 0
no thunk b'PLTE'

なんとワタシのlennaさん、IDATチャンクが64もありました。

結び

pngファイルを読み込んで書き込むだけのものを作りました。やっていることはただの劣化コピーですね。OpenCVとかPILなどを使えば、劣化することなく数行で終えることができるでしょう。
しかし、今回ここに辿り着くまでに、

  • pngフォーマットの構成
  • pythonでのバイナリデータの扱い方

など、得られた知識は多くありました。

今後

pngファイル入出力関係は一旦一区切りです。ただ、crcのこととかbyteリテラルのこととかはまとめておきたいと思います。

さて、せっかくここまで作ったので、この流れで画像処理の基礎もやって見ようと思います。昨今流行りのDeepLearningの基礎の基礎の基礎くらいの内容です。

その前に得られたIDATの圧縮を解かねばなりませんね。ゆっくりやっていこうかと。

参考にさせていただいたサイト

こういったことをやりたい人は一定数いるのかなあ、という印象です。ワタシの記事よりわかりやすく正確なものがいっぱい。

PNGイメージのデータ構造を知ってみる(1) | エンジニアもどきの技術メモ
PNG イメージを自力でパースしてみる ~5/6 PNGフォーマット編~ - 自由研究ノート(仮)
pythonでバイナリデータを読む(PNGを例として) - Qiita

本サイト内関連記事

ダラダラのんびりやってきた記録。

pythonでPNGファイルを開いてみる - 放心ラボラトリ
pythonでpngファイルを開いてみる2 - 放心ラボラトリ
pythonでpngファイルを開いてみる3 - 放心ラボラトリ
pythonでpngファイルを開いてみる3.5 - 放心ラボラトリ

趣味プログラミングの楽しみ方

趣味でプログラミング

プログラミングですか?そうですね。嫌いじゃないですよ。どっちかっていうと好きな方です。でも『趣味です』と言えるほどお金も時間もかけてないですよ。
と思っていましたが、冷静に考えてみると、PC触ってる時間の7割くらいはプログラミングで遊んでいる気がするし、そのPCはソコソコの値段のノートPCです。そもそもワタクシ、そんなに出費が多い方ではないし、全くもって多趣味でもありません。というかすごく少ない方だと思います。
ワタシという人間の、周辺機器含むあらゆるリソースのうち1割くらいは、プログラミングに割いているような気がしてきました。これはもう胸を張って趣味と言って良いのではないだろうか。

とはいえ現状、腰を据えて体系的に学ぼうという気はなく、いろんなWEBサイトを見ながら適当に書いては実行しているわけです。なんとなく思いついた事を調べながら試しているだけです。
知識はついてきている気はしていますが、あんまりレベルは上がっていないと思います。

趣味プログラミングの腕前

そんなワタシですが今は専らpythonで遊んでいます。
日々pythonさわってて、どんなエラーを出しているかといえば、

  • )の数がたりないよ』
  • :がないんじゃないかな』
  • 『型があってないからも一回確認しな』
  • 『そんなオブジェクトないけど、importちゃんとしてる?』
  • forってそういう使い方じゃないんだけど…』

などなど。まあ懲りずに何回も何回もくだらん間違いを繰り返すわけです。その度に、自分が書いたロクでもないコードみて、たまにprintなんちゃらとか書きながら直していきます。いわゆるprintデバッグです。『いい加減学べよ。何回目だよ』と自分に言い聞かせながら、)を追加したり:を追加したり。ワタシはこんなくだらん事でこんなに長い時間悩んでいたのか、クソッ、バカバカしい。とか思いながら直しては実行して、またエラー出して…、の繰り返し。根気はある方ですがそれにしても酷い。この時間であの本を読んだりあの映画を見たりしたほうが良いのではないだろうか。全く、一人PCに向かってチマチマとコードの修正をするなんて、もう本当に、嫌気がさすくらい楽しすぎる

われながら結構マゾいと思います。

一人で楽しめるって良いよね

何でしょうか、この感覚。
ナンクロで悩んでいる感じ?
2000ピースくらいのジグソーパズルに悩んでいる感じ?
足りないところを探して埋めていって正解に近づいていく感覚がたまりません。
しかもプログラミングやってると、

  • モノづくりやってるような感覚
  • スキルが身に付いていくような感覚

そういったものの片鱗も得ることができて、なかなかいい趣味だなあと思っています。
ナイス前向き!ナイス自画自賛

pythonでpngファイルを開いてみる3.5

手探りpython

まずは前回の記事へのリンク。

pythonでpngファイルを開いてみる3 - 放心ラボラトリ

前回、こんなコードを書いています。

self.i_width = int(self.f.read(4).hex(),16)

なんというか、()が多いのがまずイマイチ。そして、わざわざ16進数に直してから整数型で返しているし…。なにをやりたいんだ?
と言われてもしょうがないですね。で相変わらずネットポチポチしてたら見つけましたよ。

import struct
・・・
self.f = open(fname,'rb')
imgdata = self.f.read()
width = struct.unpack_from(">I", imdata, 16)

byte型を所定の型に変換(unpack)して返してくれるらしい。マニュアルに載ってた。

struct.unpack_from(fmt, buffer[, offset=0])
buffer を与えられたフォーマットでアンパックします。 値が一つしかない場合を含め、結果はタプルで返されます。 buffer には最低でも format に要求されるサイズのデータが必要です。 (len(buffer[offset:]) は calcsize(fmt) 以上で無ければなりません)。

ですよねー。そりゃあ、それくらいありますよねー。まさにCの型に変換するのを目的としているらしいですよ。 第一引数が型指定のようです。 今回使ったやつだけメモしとこう。

引数で指定 Cの型
I unsigned int
i int
s char
B unsigned char
b char

python勉強してて思うこと

byteとかbinaryで読み出して他の型(整数型とか)に直したい時なんて、当然のようにあるから、標準ライブラリには当然のように実装されているだろうとは思ってました。そして実際に標準ライブラリに実装されていました。
だだ、よく考えるまでもなく、pythonって型宣言しなくても良いんですよね。勝手に解釈してくれるから。で、世間に出回ってるライブラリが超豊富だから、大体のことはサンプルコードコピペで出来ちゃう。
ということは、初めての言語がpythonで、独学で学ぼうとする場合、変数の型なんて意識せずに結構なアプリ開発ができるようになるのかな。なるんでしょうね。 pythonは、VMの機能が強烈なのか、各種ライブラリがそこまでフォローしているのか…。まあ、何でもかんでもオブジェクトにしてやってこう、という考え方とたいへんマッチしていると思いました。とにかく、コードを書く人がPC側の都合に左右されないように、という考え方のもと設計されているということですね。むしろその先がプログラマの方々のウデの見せ所になるのか。

なんとなくコードを載せておこう

上記を反映させて、以下のようなソースとしてみました。我がPCにお住まいのlennaさん、サブチャンクないと思っていたら、sRGBというのが入ってました。あと、結局、見難さは変わっていないというね。

import struct

class png_img:
    def __init__(self,fname):
        self.f = open(fname,'rb')
        self.imgdata = self.f.read()
        self.signature = struct.unpack_from(">8B", self.imgdata, 0)
        self.slength = struct.unpack_from(">I", self.imgdata, 8)
        self.c_type = struct.unpack_from(">4s", self.imgdata, 12)
        self.i_width = struct.unpack_from(">I", self.imgdata, 16)
        self.i_height = struct.unpack_from(">I", self.imgdata, 20)
        self.bit_depth = struct.unpack_from(">B", self.imgdata, 24)
        self.color_type = struct.unpack_from(">B", self.imgdata, 25)
        self.comp_method = struct.unpack_from(">B", self.imgdata, 26)
        self.filter_method = struct.unpack_from(">B", self.imgdata, 27)
        self.interlace_method = struct.unpack_from(">B", self.imgdata, 28)
        self.crc = struct.unpack_from(">B", self.imgdata, 29)
        self.cslength = struct.unpack_from(">I", self.imgdata, 33)
        self.cs_type = struct.unpack_from(">4s", self.imgdata, 37)
        self.cs_val = struct.unpack_from(">B", self.imgdata, 41)
        self.cs_crc = struct.unpack_from(">B", self.imgdata, 42)
        self.idat_length = struct.unpack_from(">I", self.imgdata, 46)
        self.idat_type = struct.unpack_from(">4s", self.imgdata, 50)
        self.f.close()
    def getsLength(self):
        return self.slength
    def getSignature(self):
        return self.signature
    def getWidth(self):
        return self.i_width
    def getHeight(self):
        return self.i_height
    def printsignature(self):
        print(self.signature)
    def printIHDR(self):
        print(self.slength,self.c_type,self.i_width,self.i_height,
        self.bit_depth,self.color_type,self.comp_method,
        self.filter_method,self.interlace_method,self.crc)
    def printsRGB(self):
        print(self.cslength,self.cs_type,self.cs_val,self.cs_crc)
    def printIDAT(self):
        print(self.idat_length,self.idat_type)

name='フルパス/lenna.png'
png=png_img(name)
png.printsignature()
png.printIHDR()
png.printsRGB()
png.printIDAT()

で、今IDATチャンクを読み出していってるんだけど、いっぱいあるんですよね。複数あっても結合するように書かないといけないんだな。面倒だな。Cだったらすぐできそうだけど(強がりです)、pythonだとどうすれば良いのかな。勉強だな。