Archive for the 'FineReader OCR Pro' Category

2015/12/04 FineReader OCR Proで指定文字列から言語指定オブジェクトを生成する

FineReader OCR Proで、言語指定文字列から実際に言語指定オブジェクトを生成するAppleScriptです。

FineReader OCR Proにはいろいろと不可解な仕様があり・・・とくに、言語を文字列で(”日本語”とか)指定すると、実際に指定するオブジェクト(Japaneseとか)を指定できそうな気配がするものの、実際に取得できるものはオブジェクトを文字列化したものであり、そのまま認識言語として指定できるものではありません。

そこで、テキストで指定した言語名からFineReader OCR Proのオブジェクトを生成するルーチンを作ってみました。

繰り返しになりますがFineReader OCR ProでAppleScriptから「C/C++」という言語は指定できません。

AppleScript名:FineReader OCR Proで指定文字列から言語指定オブジェクトを生成する
– Created 2015-12-04 by Takaaki Naganoya
– 2015 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation” –ASOCの機能は一切使っていないが、ASOC環境で問題なく実行できることを確認

set langList to {“C/C++”, “C++”, “Basic”, “Java”, “Fortran”, “COBOL”, “Pascal”}
set aList to {}

tell application id “com.abbyy.FineReaderPro”
  
  
repeat with i in langList
    set j to contents of i
    
set tmpObj to getLanguageObjFromString(j) of me
    
if tmpObj is not equal to “” then
      set the end of aList to tmpObj
    end if
  end repeat
  
  
return aList
  
–> {Basic, Java, Fortran, Cobol, Pascal}
end tell

on getLanguageObjFromString(aStr)
  tell application id “com.abbyy.FineReaderPro”
    set alangID to get language id from language name aStr –この命令が使いものにならない。オブジェクトではなく文字列を返してくる
    
if alangID = missing value then return “”
    
    
set aScript to “tell application id \”com.abbyy.FineReaderPro\” to “ & alangID
    
    
try
      set aRes to run script aScript
    on error
      return “”
    end try
    
    
return aRes
  end tell
end getLanguageObjFromString

★Click Here to Open This Script 

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/12/02 Photosで選択中の写真の撮影場所が指定地点から50メートル以内の場合には書き出してFineReader OCR ProでOCR処理

多言語OCRソフト「FineReader OCR Pro」を用いて、現代のAppleScriptに備わっているさまざまな機能を利用した処理を行ってみました。

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

img_2980.jpg

これまでは、リプレイのための情報をゲーセンの端末で表示させて、それをiPhoneで写真に撮り、自宅で手入力していたのですが・・・これが、ものすごく不毛な作業なので、手入力しなくてもいいようにAppleScriptを書いてみました。

gamecity.jpg

step1:写真.app(Photos.app)の撮影場所の取得

まず、ゲーセンで撮影した写真かどうか、撮影時に記録されているGPS情報から判定します。
Photos上で選択中の写真からの緯度/経度情報の取得はとくに問題はありません。ふつーにできます(ただし、OS X 10.11上の最新版が必要。OS X 10.10上のものは機能が不完全で使用不可)。Photos.appで選択中の写真のファイル名やファイルパスを求めることはできませんが、それは指定の写真がローカルにあるのかCloudにあるのかわからないためで、実際の写真にアクセスするためにはいったんexportする必要があるというのがPhotos.appの流儀です。

fine1.png

2点間の距離を求める処理も、CoreLocationの機能を用いて余裕でできます。

step2:写真のフィルター処理

写真を書き出してそのままOCR処理・・・したかったのですが、そのままだとFineReader OCR Proが「OCR処理できない」と言ってきたので(白地に黒っぽい文字の構成でないと認識しないらしい)、CIFilterを用いて階調反転を行い、その処理結果をFineReader OCR Proに渡しています。画像の編集機能はFineReader OCR Proに内蔵されており階調反転も行えるのですが、この機能はAppleScriptから呼び出せません。それでも、AppleScript単体で画像処理できるので問題ありません。Photoshopを併用する必要もありません。

step3:OCR処理

以前に作成した文字認識Scriptを組み合わせてすぐにOCR処理できるか・・・と、思いきや、なんと以前のバージョンのScriptだとそのまま実行してくれませんでした。バージョンアップ時にAppleScript用語辞書が変更になったらしく、そのままだと構文確認(コンパイル)をパスしません。

最初に画像を別途オープンする必要があるんだな、とあたりをつけて・・・画像をopenさせてみたら大丈夫でした(ここちょっと、難易度高いです)。

fine2.png

OCR処理する場合に、今回は日本語の文字列が不要だったので、認識言語に「English」のみを指定してみました。ログ表示させたまま実行すると文字化けした文字が表示されますが、これで正しい動作です。

kizuna.png

step4:認識結果のテキストファイルへの出力

認識結果をテキストファイルに出力させているのですが、FineReader OCR ProがMac App Store版であるため(以前にしらべたお試し版と異なり)Sandbox化されています。このため、出力先が極度に限定されており、アプリケーションに出力フォルダを聞いて、そこに指定ファイル名のテキストがあるものと仮定して処理しています。

その後、ごにょごにょと文字列の抽出処理を行って、希望のリプレイIDを取得できました。ここまでくれば、リプレイムービーをYouTubeからダウンロードするのも余裕です(リプレイムービー検索ページのFormにIDを突っ込んでYouTubeのムービーのURLを取得する未公開ルーチンが存在しているため)。

fine3.png

こういうレベルの処理がAppleScriptでさっくり書けるようになったことは、素直に喜びたいと思います。

FineReader OCR Proについて

万能無敵のFineReader OCR Proですが、いただけない点もあります。OCR処理したあとの画像をクローズしたり捨てるためのAppleScriptの命令が存在せず、複数の画像を連続認識するような場合にはこれでは困ります(processをkillするしかなさそう)。メーカーにフィードバックしておかないと、、、、(しました)。

cannotclose.png

また、できればFineReader OCR Pro内の階調反転機能は呼び出せたほうがよいものと思われます。今回はあらかじめ画像の下地が濃い色(Whiteではない)だとわかっていたので決めうちで階調反転させましたが、ここの判断まで自動化したいのであれば、Photoshopが持っているような明度別ヒストグラムの集計処理が利用できたほうがよいでしょう(認識エラーが出たら階調反転させる、という場当たり的な処理でもOKといえばOK)。

今回のScriptでは「ゲームシティ板橋店」からの距離を計算しましたが、全国の「戦場の絆」設置ゲームセンターの住所はわかっているので、これらをすべてデータで持って、緯度経度情報をすべて照合しても、たいした時間はかからないと思われます(後日、これを行ってGoogle API経由で住所ジオコーダーを呼び出して、3箇所だけどうしても緯度・経度情報に変換できない住所がありました。田んぼのまんなかに作ったショッピングセンター的なもので、最近作られた地名のもよう。意外と苦労しました、、、)。

AppleScript名:Photosで選択中の写真が指定場所から50メートル以内の場合には書き出してFineReader OCR Proで処理
– Created 2015-12-02 by Takaaki Naganoya –v1.1.1
– 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} –認識ターゲット言語
  
–Caution: this command is executed asynchronously
  
–Caution: export command was changed in v12.1.4
  
  
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”}

–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/12/02 多言語OCR「FineReader OCR Pro」がAppStoreで40% OFF!

さんざん人前でデモをして他人にすすめまくっているMac用のAppleScript対応OCRソフトウェア「FineReader OCR Pro」が、Mac App Storeで40% Offの8,400円で販売中です(2015/12/02 本日まで)。

sales.png

けっこう頻繁にセール価格を設定するようなので、見るたびに価格が変わっていますが、この価格ならお買い得です(日付の書き方が英語圏の書き方のまんまなので、いろいろ誤解してました)。

finereaderocr.png

Mac App Store版のFineReaderを購入して気づいたことは・・・

・Downloadお試し版ではアプリケーション名が「FineReader」だったが、Mac App Store版では「FineReader OCR Pro」になっている(tell文を書き換える必要がある)

・現時点でのバージョン番号はv.12.1.4

・AppleScriptのコマンド「is sandboxed」で確認すると「true」が返る(DL版はfalseが返ってきていた)

finereader_sandbox.png

・文字認識を行うコマンドのパラメータ構成が変更になった(画像ファイルのオープンを別途行っておく必要アリ)ため、以前のバージョン用のAppleScriptがそのままでは構文確認(コンパイル)をパスしない。書き換える必要がある

・Mac App Store版ではSandbox化されており、Scriptから結果出力フォルダを指定しても無視され、出力フォルダに出力される。出力フォルダを求める命令が用意されており、is sandboxがtrueの場合には、そのフォルダを参照のこと

AppleScript名:FineReaderで出力フォルダを取得
tell application id “com.abbyy.FineReaderPro”
  set outDIr to (get output dir) as text
  
–> “Macintosh HD:Users:me:Library:Group Containers:XXXXXXXXXX.com.abbyy.FineReader12:tempGroupDir:scriptDir:”
end tell

★Click Here to Open This Script 

2015/09/29 多国語OCR「FineReader OCR Pro」をAppleScriptでコントロール

finereader_ocr_pro.jpgMac App Storeで見つけた多国語OCRソフトウェア「FineReader OCR Pro」(バージョン12.1.3)がAppleScriptに対応していたので、いろいろ試してみました(以下、FineReaderと省略)。

FineReaderは英語、日本語をはじめ185もの自然言語に4つの人工言語(エスペラント語とか)、8つの公式言語(簡易化学式とか)などなど、さまざまな言語に対応しており、日本語の認識率もかなりのものです(こんなに認識率の高いOCRソフトは久しぶり)。価格も期間限定で9,800円と非常にリーズナブルです。先日、オープンソースのOCRソフト「tesseract」を試して「こんなもんなのかー」と打ちのめされたばかりなので、なおさらFineReader OCR Proは好印象です。

185言語と書きましたが、単語チェック用の辞書を備えている39の言語(古語や重複分をのぞく)がターゲットといえるでしょう。

開発元の「ABBYY USA Software House Inc.」のサイトからお試し版をダウンロードできる(メールアドレスなどの登録が必要)ので、そちらで試してみました。試用版は30日間あるいは100ページの文字認識を行うと期限満了となるようです。

freader1.png

そんなFineReaderは、なんとAppleScript対応。しかも、AppleScript用語辞書の内容までローカライズされています(内容は各言語に合わせて動的に生成しているもよう)。久しぶりに日本語で書かれたAppleScript用語辞書を見ました。

freader2.png

実に気合いの入ったFinerReader、実際にScriptingを試してみるとどんなもんでしょうか?

まずは、認識言語関係の情報を調べてみました。

AppleScript名:FineReaderで言語情報を取得
tell application “FineReader”
  set anID to get language id from language name “日本語”
  
–> “Japanese”
  
  
set aName to get language name from id anID
  
–> “日本語”
  
  
set aBool to has dictionary support from language with id anID
  
–> true
  
  
set aType to get ocr language group with key anID
  
–> “自然言語”
  
end tell

★Click Here to Open This Script 

日本語のIDは”Japanese”だよ、と親切に教えてくれました。また、日本語が自然言語に分類される言語だということも教えてくれます(C++、Basic、Cobolとかのプログラミング言語も認識言語にリストアップされているが、Objective-CはないしAppleScriptもない)。ちなみに、FineReader OCR Proいわく、C++は「公式言語」という区分のようです(プログラミング言語じゃないんだ、、、)。

ためしに、設定内容を取得してみたところ・・・

AppleScript名:FineReaderの設定内容を取得
tell application “FineReader”
  get preferences
end tell
–> {exportPdfImageQuality:balanced quality, exportPptXKeepPictures:true, exportHtmlImageQuality:balanced quality, exportPdfPrintDocumentSequrity:false, exportFb2ImageQuality:balanced quality, exportPdfCopyDocumentSequrity:false, exportPdfOpenDocumentSequrity:false, exportHtmlTextEncoding:utf8, exportOdtLayout:as editable copy, exportEpubUseFirstPageAsBookCover:true, exportRtfKeepLineNumbers:true, exportEpubKeepPictures:true, exportRtfLayout:as editable copy, exportHtmlUseCSS:true, exportEpubKeywords:{}, exportHtmlTableContext:autocontext, exportOdtHighlightUncertainCharacter:false, exportHtmlCreateFileBasedOnTableContext:false, exportRtfKeepPictures:true, exportCsvInsertPageBreakCharacterAsPageSeparator:false, exportRtfHighlightUncertainCharacter:false, exportOdtKeepPictures:true, exportDocXKeepLineBreaksAndHyphens:false, exportHtmlLayout:as formatted text, exportPdfExportMode:text under image, exportDocXIncreasePaperSizeFitToContent:true, exportOdtKeepLineBreaksAndHyphens:false, exportPdfKeepPageNumbersHeadersAndFooters:true, exportXlsXImageQuality:1, exportPdfCopyDocumentSequrityPassword:”", exportPdfUseMRC:false, exportHtmlKeepTextAndBackgroundColor:false, exportPptXKeepPageNumbersHeadersAndFooters:true, exportPdfPaperMargins:”1.180555, 0.7881944, 0,59027777, 0.7881944″, exportHtmlKeepPictures:true, exportPdfKeepTextAndBackgroundColor:true, exportFb2UseFirstPageAsBookCover:true, exportDocXKeepPageBreaks:true, exportTxtUseBlankLineParagraphSeparator:false, exportEpubBookTitle:”", exportTxtKeepLineBreaksAndHyphens:true, preferencesRecognitionLanguages:”Japanese+English”, exportTxtInsertPageBreakCharacter:false, exportXlsXKeepPictures:true, exportPdfOpenDocumentSequrityPassword:”", exportEpubAnnotation:”", exportTxtCodePage:1251, exportCsvTextCodePage:1251, exportXlsXKeepPageNumbersHeadersAndFooters:true, exportHtmlKeepPageNumbersHeadersAndFooters:true, exportDocXImageQuality:balanced quality, exportHtmlKeepTextLineBreaksAndHyphens:false, exportCsvFieldSeparator:semicolon, exportDocXKeepLineNumbers:true, exportEpubAuthor:”", exportPdfEmbedFonts:true, exportRtfImageQuality:balanced quality, exportImageFormat:2, exportFb2BookTitle:”", exportXlsXConvertNumericalValuesToNumbers:false, exportDocXHighlightUncertainCharacter:false, exportFb2PreserveFontsAndFontsSize:false, exportOdtImageQuality:balanced quality, exportOdtKeepTextAndBackgroundColor:true, exportPdfEnabledTaggedPDF:true, exportDocXPaperMargins:”1.180555, 0.7881944, 0,59027777, 0.7881944″, exportRtfKeepPageNumbersHeadersAndFooters:true, exportTxtTextEncoding:utf8, exportDocXKeepPictures:true, exportPdfKeepPictures:true, exportFormat:to plain text, exportFb2KeepPictures:true, exportImageCompressionType:2, exportRtfKeepLineBreaksAndHyphens:false, exportPptXTextLineBreaksAndHyphens:false, exportTxtKeepPageNumbersHeadersAndFooters:true, exportEpubPreserveFontsAndFontsSize:false, exportCsvTextEncoding:utf8, exportTxtLayout:as plain text, exitAfterExport:false, exportFb2Keywords:{}, exportRtfPaperMargins:”1.180555, 0.7881944, 0,59027777, 0.7881944″, exportDocXLayout:as editable copy, exportSaveOption:0, exportImageQuality:50, exportXlsXIgnoreTextOutsideTables:false, exportDocXPaperSize:automatic, exportEpubLayout:as formatted text, exportPptXImageQuality:balanced quality, exportImageColorMode:0, exportPdfMakePdfACompliant:false, exportOdtPaperMargins:”1.180555, 0.7881944, 0,59027777, 0.7881944″, exportPdfCreateOutline:false, exportRtfIncreasePaperSizeFitToContent:true, exportRtfKeepTextAndBackgroundColor:true, exportEpubEmbedFonts:false, exportOdtPaperSize:automatic, exportOdtKeepPageNumbersHeadersAndFooters:true, exportDocXKeepTextAndBackgroundColor:true, exportSaveMultyPageImage:false, exportFb2Author:”", exportRtfPaperSize:automatic, exportFb2Annotation:”", exportEpubImageQuality:balanced quality, exportPdfPaperSize:automatic, exportRtfKeepPageBreaks:true, exportOdtIncreasePaperSizeFitToContent:true, exportOpenAfterExport:true, exportFb2Layout:as formatted text, exportPptXWrapText:false, exportOdtKeepPageBreaks:true, exportOdtKeepLineNumbers:true, exportHtmlCreateNavigation:true, exportFb2EmbedFonts:false, exportCsvIgnoreTextOutsideTables:0, exportDocXKeepPageNumbersHeadersAndFooters:true, preferencesRecognitionLanguages:”Japanese+English”}

★Click Here to Open This Script 

大量の情報が出てきました。ただし、Read Onlyです(取得コマンドはあっても、設定コマンドがない)。しかも、デバッグ情報っぽい内容であり、誰が何のためにこの情報を使うんだろうと不思議に思いました(せめて、設定できれば ^ー^;;)。

不思議なことに、サンドボックスで実行中かどうかの確認が行えます。一応、Activity Monitorで調べてみるとサンドボックス対応ではありません。

sandbox.png

AppleScript名:FineReaderがSandboxで実行中かを取得
tell application “FineReader”
  set aRes to (is sandboxed)
  
–> false
end tell

★Click Here to Open This Script 

AppleScriptからも属性値を確認してみましたが、やはりSandboxedな状態ではないようです(将来的にそうなる、ということかも?)。

で、指定の画像を文字認識させるべく試してみたのですが・・・なかなか苦労しました(30分ぐらい悩んでしまいました)。

苦労ポイント1:言語指定の方法がわかりにくい

冒頭のAppleScriptで、”日本語”のIDを調べてみたら”Japanese”だといわれたので、パラメータに”Japanese”と指定してみましたが・・・何も認識されませんでした。

いろいろ試してみたところ、Japaneseという予約語があって(おいおいー!!)、そちらで指定するようになっているようです。じゃあ、IDを調べる機能が返してきた文字列はなんなんだ?!(^ー^;;

ほかにも、対象言語が1つでもリストで指定する必要があったりと、いろいろ楽しませてくれます。

苦労ポイント2:認識コマンドが非同期実行

さらに、認識コマンドを実行すると、すぐにAppleScriptが終了してしまいました。認識コマンドが非同期実行されるらしく、OCR処理が終わったかどうかはステータスを監視しないといけないようです。かなり特殊な挙動です。

Mac AppStoreのレビューを読むと、ページ数のあるPDFなどをOCR処理するとけっこうな時間待たされるようなので、そのあたりへの配慮(タイムアウトするよりはいいでしょ? という)なのかもしれません。

Scriptからコントロールできるようになるまで、少々苦労させられましたが、認識率自体は非常に高く、実用性は高いと思われました。

AppleScript名:FineReaderで指定画像を文字認識してデスクトップにテキスト出力
set aFile to (choose file) as string
set outPath to ((path to desktop) as text) & (do shell script “uuidgen”) & “.txt”

tell application “FineReader”
  
  
–Check Ready
  
set getReady to (is finereader controller active)
  
if getReady = false then return
  
  
set idList to {Japanese, English} –認識ターゲット言語
  
–Caution: this command is executed asynchronously
  
export to txt file outPath from file aFile 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
  
end tell

★Click Here to Open This Script 

Keynote書類をキャプチャした画像を認識させてみましたが、そのぐらいだと100%近い認識率で、書類に貼り付けた画像の内容まで認識してしまうほど。本アプリのエンジン部分は非常に高性能です。

ただ、AppleScript用語辞書の内容とかはもうちょっと、実際にAppleScriptを書いている人間からのフィードバックを取り入れたほうがよいと思われます。本ソフトウェア自体は、ひじょうにおすすめです。