2021年1月30日土曜日

ペリカン児童公園から田ノ上公園

 11月15日のお散歩写真の続きです。

アパートから隣駅の羽村駅まで散歩しました。

ハードオフを冷かしてから、羽村市役所近くにあるペリカン児童公園へ。





ここのイチョウはきれいに黄葉していました。

雑誌の撮影なのか、キヤノンの白い望遠ズームを付けたのを

持っている女性が家族連れの写真を撮ってました。



青梅線の踏切を渡って、田ノ上公園へ。
桜があるのは覚えていたけど、他の木はあまり覚えが無かったですが、ハナミズキ。



田ノ上公園にモミジもあったのですね。
こんなことなら、マクロレンズも持ってくれば良かった。
Panasonic DMC-GX7, SIGMA 60mmF2.8DN

2021年1月24日日曜日

武蔵野公園のイチョウ

 11月15日のお散歩写真です。

アパートから隣駅の羽村駅まで散歩しました。




羽村市の武蔵野公園のイチョウ並木は色づいていました。

この日はお天気が良く、お出かけ日和でここに家族写真を

撮りに来ている人が居ました。




武蔵野公園の近くの児童公園のモミジ

今年は状態が悪かったです。

Panasonic DMC-GX7, SIGMA 60mmF2.8DN




年末にお散歩で使って、OLYMPUS E-P3が調子良かったので、

1台追加してみました。

ファームウェアを更新するのに、OLYMPUS用のUSBケーブルを

探して、部屋の中をひっくり返して、探すことになりましたw

なんだかUSB充電器やらmicro-bのUSBケーブルがゴロゴロ出てきて

ちょっと捨てないといけないようです(汗)


せっかくカメラを買ったのに、この週末は雨降りで、

お出かけすることはできませんでした。


2021年1月17日日曜日

秋のご近所散歩

 11月7日のお散歩写真です。

ご近所を散歩しました。


アパートから徒歩2分ぐらいにある公園の木

なんか、つやつやに写りました。

腐ってもデジタル用レンズだけのことはある?



畑の柿の実



武蔵野公園に行ってみました。




武蔵野公園の隣の緑道

Panasonic DMC-GX7, OLYMPUS 40-150mm




2021年1月9日土曜日

GIMP 2.10 でトーンカーブのインポートでエラーになる

 今のPCに切り替えてから、ずっとGIMP はPortable版の2.8を

使っていたのですが、最近になって Portable 版の2.10 を

インストールして使い始めています。

昔 GIMP 2.6 の頃にダウンロードしたトーンカーブを

GIMP Portable 2.10 トーンカーブの「現在の設定をファイル

からインポート」で読み込むと、「〇〇の読み込み中にエラーが発生しました。

 想定していたよりも早くストリームの最後に到達しました。」

というエラーになってしまいました。




で、GIMP Portable 2.10 でエクスポートしたファイルと見比べて、

以下のことに気を付けてインポートできるようになりました。


(1) 改行コードは LF

(2) 最初の行は "# GIMP Curves File" 以外のことを書かない

(3) 数値データ行の最後にスペースを1文字入れる



(1) について

自分で作ったファイルは CR+LF だったので、エラーになりました。


(2) について

# で始まっている行なので、コメント行かと思って、

適当にコメントを書き足していたら、エラーになりました。


(3) について

昔ダウンロードしたファイルが読めなかったのはこれが原因だったようです。


---


GIMP のトーンカーブがダウンロードできるところを

探してみたら、ここが見つかりました。


https://gist.github.com/neo22s/f7d9a1348b4376f8085b1e1387edf9a5


このページの "gimp-curves-tool.settings" と書いてある右側の Raw

ボタンをクリックすると、設定ファイルだけのページに移るので、それを保存します。

GIMP Portable 2.10 だと、このファイルを GimpPortable を

インストールしたディレクトリの

Data\.gimp\filters\GimpCurvesConfig.settings

に上書きすると、トーンカーブが使えるようになります。

【注】トーンカーブの履歴が消えてしまうので、消えると困る場合は上書きしないでください。


設定したトーンカーブを呼び出すには、GIMP Portableで画像ファイルを

開いたところで、メニューの

「色(C)」 → 「トーンカーブ(C)」

を選択し、トーンカーブのダイアログを開きます。





トーンカーブのダイアログの「プリセット」のドロップダウンリストに

ダウンロードしたトーンカーブのプリセットが入っています。

「Cross Process」のトーンカーブは、昔ダウンロードしたものと同様のカーブでした。





トーンカーブを適用すると、このプリセットのドロップダウンリストに

履歴が追加されるようです。

トーンカーブを1つだけエクスポートしたり、不要なトーンカーブを

削除するには、プリセットのドロップダウンリストの右側の

「プリセットの管理」をクリックします。




クリックすると、プリセットに関するメニューが出るので、

エクスポートしたり、削除したりする機能を呼び出せます。




2021年1月2日土曜日

Python+Pillowでミラーエフェクト

最近、お出かけすることが減って、Pythonを勉強しています。
そのPython言語の、Pillowという画像ライブラリを使ったスクリプトです。
Pythonをインストールして、Pillowのライブラリをpipでインストールしておく必要があります。
記事を書いている時点のPythonは3.8です。

前回までは、塗りつぶしした画像やぼかし加工した画像を元の画像とブレンドしていますが、
今回のスクリプトは、元画像を折り返ししたものを元画像と並べるだけなので、
比較的、簡単な処理になっています。

折り返して貼り合わせるだけなので、あんまり面白くないかなぁって思っていましたが、
元の画像によっては、意外と面白い画像が出来上がりました。

以下にスクリプトのコードを書きます。


"""
鏡に映したように左右対称の画像にする
tkinterを使ったGUI版
Usage : コマンドラインから以下のコマンドで起動
    python mirror_gui.py
"""

import os
from PIL import Image, ImageTk, ImageOps
import tkinter as tk
from tkinter import ttk
from tkinter import filedialog, messagebox

class FormClass:
    """ 
    鏡に映したように加工する画面のフォームを作成するクラス
    """

    def __init__(self, root):
        # インスタンス変数に初期値設定
        self.root = root     # Windowオブジェクト
        self.filepath = ""   # 入力ファイル名
        self.readimg = None  # 入力画像
        self.dst_img = None  # 加工結果画像

        rowno = 0            # 表示位置(行番号)

        # ラベルを作成
        tk.Label(root, text='入力ファイルPATH'
                ).grid(column=0, row=rowno)

        # 入力ファイル名
        self.src_path = tk.StringVar()

        # テキストボックスを作成
        tb_widget = tk.Entry(root, 
                             width=120, 
                             textvariable=self.src_path)
        tb_widget.grid(column=1, row=rowno)

        # 入力ファイル選択ボタンを作成
        btn_widget = tk.Button(root, 
                               text='入力ファイル選択', 
                               command=self.select_file)
        btn_widget.grid(column=2, row=rowno)
        rowno += 1

        # 左位置 スケールの作成
        tk.Label(root, text='左位置(%)'
                ).grid(column=0, row=rowno)

        self.left = tk.DoubleVar()
        left_sc = tk.Scale(
                     root,
                     variable=self.left,
                     orient=tk.HORIZONTAL,
                     from_=0,
                     to=100,
                     command=self.draw_effect)
        left_sc.grid(column=1, 
                     row=rowno, 
                     sticky=(tk.N, tk.E, tk.S, tk.W))
        self.left.set(0)
        rowno += 1

        # 右位置 スケールの作成
        tk.Label(root, text='右位置(%)'
                ).grid(column=0, row=rowno)

        self.right = tk.DoubleVar()
        right_sc = tk.Scale(
                     root,
                     variable=self.right,
                     orient=tk.HORIZONTAL,
                     from_=0,
                     to=100,
                     command=self.draw_effect)
        right_sc.grid(column=1, 
                     row=rowno, 
                     sticky=(tk.N, tk.E, tk.S, tk.W))
        self.right.set(50)
        rowno += 1

        # 反転方向 コンボボックスの作成
        tk.Label(root, text='反転方向'
                ).grid(column=0, row=rowno, pady=5)

        self.direct_select = tk.StringVar()
        direct_combo = ttk.Combobox(
                        root,
                        textvariable=self.direct_select)
        direct_combo.grid(column=1, 
                           row=rowno, 
                           pady=5,
                           sticky=(tk.N, tk.W))
        direct_combo['values'] = ('左右', '上下')
        direct_combo.current(0)
        direct_combo.bind("<>", self.draw_effect)
        self.direct_select.set('左右')
        rowno += 1

        # 左右反転 コンボボックスの作成
        tk.Label(root, text='左右反転'
                ).grid(column=0, row=rowno, pady=5)

        self.reverse_select = tk.StringVar()
        reverse_combo = ttk.Combobox(
                        root,
                        textvariable=self.reverse_select)
        reverse_combo.grid(column=1, 
                           row=rowno, 
                           pady=5,
                           sticky=(tk.N, tk.W))
        reverse_combo['values'] = ('右', '左')
        reverse_combo.current(0)
        reverse_combo.bind("<>", self.draw_effect)
        self.reverse_select.set('右')
        rowno += 1

        # ファイル保存ボタンを作成
        savebtn_widget = tk.Button(root, 
                                   text='ファイル保存', 
                                   command=self.show_save_dialog)
        savebtn_widget.grid(column=0, row=rowno,
                            sticky=(tk.N))

        self.CANVAS_WIDTH = 800
        self.CANVAS_HEIGHT = 600

        # 画像を表示するためのキャンバスの作成
        self.canvas = tk.Canvas(self.root, 
                                width=self.CANVAS_WIDTH, 
                                height=self.CANVAS_HEIGHT)
        self.canvas.grid(column=1, row=rowno, columnspan=2)


    # 入力ファイル選択ボタン押下イベント
    def select_file(self):
        # ファイル選択ダイアログを表示
        ftypes = [("All Files", ".*"),
                  ("JPEG Image Files", ".jpg .jpeg"),
                  ("PNG Image Files", ".png")]

        if len(self.filepath) == 0:
            idir = os.path.abspath(os.path.dirname(__file__))
        else:
            idir = os.path.dirname(self.filepath)
        self.filepath = filedialog.askopenfilename(filetypes = ftypes,
                                                   initialdir = idir)
        if len(self.filepath) == 0 :
            return
        self.src_path.set(self.filepath)

        # 画像を読み取り
        self.readimg = Image.open(self.filepath)
        # Exif情報を取り出し
        if 'exif' in self.readimg.info :
            self.exif = self.readimg.info['exif']
        else :
            self.exif = bytes()

        # 加工した画像を表示
        self.draw_effect()

    # 加工した画像を表示する
    def draw_effect(self,val=0):
        if self.readimg is None :
            return

        # 元画像のサイズ
        w,h = self.readimg.size

        if self.direct_select.get() == '左右' :
            # 左右方向に折り返す
            left = w * self.left.get() / 100.0
            right = w * self.right.get() / 100.0
            w_start = int(min(left,right))
            w_end = int(max(left,right))
            w = (w_end - w_start) * 2
            # 元の画像と、折り返した画像を合成する
            im_crop = self.readimg.crop((w_start, 0, w_end, h))
            im_flip = ImageOps.mirror(im_crop)
            # 出力画像の幅か高さが 0 なら return
            if w == 0 or h == 0:
                return
            self.dst_img = Image.new("RGB", (w, h), 0)
            if self.reverse_select.get() == '右':
                self.dst_img.paste(im_crop)
                self.dst_img.paste(im_flip, ((w_end - w_start), 0))
            else :
                self.dst_img.paste(im_flip)
                self.dst_img.paste(im_crop, ((w_end - w_start), 0))
        else :
            # 上下方向に折り返す
            upper = h * self.left.get() / 100.0
            lower = h * self.right.get() / 100.0
            h_start = int(min(upper,lower))
            h_end = int(max(upper,lower))
            h = (h_end - h_start) * 2
            # 元の画像と、折り返した画像を合成する
            im_crop = self.readimg.crop((0, h_start, w, h_end))
            im_flip = ImageOps.flip(im_crop)
            # 出力画像の幅か高さが 0 なら return
            if w == 0 or h == 0:
                return
            self.dst_img = Image.new("RGB", (w, h), 0)
            if self.reverse_select.get() == '右':
                self.dst_img.paste(im_crop)
                self.dst_img.paste(im_flip, (0, (h_end - h_start)))
            else :
                self.dst_img.paste(im_flip)
                self.dst_img.paste(im_crop, (0, (h_end - h_start)))


        # 画像の表示倍率を計算する
        rate = min(1.0, 
                   self.CANVAS_WIDTH / self.dst_img.width, 
                   self.CANVAS_HEIGHT / self.dst_img.height)

        # 表示用に画像を縮小する
        new_w = int(self.dst_img.width * rate)
        new_h = int(self.dst_img.height * rate)
        small_resized = self.dst_img.resize((new_w, new_h))

        # キャンバスに画像を表示する。
        self.im = ImageTk.PhotoImage(image=small_resized)
        self.canvas.create_image(0, 0, anchor=tk.NW, image=self.im)

    # ファイル保存ボタンイベント
    def show_save_dialog(self):
        if self.dst_img is not None :
            ftypes = [("All Files", ".*"),
                      ("JPEG Image Files", ".jpg .jpeg"),
                      ("PNG Image Files", ".png")]
            ini_fname = os.path.basename(self.filepath)
            filename = filedialog.asksaveasfilename(filetypes=ftypes,
                                                    initialfile=ini_fname)
            if filename:
                # 保存先ファイルが指定されたら、加工した画像を保存
                self.dst_img.save(filename, quality=100, exif=self.exif)
        else :
            tk.messagebox.showerror(title="エラー", 
                                    message="入力ファイルを指定してください")

# windowを描画
window = tk.Tk()
# windowサイズを変更
window.geometry("1000x800")
# windowタイトルを設定
window.title("Mirror effect")

# フォームを作成、表示
FormClass(window)

# 画面を操作されるのを待つ
window.mainloop()

上のスクリプトをUTF-8のエンコーディングで、mirror_gui.py というファイルに保存します。
Windowsだとコマンドプロンプト等を開いて、スクリプトを保存したフォルダにcdコマンドで移動して、

python mirror_gui.py

で実行します。 実行すると、



このような画面を表示します。
入力ファイル選択ボタンで、ファイル選択ダイアログを開きます。
そこでファイルを選択すると、



このように画像のプレビューを表示します。

「左位置」を大きくすると、切り出す左側の位置が右に移動します。

「右位置」を大きくすると、切り出す右側の位置が右に移動します。

「反転方向」で、左右反転と上下反転を切り替えます。

「左右反転」で右画像を折り返して左に貼り付けるか、
  左画像を折り返して右に貼り付けるかを選択します。

「ファイル保存ボタン」をクリックすると、保存先選択ダイアログを開きます。


以下、このスクリプトで加工した画像をアップします。



新橋辺り





ガクアジサイ





コオニユリ