省型旧形国電の残影を求めて

戦前型旧形国電および鉄道と変褪色フィルム写真を中心とした写真補正編集の話題を扱います。他のサイトでは得られない、筆者独自開発の写真補正ツールや補正技法についても情報提供しています。写真補正技法への質問はコメント欄へどうぞ

ヒストグラム平坦化アルゴリズムの仕組みと褪色補正

 ヒストグラム平坦化は、暗部などで細部が見えにくい場合、そのような細部をはっきり見せる目的で使われるアルゴリズムです。基本的な考え方は、通常山があるピクセル分布のヒストグラムをなるべく平坦に直すことで、見えやすくするということです。

 ただ、この平坦化を r,g,b チャンネル別々に実行すると、多くの場合色相がずれます。そのため、その色相のずれをなるべくなくそうといくつかの改良版アルゴリズムが開発されています。しかし、先日お示ししたように、この色相のずれという欠点が、じつは褪色フィルム画像の修復に役立つと指摘しておきました。本稿ではこの色相のずれを生む古典的ヒストグラム平坦化アルゴリズムがどのようなものかを、ImageJ APIソースコードを使って解説します。

 以前にも、この原理について解説したサイトを紹介しておきましたが、ここでもそのリンクを紹介しておきます。

codezine.jp

 ただ、具体的にどのようにアルゴリズムを実装しているのでしょうか?要するに、山のあるヒストグラムをなるべく平坦になるように目指して並べ替えるということを行います。

 今、8bit の画像を例えに考えてみましょう。8 bit 画像にはそれぞれのチャンネルごとに、 0 ~ 255 の 256通りの明るさのデータを取ります。ブラックポイント (最暗点) が 0, ホワイトポイント (最明点) が 255 の値を取ります。そして、0 ~ 255 までの値に対してヒストグラムを取るということは、例えば 0 の値を取るピクセルは何個、1 の値を取るピクセルは何個、2 の値を取るピクセルは何個、というようなデータが、255 の明るさまで取得されます。

 これをどうやってなるべく平坦化するのでしょうか。例えば、今画像全体に、25600 ピクセルあるとします。すると、1つの明るさ当たりの平均ピクセル数は、100ピクセルとなります。とはいえ、実際に各明るさごとに入っているピクセル数はバラバラです。これを 100 ピクセルに均すということはできません。

 そこで、ピクセル数を均さない代わりに、各明るさごとのピクセル数に応じて、明るさの階調の間隔を調整します。つまり明るさの値を変えてしまうのです。そのために、各明るさごとに、明るさが 0 をスタートポイントとしたときに累積ピクセル数を求めます。例えば明るさが 128 の場合、明るさが 0 ~ 128 までのそれぞれのピクセル数を足し合わせたものが累積ピクセル数になります。

 例えば、仮に明るさ 128 の累積ピクセル数が、12800 だったとします。次に 129 の累積ピクセル数が、12801 だとします。つまり、129の値を取るピクセルが1つしかないわけです。その場合は、129 の値を、128に変更して、128 のピクセルに合併させてしまいます。逆に、128 の累積ピクセル数が、12800 のときに、129 の累積ピクセル数が、14800 だとします。つまり平均 100 ピクセルのところを、129 の値を取るピクセルが、その 20 倍の 2000ピクセルあるということです。この場合は、129 の値をもっと明るくして、元々 128 のピクセルとの間隔を開けます。その場合は、128 の値ももっと下げる必要があるでしょう。つまり累積ピクセル数の差が少ない隣接した明るさのピクセル同士はなるべく諧調の間隔を小さくし (場合によると同じ値にして合併させ)、累積ピクセル数の差が大きいピクセル同士は、ピクセル値を変更して諧調の間隔をあけることで、なるべく全体的にヒストグラムが均されるよう目指します。 これが上のリンク先の図3 の右下のグラフです。要は明度ヒストグラムにおける或る明度区間に属するピクセルに関して、明度 0 からその区間までの累積度数を基に明度の値を割り当てなおす、ということをやっているわけです。

 では、具体的なアルゴリズムを見てみたいと思います。ImageJ の Contrast Enhanser API を取り上げます。

API の説明はこちらです。

imagej.net

ソースコードはこちらです。Java で書かれています。

imagej.net

 元々は、ImageJ のプラグインとして書かれています。このコードは、ヒストグラム平坦化だけではないので、ヒストグラム平坦化の部分のみ抜粋してみてみましょう。

 基本は equalize というユーザ定義関数ですが、同名の関数が3つあります。一つは ImagePlus (= ImageJ 上でほぼファイルに相当) を引数として取るもの、他は ImageProcessor (= ImageJ 上でファイル中の RGB データの入った実体に相当) を引数として取るものです。このうち一つは、histogram 変数が引数として指定されていない場合、それを引数として取れるようにするためのダミー的関数です。

 そして、ImagePlus を引数として取る関数から、ImageProcessor を引数として取る関数を呼び出しています。この後者がアルゴリズムの核心部分が書かれた関数です。

------------

    private void equalize(ImageProcessor ip, int histogram) {
        ip.resetRoi();
        if (ip instanceof ShortProcessor) { // Short
            max = 65535;
            range = 65535;
        } else { //bytes
            max = 255;
            range = 255;
        }
        double sum;
        sum = getWeightedValue(histogram, 0);
        for (int i=1; i<max; i++)
            sum += 2 * getWeightedValue(histogram, i);
        sum += getWeightedValue(histogram, max);
        double scale = range/sum;
        int
lut = new int[range+1];
        lut[0] = 0;
        sum = getWeightedValue(histogram, 0);
        for (int i=1; i<max; i++) {
            double delta = getWeightedValue(histogram, i);
            sum += delta;
            lut[i] = (int)Math.round(sum*scale);
            sum += delta;
        }
        lut[max] = max;
        applyTable(ip, lut);
    }

-------------------

 この equalize 関数は、ヒストグラム平坦化実行対象の imageProcessor (以下 ip と略)と、ヒストグラムデータの入った配列を引数として取ります。この関数を呼び出す前に、ip に対し、getHistogram() メソッドを適用し、ヒストグラムデータの入った histogram という配列を引数として与えます。なお、ImageJ の場合、getHistogram() メソッドは 32bit 浮動小数点画像では無効なので、8bit もしくは 16bit 画像しかこのアルゴリズムを適用できません。

 まず、もし ROI が設定されている (=範囲指定されている) 場合は、リセットし消去します。

 次に、画像が 16bit なのか 8bit なのかを判定し、16bit の場合は、明るさの最大値 (max)、およびヒストグラムの区間数 (range) に 65535 を、そうでなければ 255 を与えます。

 次にピクセルの累積数を計算するための sum という変数を初期化し、まずヒストグラムの値が 0 (ブラックポイント) に属するピクセル数を入力します。この時、getWeightedValue(histogram, 0) というユーザ定義関数を使っていますが、これは古典的アルゴリズムを使う場合は、そのまま histogram[0] のピクセル数の値を返します。なお色相の変化が起こりにくいアルゴリズムを使う場合は、上の値の平方根を取りますが、この記事の関心は、褪色の修復を可能にする古典的アルゴリズムですので、とりあえず、

 getWeightedValue(histogram, i)

と出てきたら、明度 i に属するピクセル数、つまり histogram[i] を取得するものと解釈してください。

 その後、ホワイトポイントの1歩手前まで、ピクセル数を2倍して足し合わせていきます。ホワイトポイントに関しては、2倍せず、そのままピクセル数を足します。この理由については後述しますが、基本的には、画像の総ピクセル数 x 2 の値の近似値を求めることになります。但し、2 倍することはヒストグラム平坦化アルゴリズム上必然的に必要なことではなく、いわばこのプログラムの工夫の部分です。

 その後、ヒストグラムの区間数を画像の総ピクセル数 x 2 近似値で割りますが、いわば平均値の約2倍の逆数を取ることになります。この値を scale という変数に入れます。

 次に元の画像の明るさを変換するための対照表 (Look up table = Lut) を初期化します。この対照表は配列となっており、その要素数は、明度の階調 (256 もしくは 65356) と同じです。lut[i] には明度 i のピクセルをどの明度に変換するか、この後計算した変換後の明度値を入れていきます。そしてまず lut[0] に 0 の値を入れます。これはブラックポイントのデータは明度変換を行わない (0 のまま) ということを意味します。

 再び累積値を格納する変数 sum を初期化し、ホワイトポイントの一歩手前まで、for ループで以下の作業を反復します。

 まず変数 delta に、明度 i のピクセル数を格納します。

 そして、sum にデルタを足し合わせることでそこまでのピクセル数 (x 2) の累積値を計算します。

 ここで、lut[i] の値を計算します。この値は、ここまでの累積値に scale を掛けて、整数化した値です。この scale とはいわば各区間のピクセル数平均値 (実はそれをさらに2倍していますが) の逆数です。この意味はどういうことかと考えると (以下平均値を 2 倍していることは一時的に棚上げして説明します) ... 仮に、ヒストグラムの各区間のピクセル数がすべて同じで平均値に一致すると考えましょう。仮にこの平均ピクセル数が 100 だとすると (その場合 8bit 画像なら総ピクセル数は 25600 ピクセルになる)、明度 100 の区間の場合、そこまでの累積ピクセル数は、10000 になるはずです。そこで、ピクセル数の平均値の逆数、つまり 1 / 100 を掛けて、Lut 上の変更する明度の値を求めると、100 になります。ということは、元の明度値が 100 に対するLut の値はそのまま 100、つまり元の 100 の値は変化なし、ということになります。

 ところがこの画像がシャドウ域に寄っているとします。そうだとすると、 100 の値のところの累積ピクセル数は、20000 になっているかもしれません。そこに平均値の逆数を掛けると、200 になります。つまり、100 の明度のピクセルを、200 の明度に変更するということになります。これは、シャドウ域の偏りをなるべく直すために、シャドウ域にあるピクセルを明るくするということを意味します。

 逆に、画像がハイライト域に寄っている場合は、100 の明度までの累積値が、10000 を下回る数になっているはずです。例えば、5000になっているかもしれません。それに平均値の逆数を掛けると 50 になりますので、100 の明度を 50 に直す、つまり全般的に暗くして平坦化をなるべく実現しようとする、ということです。

 このようにして、0 から当該区間までの累積度数に基づいて、当該区間の明度値を Lut を使って振りなおしていきます。

 ただ、このコードでは scale に平均値の逆数ではなく平均値の2倍の逆数を取っています。これは lut の値を計算した後さらに、また delta 値を累積値に加算しているためです。これは値を移動する場合でもなるべく区間の中間値に変更させようという意図 (工夫) があるためだと思います。ですので scale は平均値の2倍の逆数を取るのです。また同様の意図から、scale 値を計算するときの sum を計算するときに、最初のブラックポイントと最後のホワイトポイントに関しては、ピクセル数を 2 倍せずに加算しています。

 そして最後にこうやって作成した lut を ip に適用して画像を変換します。

 これを、R, G, B 3チャンネルに対して実行しますので、各区間に入るピクセルの頻度は異なるものの、ある特定の明度まで (例えば 0 〜 100) の累積頻度は、多少のずれはあるものの概ね揃うことになります。結果として、R, G, B の各ヒストグラムは、全く同じになるわけではありませんが、概ね似た形になります。これは褪色補正の基本原理に合致しますので、褪色補正効果が現れる、ということになります。

 なお、ここでヒストグラムの形をある程度揃えたとしても、しっかり R, G, B の違いが残っている、ということが重要で、著しく褪色が進んだ画像の場合は R, G, B の違いがほとんどなくなりほぼモノクロ画像になる場合があります。この場合は色情報が失われたということを意味しますので、着色以外に修復手段がないということになります。

 一方、「改良」版のヒストグラム平坦化は、なるべく R, G, B の差を維持したまま (つまり色を変化させないまま)、ヒストグラムの平坦化を行おうとしますので、全く褪色補正効果が現れません。但し、単純に暗い部分をはっきり見せる、という目的のためには、色相が変わらない (R, G, B 差が維持されたままの) 方が好都合です。Photoshop はおそらくこちらの「改良」版のヒストグラム平坦化を実装しているものと思われますので、Photoshop では褪色補正効果がないのです。また、ImageMagick も最近のバージョンでは「改良」版を実装しています。

 なお、褪色画像に対して、画像によっては非常に効果的な修復効果が得られますが、その理由の一つには、Lut を使って画像の値を変換しているということがあると思います。それにより他の方法 (例えばトーンカーブを使うなど) で変換するよりも大胆な画像変換が可能になるからです。

 また、このアルゴリズムは褪色がある程度進んだ画像では有効ですが、褪色があまり進んでいない画像に適用すると結構色がおかしくなります。褪色が軽度の場合は別の補正手段を使った方が良いでしょう。

 なお、以上から明らかなように、このアルゴリズムは諧調併合やトーンジャンプが必然的に起こります。そこで、オリジナルが 16bit 画像であると、元々の諧調間隔が狭い分、ヒストグラム平坦化の結果もおおむね滑らかになりますので、トーンジャンプについても問題にならないレベルにとどまります。従ってこのアルゴリズムを使って、補正を行うつもりなら、なるべくフィルムは 16bit でスキャンして保存することが望ましいことになります。

-----------

 なお、褪色補正には色相のシフトを回避するアルゴリズムの「改良」はむしろ不都合で意味がありませんが、余談として、この「改良」について触れたいと思います。ImageJ のこのプログラムの「改良」版アルゴリズムでは、累積ピクセル数の平方根を取ることで色相のシフトを軽減するようになっています。しかし、他に L*a*b* や HSL, LCh に変換して L 値にのみヒストグラム平坦化を適用することで色相のシフトを回避するアルゴリズムを採用しているケースもあるようです。この辺りはプログラムによってどのように実装するかで結果が微妙に異なります。

-----------

[関連サイト]

yasuo-ssi.hatenablog.com

yasuo-ssi.hatenablog.com

yasuo-ssi.hatenablog.com

yasuo-ssi.hatenablog.com

【緊急!】GIMP Scripts サイトが 5/1 に閉鎖予定

 以前、GIMP 用のスクリプトを配布するサイト GIMP Scripts を紹介しましたが、5/1 限りで閉鎖との予告が出ています。もし必要なスクリプトをダウンロードする必要がある場合は、至急ダウンロードすることをお勧めします。

www.gimpscripts.net

 もちろん、スクリプトによっては GIMP Scripts でなくてもダウンロードできるものもありますが...

 例えば PSPI の 1.07 はこちらからしかダウンロードできないと思います。

北関東で活躍した EF12 1 (蔵出し画像)

 EF10 の出力強化型後継機として、1941年に登場した機関車です。本車はそのトップナンバーです。戦前の貨物機関車の到達点と言われますが、製造輌数はやや少なく、17輌にとどまりました。また戦時中の資材不足で、最後の車輛が出場したのは、1944年でした。

 撮影当時は高崎第二機関区に集中配備され、山手貨物線以北、北関東を中心に活躍していました。そのため個人的にはなかなか出会う機会のない機関車でした。

 この年の3月改正で高崎地区の急形国電が引退し、解体を待つ間留置されている姿を撮るために出かけた際に出会って撮影したものです。北関東配置のためスノープロウをつけたいかめしい姿をしています。

EF12 1 (高二) 1978.3 新前橋

EF12 1 (高二) 1978.3 新前橋

 なお、こちらのページの記述によると、EF12 1 の車歴は下記のようです。筆者の方に感謝いたします。

1941.03 日立製造 → 使用開始 1941.03 沼津 → 1946.3現在 国府津 → 1955.3現在 → 高崎二 → 1975.3現在 高崎二 → 1982.05.11 廃車 (高二)

 本形式は、戦災で廃車になることなく、17輌全機が後年まで活躍しました。戦後は、多くが高崎第二機関区に配置され、主に上越高崎線系等で使われましたが、一部新鶴見機関区に配置され、EF10などとともに東海道線などでも活躍しました。しかし、そのうちの大半が 1976年から77年にかけて廃車され、軸重の関係で吾妻線用に残された 5 輌のみ、1982年まで残りました。それも吾妻線の貨物廃止で、最後の 5 輌も廃車となったようです。今考えるともうちょっと長く活躍しても良かったように思われますが...

ImageJ / Python プログラミング Tips: Jython ではリスト変数と配列は異なる

 ImageJ における Python は厳密に言うと、Jython と言って、Python のインターフェースから Java を操作する言語を使っています。

 元々 Python は、インタープリターとして C言語で書かれたコードを実行する、言わば C 言語の複雑さをオブラートで包むような言語 (CPython) として考えられていたようで、その Java 版として Jython が考えられていたようです。ただ、今日では Python (= CPython) から Java の機能を呼び出すライブラリもできていますので、今は Jython を使う意味が薄れています。そのため、Jython も 2015 年以降あまり進化していないようです。おそらく今日 Jython を使う意味は、ほぼ ImageJ を Python で操作するためと言って良いでしょう。ただ、開発が完全に終了したのではなく、メンテナンスリリースは続いているようです*1

www.jython.org

 従って、Jython は、ちょっと古い Python 2.7 準拠になっていますが、それ以外にも通常の Python とは異なります。それで今回ちょっと躓きました。

 今回つまづいたのは、imageProcessor にある applyTable メソッドです。このメソッドは、imageProcessor に LUT を適用するメソッドです。このメソッドは LUT を引数として取りますが、その LUT は整数の 256 (8bit 画像の場合) もしくは 65536 (16bit 画像の場合) の要素を持つ配列である必要があります。

 ところが Jython 上で正しく整数の配列を読ませているはずなのに、以下のエラーが出ます。

TypeError: applyTable(): 1st arg can't be coerced to int[]

 余談ですが、Chat GPT にどうして間違っているのですか、と聞いてみたところ、「コードは正しい様です。他のところが間違っているかもしれません」と答えます。ちなみに Chat GPT はプログラミングのアルゴリズムに関して、メジャーな言語、皆がよく使うようなアルゴリズムに関しては、かなりよく答えてくれますが、マイナーでニッチな言語のアルゴリズムに関してはあまり当てになりません。その原理を考えれば当然です。つまり、学習するための元ネタが少ないので、答えも怪しくなる、ということです (もちろん元ネタがいっぱいあっても、皆が間違っていれば間違った答えが出ます)。Jython でプログラミングをするなんてその最たるものでしょう。GIMP 用のスクリプトPython で書くのも、Chat GPT に正しい答えを期待できません。「本当にそれで合っていますか?」と問いかけると「すみません。間違いがありました」と言って、別のコードを提案してきます。さらに、「本当にこれで大丈夫ですか?」と追加で問いかけるとまた「すみません。間違いがありました」という具合です。Chat GPT が提案してきたコードが正しいかどうかを判断するには、自分がその言語に対してちゃんと知識が必要で、うっかりそのまま鵜呑みにできません。特にマイナーであればあるほど怪しいです。

 まぁ、Chat GPT はネット上の多数決によって決まった回答を出してくれるサービスだと思えば良いのではないでしょうか。ただ、多数決によって決まった回答が常に正しいとは限りません。プーチンだってロシア国民の圧倒的多数から支持されているのですから。

 それはともかく、その理由を探るために、Java 関連の情報を探っていると、Python では配列=リスト変数ですが、Java ではそうではなく、配列 (arrey) とリスト変数は別だということが分かりました。配列は要素数が固定されているのに対し、リスト変数は Python と同じく、要素を増やしたり減らしたりできるというのです。つまり Python のリスト変数で LUT を作ると、それを Java の配列として認識してくれないため、型がおかしいと文句を言ってくるのではないかと推測しました。

 では、Jython 上で、Java の配列が扱えないかと調べてみると、以下のような情報が見つかりました。

docs.oracle.com

 結局、この移行ガイドにあるように、

import jarray

を頭につけ、その後、

lut = jarray.array([0]*256, 'i')

で lut を作成すると、その lut を引数として取った applyTable メソッドがちゃんと動くことが分かりました。

 なお、試していませんが、以下のようなコードでも良いようです。

import java
java.type("int[]")(10)

 これ以外にも、PythonJava の型の違いから、漫然とコードを書くとうまく ImageJ の API が動いてくれないということが色々ありそうです。ImageJ の API は基本 Java 準拠ですので、この点は要注意かと思われます。

*1:なお、Java を操作する Python 3.x 準拠の Python インタープリターとして、GraalPy というのも開発されているようです。

medium.com ただ、この記事は2020年以降、Jython はメンテナンスされていないと書かれていますが、2022年にメンテナンスリリースが出ています。おそらく ImageJ で使われている限り、2年に一度程度メンテナンスが入るのではないでしょうか。

ART 1.21.3 がリリース

f:id:yasuo_ssi:20210904211415j:plain

 ART Ver. 1.21.3 が昨日リリースされました。アップデート内容としては、Libraw のアップデートに対応して、最新カメラに対応、および一部カメラでクロップ設定が正しく解釈されないものに対するバグフィックスです。ダウンロードは下記より。

 

bitbucket.org

モノクロ画像のカラー化を行う業者: Adjust Photo Service

 X を見ていたら、Adjust Photo Service という横浜にある業者さんのモノクロ画像をカラー化したケースを紹介した記事が流れてきました。その業者さんのホームページはこちらです。三木秀記さんという方が個人でやっている会社のようです。

www.adjust.co.jp このページの紹介によると、複数のソフトウェアを使った AI によるカラー化画像を組み合わせて編集し、さらに、必要に応じて手作業によって着色を行い最終的に仕上げているようです。AI のカラー化に掛ける前に一旦画像の高精細化や汚れ、傷などの修復も加えているとのことです。おそらく画像の高精細化 (補間) にも AI ソフトを使っているものと思われます。元々はグラフィックデザインを手掛ける事務所だったようですが、2016年から個人向けの写真修復サービスを手掛けはじめ、おそらく AI を使い始めたのは サンプルファイルから推測する限り、2020年頃からのようで、北國新聞の昔の写真のカラー化プロジェクトを2021年から手掛けておられるようです。

 補正例を見るとかなりナチュラルな結果が得られています。このページにいくつかのサンプルが掲載されていますが、多少出来に、出来不出来はありますが、おおむねかなりナチュラルな結果が得られており、いかにも AI 加工したという感じも、逆に着色したという感じも少ないです。

 このサイトには、Ai による着色のみでは十分な結果が得られないと書かれておられますが、その通りだと思います。現状 Ai による着色は、写ったものの形状から色を推測していますので、特に人間が任意に、恣意的に色を決めているもの、例えば、着物の色や柄、看板の色、鉄道車両の塗装といったものに関しては、原理的に不正確な結果しか得られません。たくさんの学習データを読ませても正確度が上がるとは限りません。結局、指摘されている通り、資料を読み込んだり、当時を目撃した人の証言などをもとに、色を推測して手作業で着色するしかないのです。

 また、同じ Ai に掛けるにしても、元画像の解像度が高い方が、Ai の色の推測精度も上がるという指摘は、参考になりました。おそらく bit 深度も深いほうが良いと思います。

 因みに料金ですが、ホームページを拝見すると、最も難易度の低いものは 8800円 難易度が最も高いものだと、44000円 という価格設定です。仮に 1時間当たりの作業工賃が 2000 円と仮定すると、1枚当たり最低 4 時間ぐらいから、難易度が高いものだと、22時間ぐらいの時間をかけている計算になりますが、おそらくそんなものでしょう。おそらく AI で出力したものを編集する、あるいはそれにちょっと手をかける程度が、8800円、それに対し、フルに手作業が要求される画像が 44000 円というあたりでしょうか。それでも補修難易度を考えると安いぐらいかもしれません。この辺りは自分で写真補正をやってみないとどんなに大変か分からないので、高すぎると思われる方もいらっしゃるかもしれません。

 逆に最高 44000 円という料金から考えると、フルに手作業で着色作業をやっても、24時間近くかければ何とかなる、ということなのかもしれません。とはいえ、素人だと、難易度の非常に高い画像をフルに手作業着色作業を行った場合、丸々24時間かけても到底完成するとも思えませんので、この辺りは熟練の技かと思われます。

 

凍てつく冬の辰野駅に佇む飯田線クモハ54127

 下の写真は、凍てつく厳冬の辰野駅に進入するクモハ54127 です。茅野発平岡行き238Mとして6 輛編成でやってきました。以前掲げたことのある写真ですが再編集しました。

クモハ54127 (静トヨ) 1978.1 辰野

 この日クモハ54127は豊橋機関区53運用についていました。伊那松島機関区 71, 86 運用を従えてやってきました。この時の編成をメモから再現しますと、茅野発平岡行238Mで、[53運用]54127+68042 + [77]47011+54106 + [79]51027+68402という編成でした。ここ辰野で[79]を切り離し、伊那松島で[77]を分離し、[53]運用単独で平岡へ向かう予定でした。編成の後ろには辰野駅のテルハが見えます。かつては主要駅のどこにでもありましたが、これも荷物・郵便輸送がなくなって、消えてしまった駅の風景です。

 関西でHゴム化が進行する前に、関西から飯田線に転入してきたため、運転台や戸袋窓にHゴムはなく綺麗な姿です。またパンタグラフも原形の PS-11 でした。ただし、運転台助士席側窓は隙間風対策で2段から1段に改修されています。

クモハ54127 (静トヨ) 1978.1 辰野

 なお、2-4位側の写真が撮れていませんが、他の方の写真を見ると客用扉の形状は、1-3位側と同じだったようです。

本車の車歴です。

1943.7.17 汽車会社東京支店製造 (モハ60095) → 1943.9.20 使用開始 大ミハ → 1944.5.31 座席撤去 → 1948.9.3 大ヨト → 1948.12.19 座席整備 → 1950.11.14  大ミハ → 1953.6.1. 改番 (モハ54127) → 1954.3.21 大アカ → 1955.10.13 更新修繕I 吹田工 → 1965.7.13 静トヨ → 1978.12.20 廃車 (静トヨ)

 本車は元々関西向けモハ60として汽車会社東京支店で製造されました。因みにモハ60のうち関西向けとして製造されたのは、60026 - 60042, 60090 - 60111 で、このうち、60026 - 28 の3輌は1次形ノーシルノーヘッダー、他はシルヘッダー付きで、1943年に投入された 60093以降は、110 を除いて番号にかかわらず奇数向だったようです。なお、クハ55の末期に関西に投入された、55097以降も奇数車だったようで、なぜ奇数車ばかり関西に投入されたのかよく分かりません。あるいは、最初に城東・片町線に投入されたモハ40 (偶数側にパンタグラフ) の片運化計画などを配慮してのことだったのかもしれませんが。なお、関西向きのモハ60は、戦災や事故廃車、もしくは戦後早い時期に関東に転出した車輛を除くと大半が後にセミクロスシート化され、クモハ54に改造されました。本車もその1輌です。その理由は、モハ60の内一定数が宮原区に配置されたのということと、モハ43, 42 のかなりの数が4扉化され、城東・片町線に去って行ったのとの引き換えだったと思われます。

 ロングシートでしたが、製造後初配置は宮原区です。あるいはガソリンカー事故後急いで1941年に電化された西成線用として配置されたのかもしれません。当時西成線の担当は宮原区でした。しかし京阪神緩行線用に、列車種別表示用サボが設置されています。その後、戦後一時的に淀川区に転出しますが、基本的には京阪神緩行線用として使われます。そして京阪神緩行線セミクロスシート復活の方針で、セミクロスシートに改造され、1953年の形式称号改正でクモハ54に編入されます。しかし、1965年に17m車淘汰のため飯田線に転出、その後は継続して豊橋区で使用されました。しかし、1978年の豊橋区80系化で、伊那松島に転出することなく廃車となりました。