Archive for the 'Photos(写真)' Category

2015/12/04 Photosで選択中の写真の撮影場所が指定地点から50メートル以内の場合には書き出してFineReader OCR ProでOCR処理 v2

Photos(日本語名:写真.app)で選択中の写真から緯度/経度情報を取得して、その撮影場所が指定場所から50メートル以内の範囲にあれば、画像書き出しを行って、FineReader OCR Proで画像の文字認識を行い、必要な情報(「戦場の絆」のリプレイID)を取得するAppleScriptの改良版です。

ゲームセンターで「戦場の絆」をプレイして、YouTubeに自動であがっているリプレイムービーにアクセスするために発行される「リプレイID」。

ocr3.png

これをiPhoneで写真に撮って自宅で検索ページのフォームに手入力して、リプレイムービーを見ていたわけですが、OCRをAppleScriptから呼び出すことで、手入力の手間をなくすことを目的としています。また、行きつけのゲームセンター「ではない」場所で撮影した写真を認識させることを防ぐために、写真からGPS情報を取得して指定場所との距離を計算して「50メートル以内」であれば処理するようにしています。

前バージョンでは、文字認識内容の一部に誤認識がありました。十分な文字サイズで撮影しているにもかかわらず、FineReader OCR Proの文字認識エンジンの性能を考えるとありえない誤認識でした(”1″と”t”を間違えていた)。

この認識ターゲットは「英数字から構成されるものの英単語そのものではない」ため、認識ターゲット言語が「English」では、英語の辞書によるスペルチェックや「英語の性格上、ありえない文字の並び」は排除されているものと考え、FineReader OCR Proがサポートしている「プログラミング言語」(画面上では、翻訳ミスで「公式言語」になっていますが、、、、)を指定すればよいのではないかと考えました。

ocr1.png

そこで、Basic、Java、Fortran、Cobol、Pascalの5つを指定してみたところ、今度はバッチリ間違いなく認識しました。

ocr2.png

ちなみに、FineReader OCR Proでは「C++」もサポートしているらしいのですが、C++という予約語があったとしても、そんなもん構文チェックでエラーになるに決まっています。

せめて「Cplusplus」といった予約語だったら指定できるはずですが・・・・

AppleScript名:Photosで選択中の写真が指定場所から50メートル以内の場合には書き出してFineReader OCR Proで処理 v2.0
– Created 2015-12-04 by Takaaki Naganoya –v2.0
– getDistanceBetweenTwoPlaces : Created 2015-03-03 by Shane Stanley
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
use framework “CoreLocation”
use framework “QuartzCore”

set targPlace to {35.745769, 139.675565} –Game City Itabashi
set bLoc to getSelectionOnPhotos() of me –Get Location From Photo
set aDist to getDistanceBetweenTwoPlaces(targPlace, bLoc) of me

–指定地点から50メートル以内の距離で撮影された写真であれば、Exportして後続の処理を行う
if aDist is equal to false or aDist > 50 then return false

–選択中の写真のうち最初のものだけExport
set targPhotoAlias to exportSelectedPhotoOnPhotos() of me

–実験に用いた写真はそのままではOCR処理できなかったので、手っ取り早く階調反転を行う
set invertRes to convAsFilteredJPEG(targPhotoAlias, “CIColorInvert”) of me
if invertRes = false then
  display dialog “Error in CIImage” with title “Error” buttons {“OK”} default button 1 with icon 2
  
return
end if
set invImage to (POSIX file invertRes) as alias

set outFileName to (current application’s NSUUID’s UUID()’s UUIDString() as text) & “.txt”
set outPath to ((path to desktop) as text) & outFileName –sandbox環境ではパスは無視される

tell application id “com.abbyy.FineReaderPro”
  
  
–Check Ready
  
set getReady to (is finereader controller active)
  
if getReady = false then return
  
  
–set idList to {English} –英語だとスペルチェックされて、”1″と”t”を誤認識するため英語の指定をやめた
  
–Caution: this command is executed asynchronously
  
–Caution: export command was changed in v12.1.4
  
  
set idList to {Basic, Java, Fortran, Cobol, Pascal} –認識ターゲット言語(C++の予約語はあるようだが、指定できないよ!)
  
open invImage – In this version ,we have to open image, at first.
  
export to txt outPath ocr languages enum idList retain layout (as plain text) encoding (utf8)
  
  
–Wait for finish
  
repeat 30 times
    set curStat to (is busy)
    
if curStat = false then exit repeat
    
delay 1
  end repeat
  
  
–sandbox環境(Mac App Store版)の場合にはファイル出力先を別途取得
  
set sandRes to (is sandboxed)
  
if sandRes = true then
    set outDir to (get output dir) as text
    
set outPath to (outDir & outFileName) as text
  end if
  
end tell

–OCR処理した結果のテキストを読み込む
tell current application
  set textRes to read file outPath
end tell

–数字ではじまる行のみを抽出して、リプレイIDを取得
set textList to paragraphs of textRes
set outList to {}
repeat with i in textList
  set j to contents of i
  
if length of j > 8 then
    set firstChar to first character of j
    
set nRes to chkNumeric(firstChar) of me
    
if nRes = true then
      set tmp1 to text 2 thru -1 of j –最初の数字を除去
      
set tmp2 to returnNumberAndAlphabetCharsOnly(tmp1) of me
      
if length of tmp2 8 then
        set tmp3 to text 1 thru 8 of tmp2
        
set the end of outList to tmp3
      end if
    end if
  end if
end repeat

outList
–> {”4f73vg1v”, “v3v32zt3″, “yk1z371x”, “52yzvn11″, “k1ftfvvg”}–Previous Version (3rd ID is wrong)
–> {”4f73vg1v”, “v3v32zt3″, “yk1z37tx”, “52yzvn11″, “k1ftfvvg”}– This Version (Perfect!!!!)

–Photosで選択中の写真の1枚目(複数時には無視)から緯度、経度情報を取得する
on getSelectionOnPhotos()
  tell application “Photos”
    set aa to selection
    
if aa = {} or aa = missing value then return false
    
set a to first item of aa
    
set aProp to properties of a
    
    
set aLoc to location of aProp
    
return aLoc
  end tell
end getSelectionOnPhotos

–2点間の距離を計算する
on getDistanceBetweenTwoPlaces(aPlaceLoc, bPlaceLoc)
  try
    set {aLat, aLong} to aPlaceLoc
    
set {bLat, bLong} to bPlaceLoc
  on error
    return false
  end try
  
  
set aPlace to current application’s CLLocation’s alloc()’s initWithLatitude:aLat longitude:aLong
  
set bPlace to current application’s CLLocation’s alloc()’s initWithLatitude:bLat longitude:bLong
  
set distanceInMetres to aPlace’s distanceFromLocation:bPlace
  
return (distanceInMetres as real)
end getDistanceBetweenTwoPlaces

–Photos上で選択中の写真をTemporary Folderに掘ったフォルダに書き出して、そのalias情報を返す
on exportSelectedPhotoOnPhotos()
  set dtPath to (path to temporary items) as text
  
set aUUID to current application’s NSUUID’s UUID()’s UUIDString() as text
  
  
set dirPath to ((POSIX path of dtPath) & aUUID)
  
set fileManager to current application’s NSFileManager’s defaultManager()
  
set aRes to (fileManager’s createDirectoryAtPath:dirPath withIntermediateDirectories:true attributes:(missing value) |error|:(reference))
  
set dtPath to dtPath & aUUID
  
  
tell application “Photos”
    set a to selection
    
if a = {} then return
    
set aRes to (export a to file dtPath)
  end tell
  
  
tell application “Finder”
    tell folder dtPath
      set fList to (every file) as alias list
    end tell
  end tell
  
  
if fList = {} then return false
  
return first item of fList
end exportSelectedPhotoOnPhotos

–CIFilterをかけたJPEG画像を生成
–参照:http://ashplanning.blogspot.jp/ のうちのどこか
on convAsFilteredJPEG(aPath, aFilterName)
  
  
–aliasをURL(input)とPOSIX path(output) に変換
  
set aURL to (current application’s |NSURL|’s fileURLWithPath:(POSIX path of aPath)) –Input
  
set aPOSIX to (POSIX path of aPath) & “_” & aFilterName & “.jpg” –Output
  
  
–CIImageを生成
  
set aCIImage to current application’s CIImage’s alloc()’s initWithContentsOfURL:aURL
  
  
– CIFilter をフィルタの名前で生成
  
set aFilter to current application’s CIFilter’s filterWithName:aFilterName
  
aFilter’s setDefaults() –各フィルタのパラメータはデフォルト
  
  
–Filterを実行
  
aFilter’s setValue:aCIImage forKey:“inputImage”
  
set aOutImage to aFilter’s valueForKey:“outputImage”
  
  
– NSBitmapImageRep を CIImage から生成
  
set aRep to current application’s NSBitmapImageRep’s alloc()’s initWithCIImage:aOutImage
  
  
– NSBitmapImageRep から JPEG データを取得
  
set jpegData to aRep’s representationUsingType:(current application’s NSJPEGFileType) |properties|:(missing value)
  
  
– ファイルに保存
  
set fsRes to jpegData’s writeToFile:aPOSIX atomically:true
  
if (fsRes as boolean) = false then return false –失敗した場合
  
return aPOSIX –成功した場合
  
end convAsFilteredJPEG

–数字のみかを調べて返す
on chkNumeric(checkString)
  set digitCharSet to current application’s NSCharacterSet’s characterSetWithCharactersInString:“0123456789″
  
set ret to my chkCompareString:checkString baseString:digitCharSet
  
return ret as boolean
end chkNumeric

on chkCompareString:checkString baseString:baseString
  set aScanner to current application’s NSScanner’s localizedScannerWithString:checkString
  
aScanner’s setCharactersToBeSkipped:(missing value)
  
aScanner’s scanCharactersFromSet:baseString intoString:(missing value)
  
return (aScanner’s isAtEnd()) as boolean
end chkCompareString:baseString:

–文字置換
on repChar(aStr, targStr, repStr)
  set aString to current application’s NSString’s stringWithString:aStr
  
set bString to aString’s stringByReplacingOccurrencesOfString:targStr withString:repStr
  
return bString as text
end repChar

–アルファベットと数字以外を削除して返す
on returnNumberAndAlphabetCharsOnly(aStr)
  set anNSString to current application’s NSString’s stringWithString:aStr
  
set anNSString to anNSString’s stringByReplacingOccurrencesOfString:“[^0-9A-Za-z]” withString:“” options:(current application’s NSRegularExpressionSearch) range:{0, anNSString’s |length|()}
  
return anNSString as text
end returnNumberAndAlphabetCharsOnly

★Click Here to Open This Script 

2015/04/09 写真.app(Photos.app)のScript対応機能は未完成

OS X 10.10.3がリリースされ、山のように報告していたバグの一部が修正され・・・Message経由での画面共有あたりはまともになりました。

スタイル付きテキストのコピー&ペーストでダブルクォート2個が1個に化けるとか、ファイル共有しようとしてもホスト名が勝手にMac(26)とかの変な名前になってPeer To Peerのファイル共有ができないといった深刻なバグは手付かずです、、、(ーー;

photosicon.pngそんなOS X 10.10.3の新アプリ「写真.app」(Photos.app)バージョン1.0。

ph1.jpg
▲OS X 10.10.3に新登場の「写真.app」(Photos.app)/ 各人物の顔へのモザイクは自作アプリ「Photo Face Masker」にて一括実行(顔認識しなかった若干名は手作業)

β版の頃からAppleScript用語辞書がついていてAppleScriptから機能を呼び出せることは確認していたのですが、いかんせん未完成のβ版なので「見ても仕方がない」レベルだと思っていました。

ほぼ初見のPhotos.appのAppleScript対応機能の充実度はどんなもんでしょうか?

Applicationのpropertiesがとれる

AppleScript名:Photosのプロパティを取得
tell application “Photos”
  properties
  
–> {recently deleted album:recently deleted album id “trashAlbum” of application “Photos”, last import album:container id “lastImportAlbum” of application “Photos”, selection:{}, name:”Photos”, frontmost:false, favorites album:container id “favoritesAlbum” of application “Photos”, version:”1.0″, slideshow running:false, class:application}
  
end tell

★Click Here to Open This Script 

selectionがapplicationの直下にありますね。selectionは機能しています(詳細は後述)。

selectionの内容から、写真1枚1枚は「media item」という名称でアクセスされることがわかります。ただし、media itemに直接アクセスしようとするとエラーに(汗)

アルバムへのアクセスも可能

アルバムはcontainerというオブジェクトで表現されています。container “フラグ付き”といった名称でアクセスすることも可能です。

AppleScript名:Photosで全アルバム名を取得
tell application “Photos”
  set aList to name of every container –Every Album Name
  
–> {”フラグ付き”, “iPhoto イベント”, “MobileMe から”, “ともぞうさん2010″, “あいかちゃん2010″, “かいちゃん2010″, “けいこ2010″, “ムービー”, “こうじ2010″, “名称未設定アルバム 2″, “iPhone4″, “あいかちゃん2011″, “大きすぎ”, “うどん”,……….}
end tell

★Click Here to Open This Script 

AppleScript名:Photosで指定のアルバムにアクセス
tell application “Photos”
  tell container “フラグ付き” –Album
    properties
    
–> {id:”yFpznZXFQo2IyXJqLjlAtQ”, class:album, name:”フラグ付き”, parent:missing value}
    
    
set aList to every media item
    
–> {media item id “Alt+61wVTkGVnhSsyfrayg” of container id “yFpznZXFQo2IyXJqLjlAtQ” of application “Photos”, media item id “pWF6W56sRXaswwvao6UJpw” of container id “yFpznZXFQo2IyXJqLjlAtQ” of application “Photos”,………….}
  end tell
end tell

★Click Here to Open This Script 

AppleScript名:Photosでアルバム内のmedia item一覧を取得
tell application “Photos”
  tell container “フラグ付き”
    set aList to every media item
  end tell
end tell

–> {media item id “Alt+61wVTkGVnhSsyfrayg” of container id “yFpznZXFQo2IyXJqLjlAtQ” of application “Photos”, media item id “pWF6W56sRXaswwvao6UJpw” of container id “yFpznZXFQo2IyXJqLjlAtQ” of application “Photos”……….}

★Click Here to Open This Script 

「人々」の各人物を選択してselectionを取得すると、media itemのlistが返ってきます。containerとかfolderではないようです。

「最後の読み込み」アルバムにアクセスして、その中に入っているmedia itemへのpropertiesは取得できます。selectionから取得した各media itemのpropertiesはエラーになるのに、container内のmedia itemにはpropertiesの取得が効きます。このあたりで、まだまだ未完成な印象を受けます(ーー;;

AppleScript名:Photosで「最後に読み込み」アルバム内のmedia itemのプロパティにアクセス
tell application “Photos”
  set aProp to properties
  
set aLast to last import album of aProp
  
  
tell aLast
    set aPhotos to every media item
    
repeat with i in aPhotos
      
      
properties of i
      
–> {favorite:false, id:”2np1X29yQrOm0lV7xlOFBA”, class:media item, filename:”DSCF3559.JPG”, width:1920, location:{missing value, missing value}, keywords:missing value, date:date “2010年1月1日金曜日 0:06:55″, height:1080, description:missing value, altitude:missing value, name:missing value}
      
    end repeat
  end tell
  
end tell

★Click Here to Open This Script 

AppleScript名:Photosで直接selection内のmedia itemのpropertiesを取得するとエラーに
tell application “Photos”
  set aProp to properties
  
  
set aSel to selection of aProp
  
–> {media item id “5hwoENYJSP6JRutP8n9Miw” of application “Photos”}
  
  
repeat with i in aSel
    set j to contents of i
    
set aCon to filename of j
    
–> error “Photos でエラーが起きました:AppleEvent のハンドラで誤りが起きました。” number -10000
  end repeat
end tell

★Click Here to Open This Script 

全体の印象は悪くないが、未完成であることは事実

KeynoteがiOS版と足並みをそろえるために機能ダウンしてフォントパネルが使えないとかいろいろ不満な点が出て「残念な出来」になってしまったのにくらべ、iPhotoからの機能ダウンはそれほど感じられず、「悪くない」印象です。

AppleScript対応機能については、まだ触りだしたばかりですが……selectionからmedia itemにアクセスできないというのは、おっとっと、という感じです。「人々」と連絡先.app(Contacts.app)との連携なども期待していたのですが、そこまでも行っていない感じです。

Keynote 6.xのAppleScript対応機能の残念さにくらべれば、まだ望みがあるように見えます。

ちなみにPhotos.appのsdefファイル(Script用語辞書書類)は、読みやすいように空行が入れてあり、きちんとメンテナンスするぞという(生きているという)印象を受けます。改行を全部とっぱらって、メンテナンスもなにものぞめないような「死んだ」辞書ではない、という印象を受けます。

ph2.png

ありもののアプリの再構築についてはiPhoto→Photosで経験を積んで、次は本丸の「iTunes」を作り直したいといったところでしょうか、アップル的には。