PyQt で画像のビューアを作る 9 version 10

2019/07/08 11:06 by yamasyuh68
  :追加された部分   :削除された部分
(差分が大きい場合、文字単位では表示しません)
PyQt で画像のビューアを作る 9
- スト内包 使えるかな
画像に変換けるとき
- 190705 金曜夜
やりたいことほぼできた
UIも変えてヒストグラム示二つを入れこんで見れるようにした
- 190706 土曜
変換後のヒストグラム表示の動作がおかしい、直そうとしてけどうまく行かな
- 190707 日曜
保存ルーチン、仕組み書き直し、ちょっと時間かかったどまあまあいけて実用出来るようになった、以前の自作物よりは遙かに良いっす

```
        data = im.getdata()
        data2=[]
        width, height = im.size
        for l in range( width * height ):
            r,g,b = data[l]
            r = self.LUT[r][1]  
            g = self.LUT[g][1]  
            b = self.LUT[b][1]  
            data2.append((r,g,b))   #  <======== tupple!!!!!!
        im2.putdata(data2)

# ベジェカーブ改善
- LUTの欠落改善
結構悩んだ末に書いたコードは極めてシンプルになった
まあそういうものなんだろなあ
xとインデクスは等しいからやめてyだけにもしたのでいっそうシンプル
一般的なベジェカーブの関数化ってことではないが、0-256の整数データを作るという意味ではかなり正確に出来てると思う
- 欠落したx値については、前後のt値をさらに分割して行けばいずれ見つかると思うけど、そうやって計算したy値といまのや

        data = im.getdata()
        data2=[( LUT(i[0]) , LUT(i[1]) , LUT(i[2]) )  for i in data ]
        # data2=[( i[0] , LUT(i[1]) , LUT(i[2]) )  for i in data ] # rだけそのままのパタ
        im2.putdata(data2)
```
- **チャンネルの選択も簡単書ける!!!**
り方のy値は、ずれても1だと思う
- x値が飛ぶって事は、傾きが0に近いって事だから、y値は前後と変わらない可能性が高い
コードは前後の平均を取って四捨五入したど、前か後ろか、どっちかの値をもまま適用しても良かったと思う
- Y軸反転できた
描画系座標はそのままにしておいて、テブルを作るときに反転させることにした
反転するから基本は絶対値が変わる、この辺りは未だに直感的な理解は難しいな
- 画素変換はチャンネル毎にしてみた、良いわ
- そ他
右ドラッグでベジェの二つの端点を同時移動すようにした、結構良いカーブのリセット機能をつけた
ベジェの計算をマウスリリース時では無くムーヴ時に変えた
負担は大きくなったがそこそこ動いてる( ´∀`)


- Y軸反転の実験
・最初のポインを右上がりになるように設定する
widgetの大きさによるが、
(0,0)-> (255,255) は、 
(0 ,270 )->( 255,15) る、・yジ 0~255 は、270~15 に反転す描画はこまで良が、画像の変換テーブル反転戻す
各値を -(a-270) れば良い
> newList = [ -( i-270) for i in list]
# ヒスグラム表示
- pillowimage.histogram() で簡単にイけた
RGB毎に256個が一列で単純ので表示するときに三色に切りければいい
- ドットで描画したが見づらいでライを引くことにしてみた
ドット繋がらない当然かもしれないけど、棒グラフだと塗りつぶされから折れ線しかないかな
- しかし、**変換後の表示はこれだとうかない**
変換前の画像ならドットYは飛ぶがx値は連続している
変換そもそもx値が不連続になるのでライン引いてしまうと山にならずに大きなギザギザになってしまう
この部分もLUTと同じで座標変換が必要で、まだ頭がついて行けてなくて対応できてない┐('д')┌
- ヒストグラムの変換(レベル補正)はまだ、見れるだけでもごく良い

# リスト内包表記
- 今回のプログラムはこれのおかげでかなり進んだ
LUTの作成はこれをフルに活用している
for で実装すれば良いんだけど一行で書けてしまうし、最初は可読性が低いと思ったけど慣れたらそうでもない
まあ慣れなきゃイケないんだが
- **画像のピクセル変換は全てこれで書けると思う**
調べた限りでは**普通のforよりも速いらしい**
これは使うべき技術ですよね、もっと勉強したいっす
改めて**pythonに感動した**、python固有ってことでもなさそうだけど

- マウス操作改善
①フラグはキープレスで立てる
②端点の■は常時表示してマウスムーブは無視
③マウストラッキングもはずす
④右クリックで両端点の同時ドラッグとする
- ベジェカーブのリセット機能(シフトキーとか)
- ベジェの描画をやめてLUTの描画だけにしたらどうかな?少し軽くないか?
- マスクをかけれないので改善(わかりづらいので書き直した方が良いような気がする)
- LUT改善
第一段階
 重複のxはパスして欠落したLUTを作る(256はないことになる)
第二段階
 x値をインデクスとしたy値だけのリストをLUTを元に新たに作る
 その際に欠落したxは前後のインデクスの平均で補完して、完全に256個のリストにする
 欠落が複数連続していても一律で平均値補間とする(傾斜はつけない)
欠落した数が多いほど信頼性は低いが、前後のy値が同じなら問題ない
前後のY値の幅が大きいときは誤差が大きいことになる
でも平均値で補完しておけばほぼ誤差はないと思う

```
temp=[]
self.LUT=[] #グローバルにしよう
# ToDo
- トーンカーブでRGB以外にも対応する
- ベジェの描画をドットにしてみる(どっちが軽いかな?)
考えたら描画してるんだから**Qtは(x,y)を知ってる**んだろうな
関数として提供してくれたらいいのに
- ヒストグラム表示を正確に
- ヒストグラム変換実装(レベル補正)
- **pillow の部分を Qt で書く**
データを直接いじるようになったので、pillowを使うメリットが薄れているような???
Qimage だとデータのポインタを取得できるので直接いじれそう
- **色調補正を書きたい**
ホワイトポイント系の処理、ロジックがわかれば書けそうなんだけど
- もろもろ
scipy 補間読んでもう一回やってみよう
→ https://qiita.com/maskot1977/items/2a55c087974d0ac5e843
PyQtGraph、いつか試してみるか?
→ http://www.pyqtgraph.org/
QImage bit 直接データをいじれる
→ https://qiita.com/kanryu/items/89812b362dfd581a4c10

        #  first step -----------------
        for l in range(256):
            t=l*tt
            x = (1-t)**3*p1[0] + 3*(1-t)**2*t*p2[0] + 3*(1-t)*t**2*p3[0] + t**3*p4[0]
            if round(x)==last_x:
                continue
            y = (1-t)**3*p1[1] + 3*(1-t)**2*t*p2[1] + 3*(1-t)*t**2*p3[1] + t**3*p4[1]
            last_x=round(x)
            temp.append([ last_x , round(y)])
        #  second step -----------------
        ii=0 # index of temp ( made by first step )
        self.LUT.clear()
        for i in range(256) :
            if l[ii][0] == i :
                self.LUT.append( temp[ii][1] ) # set y-value
                ii += 1
            else: 
                self.LUT.append( round((temp[ii][1] + temp[ii-1][1])/2) ) # set y-value
        print( len(self.LUT) , self.LUT )
```

---


- トーンカーブをチャンネルごとに適用する
①全て②rのみ③gのみ④bのみ⑤rg⑥rb⑦gb
以上7種類、ルーチンを7種類作った方が速いと思う
とりあえずは独立したラジオを三つ作って分岐させるのが簡単か?
- 画像種類毎に
RGB
CMYK
YCbCr (Y:輝度、Cb:青の色差、Cr:赤の色差)  これやってみたい
HSV

```
im = Image.open(sys.argv[1])
im = im.convert("YCbCr")
yy, cb, cr = im.split()
yy = ImageOps.equalize(yy);
im = Image.merge("YCbCr", (yy, cb, cr))
im = im.convert("RGB")
im.show()

```



- ヒストグラム表示してみる
https://qiita.com/pashango2/items/145d858eff3c505c100a
pillow
his=img.histgram()
print(his)
とりあえずコンソールでプリントしてみよう

- 各バンドを連続して返すため、RGBモードの場合は256 x 3=768個の要素を返します。
最初に最大値設定するか??
平均値を求めてその2倍まで表示、2倍以上の値は2倍に書き換える
最大値も求めておく必要?
h = mean(his) # 平均
m = max(his)  # 最大

```
his=img.histgram()
painter.setPen( Qt.red )
for i in range(255):
 painter.drawPoint( QPointf( i , his[i] ) 
painter.setPen( Qt.green )
for i in range(256,511) 
 painter.drawPoint( QPointf( i-256 , his[i] ) 
painter.setPen( Qt.blue )
for i in range(512,767) 
 painter.drawPoint( QPointf( i-512 , his[i] ) 

```

- ヒストグラム平坦化してみる
- ホワイトバランス出来ないかな??




- scipy 補間ここを読んでもう一回やってみよう
https://qiita.com/maskot1977/items/2a55c087974d0ac5e843








PyQtGraph
いつか試してみるか?
http://www.pyqtgraph.org/









----
→ [目次に戻る](https://mimemo.io/m/QORbW4qkvOoda0N)



      
  • 190705 金曜夜
    やりたいことほぼできた
    UIも変えてヒストグラム表示二つを入れこんで見れるようにした
  • 190706 土曜
    変換後のヒストグラム表示の動作がおかしい、直そうとしてるけどうまく行かない
  • 190707 日曜
    保存ルーチン、仕組みを書き直し、ちょっと時間かかったけどまあまあいけてる
    実用出来るようになった、以前の自作物よりは遙かに良いっす

ベジェカーブ改善

  • LUTの欠落改善
    結構悩んだ末に書いたコードは極めてシンプルになった
    まあそういうものなんだろなあ
    xとインデクスは等しいからやめてyだけにもしたのでいっそうシンプル
    一般的なベジェカーブの関数化ってことではないが、0-256の整数データを作るという意味ではかなり正確に出来てると思う
  • 欠落したx値については、前後のt値をさらに分割して行けばいずれ見つかると思うけど、そうやって計算したy値といまのや

り方のy値は、ずれても1だと思う

  • x値が飛ぶって事は、傾きが0に近いって事だから、y値は前後と変わらない可能性が高い
    コードは前後の平均を取って四捨五入したけど、前か後ろか、どっちかの値をそもまま適用しても良かったと思う
  • Y軸反転できた
    描画系の座標はそのままにしておいて、テーブルを作るときに反転させることにした
    反転するから基本は絶対値が変わる、この辺りは未だに直感的な理解は難しいな
  • 画素変換はチャンネル毎にしてみた、良いわ
  • その他
    右ドラッグでベジェの二つの端点を同時に移動するようにした、結構良い!
    カーブのリセット機能をつけた
    ベジェの計算をマウスリリース時では無くムーヴ時に変えた
    負担は大きくなったがそこそこ動いてる( ´∀`)

ヒストグラム表示

  • pillow の image.histogram() で簡単にイけた
    RGB毎に256個が一列で単純に来るので、表示するときに三色に切り分ければいい
  • ドットで描画したが見づらいのでラインを引くことにしてみた
    ドットは繋がらない、当然かもしれないけど、棒グラフだと塗りつぶされるから折れ線しかないかな
  • しかし、変換後の表示はこれだとうまくいかない
    変換前の画像ならドットのYは飛ぶがx値は連続している
    変換後はそもそもx値が不連続になるのでラインを引いてしまうと山にならずに大きなギザギザになってしまう
    この部分もLUTと同じで座標変換が必要で、まだ頭がついて行けてなくて対応できてない┐('д')┌
  • ヒストグラムの変換(レベル補正)はまだ、見れるだけでもすごく良いわ

リスト内包表記

  • 今回のプログラムはこれのおかげでかなり進んだ
    LUTの作成はこれをフルに活用している
    for で実装すれば良いんだけど一行で書けてしまうし、最初は可読性が低いと思ったけど慣れたらそうでもない
    まあ慣れなきゃイケないんだが
  • 画像のピクセル変換は全てこれで書けると思う
    調べた限りでは普通のforよりも速いらしい
    これは使うべき技術ですよね、もっと勉強したいっす
    改めてpythonに感動した、python固有ってことでもなさそうだけど

ToDo

  • トーンカーブでRGB以外にも対応する
  • ベジェの描画をドットにしてみる(どっちが軽いかな?)
    考えたら描画してるんだからQtは(x,y)を知ってるんだろうな
    関数として提供してくれたらいいのに
  • ヒストグラム表示を正確に
  • ヒストグラム変換実装(レベル補正)
  • pillow の部分を Qt で書く
    データを直接いじるようになったので、pillowを使うメリットが薄れているような???
    Qimage だとデータのポインタを取得できるので直接いじれそう
  • 色調補正を書きたい
    ホワイトポイント系の処理、ロジックがわかれば書けそうなんだけど
  • もろもろ
    scipy 補間ここを読んでもう一回やってみよう
    https://qiita.com/maskot1977/items/2a55c087974d0ac5e843
    PyQtGraph、いつか試してみるか?
    http://www.pyqtgraph.org/
    QImage bit 直接データをいじれる
    https://qiita.com/kanryu/items/89812b362dfd581a4c10