#はじめに
プライベートですが、FireTVStickを導入しています。
TVでAmazonPrimeビデオが見れるようになるアレですね。
FireTVStickはAmazonDrive上の画像からスライドショーを表示できるんです。
スクリーンセーバーとしても設定できるので目の保養としていい感じです。
ところでTumblrっていいですよね(唐突)
dashboardは自分の好きなものストリームなので無限に見れますし、
自分のblogは好きなものの集合体なのでコレクションとしての価値が大きいです。
そんなTumblrの画像群から、スクリーンセーバー向けの画像のピックアップを行いたいとします。
要件としては以下
-
jpgかpngであること
GifファイルはFireTVStickのスライドショーでは動きませんでした。 -
横長の画像で、かつ縦幅の大きいものを優先すること。
画面に映したときに見栄えがいいです。
細長い画像だとあまり美しくないので… -
ファイルサイズの大きいものを優先すること
これも見栄え重視。
対象画像は事前にスクレイピングされているものとします。
ファイル形式もサイズもへったくれもなく1フォルダに入れておきます。
#参考資料様
画像の仕分けスクリプトをPowerShellで書き直す
親元です。私は二番煎じです。
こちらではファイルのプロパティを取得してどうこうされていましたが、
「nnn ピクセル」のString型を整数型に直せず、わかっているやり方に変更。
この部分は「わからなかった部分」として記事末尾に記載しています。
#環境
-Windows10
-PowerShell
#テスト
諸般の事情によりテスト的なものを作成してから持ち込みました。
ランダム画像群を生成してそれに対してスクリプトを実行します。
#Tumble2Amdrのためのランダムファイル群作成
$path = "C:\Workspace\picturetest"
Add-Type -AssemblyName System.Drawing
foreach($i in @(1..100)){
$width = Get-Random -Minimum 160 -Maximum 640
$height = Get-Random -Minimum 160 -Maximum 640
$image= New-Object System.Drawing.Bitmap($width,$height)
$image.Save($path+"\jpg_"+$i+".jpg",[System.Drawing.Imaging.ImageFormat]::Jpeg)
$image.Dispose()
}
foreach($i in @(1..100)){
$width = Get-Random -Minimum 160 -Maximum 640
$height = Get-Random -Minimum 160 -Maximum 640
$image= New-Object System.Drawing.Bitmap($width,$height)
$image.Save($path+"\gif_"+$i+".gif",[System.Drawing.Imaging.ImageFormat]::gif)
$image.Dispose()
}
foreach($i in @(1..100)){
$width = Get-Random -Minimum 160 -Maximum 640
$height = Get-Random -Minimum 160 -Maximum 640
$image= New-Object System.Drawing.Bitmap($width,$height)
$image.Save($path+"\png_"+$i+".png",[System.Drawing.Imaging.ImageFormat]::png)
$image.Dispose()
}
で、これを実行すると…
PS C:\Workspace\picturetest\item> Get-ChildItem
ディレクトリ: C:\Workspace\picturetest\item
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 2018/09/07 8:21 1297 gif_1.gif
-a---- 2018/09/07 8:21 1749 gif_10.gif
-a---- 2018/09/07 8:21 1413 gif_100.gif
-a---- 2018/09/07 8:21 1564 gif_11.gif
-a---- 2018/09/07 8:21 1811 gif_12.gif
(中略)
-a---- 2018/09/07 8:21 646 png_95.png
-a---- 2018/09/07 8:21 1029 png_96.png
-a---- 2018/09/07 8:21 507 png_97.png
-a---- 2018/09/07 8:21 651 png_98.png
-a---- 2018/09/07 8:21 971 png_99.png
さまざまな画像サイズのファイル群が作成されました。
#ソースコード
本題はこっち。
# Tumblrの画像群からスクリーンセーバー向けの画像をピックアップ
#画像を扱えるようにする
Add-Type -AssemblyName System.Drawing
#参考値
$ABSOLUTERATIO = 0.5625 #16:9のアス比
$BAND = [math]::round($ABSOLUTERATIO/4,4)
$filepath = "C:\Workspace\picturetest\item"
$resultpath = "C:\Workspace\picturetest\Result"
$list = Get-ChildItem $filepath
#ファイルの抽出
$pickups = foreach($file in $list){
if(($file.Extension -eq ".jpg") -or ($file.Extension -eq ".png")){
#画像読み込み
$image = [System.Drawing.Image]::FromFile($file.FullName) #画像を読み込む
$width = $image.Width
$height = $image.Height
$image.Dispose()
#下ごしらえ
if($width -ge $height){
$ratio = [math]::round($height/$width,4) #画像のアス比
if(($ratio -ge $ABSOLUTERATIO-$BAND)){ # 許容アス比、これより細い画像は弾く
[PSCustomObject]@{
Fullname = $file.FullName
Length = $file.Length
Width = $width
Height = $height
}
}
}
}
}
$annoited_list = $pickups | Sort-Object -Descending Width,Height,Length | Select-Object -First 50
$annoited_list|Export-Csv $resultpath"\result.csv" #結果のCSV出力
#ファイルのコピー
foreach($movefile in $annoited_list){
Copy-Item -Path (($movefile).Fullname) -destination $resultpath
}
Excelizeの時の画像ノウハウで画像サイズだけ取得してリリース。
適宜条件で弾いてから、リストに入れて並べなおして上位をピックアップ。
アス比閾値を設定して条件に加えることで、クソ細い画像を排除している。
#出力
ディレクトリ: C:\Workspace\picturetest\Result
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 2018/09/07 8:21 5775 jpg_100.jpg
-a---- 2018/09/07 8:21 5379 jpg_11.jpg
-a---- 2018/09/07 8:21 4211 jpg_12.jpg
-a---- 2018/09/07 8:21 4947 jpg_15.jpg
-a---- 2018/09/07 8:21 3515 jpg_18.jpg
-a---- 2018/09/07 8:21 3187 jpg_19.jpg
-a---- 2018/09/07 8:21 5587 jpg_21.jpg
-a---- 2018/09/07 8:21 3059 jpg_39.jpg
-a---- 2018/09/07 8:21 4427 jpg_48.jpg
-a---- 2018/09/07 8:21 5747 jpg_5.jpg
-a---- 2018/09/07 8:21 3727 jpg_51.jpg
-a---- 2018/09/07 8:21 6099 jpg_56.jpg
-a---- 2018/09/07 8:21 2939 jpg_59.jpg
-a---- 2018/09/07 8:21 5659 jpg_62.jpg
-a---- 2018/09/07 8:21 4427 jpg_66.jpg
-a---- 2018/09/07 8:21 4527 jpg_71.jpg
-a---- 2018/09/07 8:21 4059 jpg_72.jpg
-a---- 2018/09/07 8:21 4147 jpg_74.jpg
-a---- 2018/09/07 8:21 3483 jpg_76.jpg
-a---- 2018/09/07 8:21 3507 jpg_78.jpg
-a---- 2018/09/07 8:21 2611 jpg_8.jpg
-a---- 2018/09/07 8:21 3003 jpg_80.jpg
-a---- 2018/09/07 8:21 3291 jpg_81.jpg
-a---- 2018/09/07 8:21 685 png_100.png
-a---- 2018/09/07 8:21 556 png_12.png
-a---- 2018/09/07 8:21 1161 png_19.png
-a---- 2018/09/07 8:21 757 png_2.png
-a---- 2018/09/07 8:21 641 png_20.png
-a---- 2018/09/07 8:21 1028 png_21.png
-a---- 2018/09/07 8:21 1064 png_26.png
-a---- 2018/09/07 8:21 906 png_27.png
-a---- 2018/09/07 8:21 1187 png_33.png
-a---- 2018/09/07 8:21 997 png_34.png
-a---- 2018/09/07 8:21 1217 png_39.png
-a---- 2018/09/07 8:21 645 png_4.png
-a---- 2018/09/07 8:21 705 png_42.png
-a---- 2018/09/07 8:21 898 png_5.png
-a---- 2018/09/07 8:21 1292 png_51.png
-a---- 2018/09/07 8:21 1527 png_52.png
-a---- 2018/09/07 8:21 1260 png_55.png
-a---- 2018/09/07 8:21 741 png_60.png
-a---- 2018/09/07 8:21 547 png_62.png
-a---- 2018/09/07 8:21 631 png_72.png
-a---- 2018/09/07 8:21 831 png_75.png
-a---- 2018/09/07 8:21 990 png_8.png
-a---- 2018/09/07 8:21 1247 png_84.png
-a---- 2018/09/07 8:21 901 png_85.png
-a---- 2018/09/07 8:21 610 png_93.png
-a---- 2018/09/07 8:21 646 png_95.png
-a---- 2018/09/07 8:21 971 png_99.png
-a---- 2018/09/07 8:24 3226 result.csv
#わからなかった部分
ここからは親元を参考に試したけどうまくいかなかった部分です。
ファイルのプロパティから画像サイズ自体は取得できそうだったんです。
#プロパティから対象を探し出す
$path = "C:\Workspace\item"
$list = ls $path *_1.*
# プロパティ取得の準備
# shellの機能を使えるようにする。多分GetDetailsOfのため。
$shell = New-Object -ComObject Shell.Application
# $folderに$pathのフォルダーオブジェクトを代入
$folder = $shell.NameSpace($path)
#ファイルの抽出
$object = $folder.ParseName($file.Name) #オプションを取得できるようにする
#プロパティの抽出
$pickups = foreach($file in $list){
$object = $folder.ParseName($file.Name) #オプションを取得できるようにする
Write-Host $file.Name #見やすくするため
@(1..200)|%{
$detail = $Folder.GetDetailsOf($object,$_)
#if($detail -ne ""){
Write-Host $_`t $detail`t $detail.GetType()
#}
}
Write-Host `r`n`r`n #見やすくするため
}
拡張子によってプロパティの内容と位置が変わらないか一応確認しています。
PS C:\Workspace> C:\Workspace\get-option.ps1
gif_1.gif
1 1.25 KB System.String
2 GIF ファイル System.String
3 2018/09/07 9:00 System.String
4 2018/09/07 9:00 System.String
5 2018/09/07 9:00 System.String
6 A System.String
7 System.String
8 オフラインで利用可能 System.String
9 イメージ System.String
10 TC\1501275 System.String
11 ピクチャ System.String
12 System.String
(中略)
168 System.String
169 8 System.String
170 96 dpi System.String
171 162 ピクセル System.String
172 96 dpi System.String
173 495 ピクセル System.String
174 System.String
175 System.String
176 System.String
177 System.String
178 System.String
179 System.String
180 System.String
181 System.String
182 いいえ System.String
183 System.String
184 System.String
185 item System.String
186 C:\Workspace\item System.String
187 item (C:\Workspace) System.String
188 System.String
189 C:\Workspace\item\gif_1.gif System.String
190 System.String
191 GIF ファイル System.String
192 System.String
(中略)
289 System.String
290 非共有 System.String
291 利用可能 System.String
292 System.String
(中略)
499 System.String
500 System.String
(後略)
結論からするとどのファイルでもでも171番と173番が幅と高さでした。
ファイルのプロパティは291番が最後っぽいけど他のファイルだと変わるかも。
PS C:\Workspace> $width = $folder.GetDetailsOf($object,171)
PS C:\Workspace> $width
156 ピクセル
PS C:\Workspace> $width.GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True String System.Object
まぁわかる。ピクセル入ってるもんな。
PS C:\Workspace> $a=$width.Split()[0]
PS C:\Workspace> $a
156
PS C:\Workspace> $a.GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True String System.Object
そうなるんか。数字だけなら整数型に戻るわけではないのね。
PS C:\Workspace> $b = [int]$a
値 "156" を型 "System.Int32" に変換できません。エラー: "入力文字列の形式が正しくありません。"
発生場所 行:1 文字:1
+ $b = [int]$a
+ ~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) []、RuntimeException
+ FullyQualifiedErrorId : InvalidCastFromStringToInteger
うーん…?
数字だけだけど直ってはくれんのか?
#おわりに
実環境では約30000枚の画像から1000枚ちょいをピックアップします。
その後スクリーンセーバーにふさわしくない画像達を手動で弾きました。
あとはresultフォルダをAmazonDriveと同期してFireTVStickで設定すればOKです。
なおピックアップの結果はほとんどがアニメのキャプになりました。
Duh...