技研のまつけんです。

機械学習の仕事をしていると大量の画像をプレビューしなければならない場面があります。特に、動画から静止画を切り出した場合は、数万~数十万枚レベルになることも、しばしばあります。しかし、WindowsのExplorer、MacOSのFinderでのプレビューでは最大サイズまで拡大表示:

しても、よく見えない場合があります。そんなとき、ブラウザでフォルダ内の ( サブフォルダも含めて) 画像をプレビューできたら便利です。そこで、それを実現するためのHTMLファイルを自動生成するシェルスクリプトを自作して使っています。

冒頭のプレビュー画像は、2021年の夏にブルーインパルスを撮影したものです。気付いたら500枚ほど撮影していまして、その中からベストショットを選ぶのにも活躍しました。

基本編

基本形は、以下のようになります:

EXTS="jpg jpeg"
CMD="find -type f "
N=0
for EXT in $EXTS
do
if [ 0 -lt $N ]
then
CMD="$CMD-or "
fi
PTN='"*.'$EXT'"'
CMD="$CMD-iname $PTN "
N=$(($N + 1))
done
echo "$CMD" | bash | sort > files.txt
echo "<html><body>" > index.html
cat files.txt | sed -e 's#^./##' -e 's#^#<img src="#' -e 's#$#"><hr/>#' >> index.html
echo "</html></body>" >> index.html

これにより、以下のようなindex.htmlが生成されます:

<html><body>
<img src="103_0723/_IMG9486.JPG"><hr/>
<img src="103_0723/_IMG9487.JPG"><hr/>
<img src="103_0723/_IMG9488.JPG"><hr/>
(中略)
<img src="105_0723/_IMG0016.JPG"><hr/>
<img src="105_0723/_IMG0017.JPG"><hr/>
<img src="105_0723/_IMG0018.JPG"><hr/>
</html></body>

発展編

せっかくなら、大きさを揃えたり、画像情報を横に表示した状態でプレビューしたいものです。それを実現するのがこちらです:

EXTS="jpg jpeg"
CMD="find -type f "
N=0
for EXT in $EXTS
do
if [ 0 -lt $N ]
then
CMD="$CMD-or "
fi
PTN='"*.'$EXT'"'
CMD="$CMD-iname $PTN "
N=$(($N + 1))
done
echo "$CMD" | bash | sed 's#^\./##' | sort > files.txt
OP1='Pixel X Dimension'
OP2='Pixel Y Dimension'
OP3='Focal Length'
OP4='Focal Length in 35mm'
OP5='F-Number'
OP6='Exposure Time'
OP7='Model'
for OP in "$OP1" "$OP2" "$OP3" "$OP4" "$OP5" "$OP6" "$OP7"
do
cat files.txt | xargs exif | grep -e "^$OP *|" | sed -e "s#^$OP *|##" > "$OP.txt"
done
for WID in 640 1024 act
do
if [ $WID = "act" ]
then
OUT="$WID.html"
WID=""
else
OUT="w$WID.html"
WID="width=$WID "
fi
echo -n "Generating $OUT "
echo "<html><body>" > "$OUT"
echo "<html><body><table border=1>" > "$OUT"
while read LINE
do
FILE=`echo "$LINE" | cut -d , -f 1`
OP1VAL=`echo "$LINE" | cut -d , -f 2`
OP2VAL=`echo "$LINE" | cut -d , -f 3`
OP3VAL=`echo "$LINE" | cut -d , -f 4`
OP4VAL=`echo "$LINE" | cut -d , -f 5`
OP5VAL=`echo "$LINE" | cut -d , -f 6`
OP6VAL=`echo "$LINE" | cut -d , -f 7`
OP7VAL=`echo "$LINE" | cut -d , -f 8`
INFO="$FILE<br/>"
INFO="$INFO$OP1VAL x $OP2VAL<br/>"
INFO="$INFO$OP3: $OP3VAL<br/>"
INFO="$INFO$OP4: $OP4VAL<br/>"
INFO="$INFO$OP5: $OP5VAL<br/>"
INFO="$INFO$OP6: $OP6VAL<br/>"
INFO="$INFO$OP7: $OP7VAL<br/>"
echo -n "<tr>" >> "$OUT"
echo -n "<th>" >> "$OUT"
echo -n ' <img '$WID'src="' >> "$OUT"
echo -n "$FILE" >> "$OUT"
echo -n '">' >> "$OUT"
echo -n "</th>" >> "$OUT"
echo -n "<th>" >> "$OUT"
echo "$INFO" >> "$OUT"
echo -n "</th>" >> "$OUT"
echo "</tr>" >> "$OUT"
echo -n "."
done < <( paste -d , files.txt "$OP1.txt" "$OP2.txt" "$OP3.txt" "$OP4.txt" "$OP5.txt" "$OP6.txt" "$OP7.txt" )
echo "</table></html></body>" >> "$OUT"
echo " done."
done

こちらを実行すると、w640.html、w1024.html、act.htmlという3つのHTMLファイルが生成されます (最後のactはactual sizeの意味)。w640.htmlは以下のような内容になります:

<html><body><table border=1>
<tr><th> <img width=640 src="103_0723/_IMG9486.JPG"></th><th>103_0723/_IMG9486.JPG<br/>5472 x 3648<br/>Focal Length: 250.0 mm<br/>Focal Length in 35mm: 375<br/>F-Number: f/14.0<br/>Exposure Time: 1/500 sec.<br/>Model: PENTAX K-S1<br/>
</th></tr>
<tr><th> <img width=640 src="103_0723/_IMG9487.JPG"></th><th>103_0723/_IMG9487.JPG<br/>5472 x 3648<br/>Focal Length: 250.0 mm<br/>Focal Length in 35mm: 375<br/>F-Number: f/14.0<br/>Exposure Time: 1/500 sec.<br/>Model: PENTAX K-S1<br/>
</th></tr>
<tr><th> <img width=640 src="103_0723/_IMG9488.JPG"></th><th>103_0723/_IMG9488.JPG<br/>5472 x 3648<br/>Focal Length: 55.0 mm<br/>Focal Length in 35mm: 82<br/>F-Number: f/8.0<br/>Exposure Time: 1/800 sec.<br/>Model: PENTAX K-S1<br/>
</th></tr>
(中略)
<tr><th> <img width=640 src="105_0723/_IMG0016.JPG"></th><th>105_0723/_IMG0016.JPG<br/>5472 x 3648<br/>Focal Length: 300.0 mm<br/>Focal Length in 35mm: 450<br/>F-Number: f/14.0<br/>Exposure Time: 1/640 sec.<br/>Model: PENTAX K-S1<br/>
</th></tr>
<tr><th> <img width=640 src="105_0723/_IMG0017.JPG"></th><th>105_0723/_IMG0017.JPG<br/>5472 x 3648<br/>Focal Length: 300.0 mm<br/>Focal Length in 35mm: 450<br/>F-Number: f/14.0<br/>Exposure Time: 1/500 sec.<br/>Model: PENTAX K-S1<br/>
</th></tr>
<tr><th> <img width=640 src="105_0723/_IMG0018.JPG"></th><th>105_0723/_IMG0018.JPG<br/>5472 x 3648<br/>Focal Length: 300.0 mm<br/>Focal Length in 35mm: 450<br/>F-Number: f/14.0<br/>Exposure Time: 1/500 sec.<br/>Model: PENTAX K-S1<br/>
</th></tr>
</table></html></body>

w640をブラウザで開くと、このように表示されます:

なお、上記のシェルスクリプトを変更すれば、こちら:

のように横方向に4枚ずつ表示することも可能です。10行程度の追加で可能なのですが、どのように変更すれば良いのかは、長くなるので掲載しません (所謂、「読者への宿題とする」)。ヒントは「n行に一度だけ</tr><tr>を出力し、それ以外の場合は<th/>を出力する」ようにすればよい、です。

まとめ

如何でしたか? 今回は、画像が大量にある場合に、OSのプレビューでは小さいと思ったとき、また、Exif情報も一覧で見たい場合にブラウザでそれを実現するためのシェルスクリプトを紹介しました。なお、<img src=”…”>を出力しないようにすれば、ファイル名とExif情報だけを一覧表示することも出来ますね。もし良かったら試してみてください。