Scene Text Eraser を読んだのでメモ

情景内文字のテキスト消去に関して興味があるのでメモ

論文詳細

T. Nakamura, A. Zhu, K. Yanai, and S. Uchida. Scene text eraser. In The 14th International Conference on Document Analysis and Recognition, pages 2–45, 2017.

どのような論文か?

情景内画像含まれる個人的な情報を含む住所や電話番号などのテキストを,テキスト行検出を用いないCNNベース手法で消去する研究.
テキスト消去後の文字検出の精度(Recall・Precision・F-Score)が大幅に低下した.

この論文のすごいと感じたところ

情景内画像に含まれる個人的な情報(住所や電話番号)は,悪用されることも多いので消去することが求められている.
通常テキストの消去では,テキスト行の検出 → 消去という二つのステップで消去をおこなう必要がある.

コンピュータビジョンにおける情景内画像に対するテキスト行検出の処理では,CCA(connected component analysis) や sliding windowを用いた手法が用いられてきた*1,*2,*3,*4

しかし,*5で定義されるように古典的な手法ではうまくいかないことも多く,まだまだ発展途上と言える.さらに,ガウシアンブラーなどを用いたぼかし処理などは,精度が特定のストローク・フォントに依存してしまうことから用いることが難しい.

この研究では行検出の処理をおこなわずに,入力画像(情景画像)から文字を消去したInpating画像を生成するCNNベースの手法を提案している.

DNNの構成

構成は,四層のConvolution層とDeconvolution層で構成されている.

f:id:dr_takuya:20181015140512p:plain

Convolution層は画像の特徴を掴むために,Deconvolution層は画像を復元させるために用いられている.
この研究の肝は,Skip Connection*6と呼ばれる層の計算をサボるために使われている技術を転用していることである.

ConvolutionとDeconvolutionの計算を線形で独立におこなってしまうと,Covolutionでは画像の縮小,Deconvolutionでは画像の膨張を繰り返し,画像の品質が劣化してしまう問題がある.

Skip Connectionでは,画像の縮小を行う前に特徴マップにオブジェクトの位置情報などの情報を足し合わせ,Deconvolution層でその情報を復元することにより,画像に品質を劣化させずにシーンテキストの消去をおこなうことができる(下図).

f:id:dr_takuya:20181015144700p:plain

CNNの学習では,元画像とInpating mask(文字領域を白,それ以外を黒で塗りつぶした画像)を用いて学習画像を生成している.

結果として,文字領域だけは削除され,文字領域が残される結果になった.f:id:dr_takuya:20181015142312p:plain

さらに,定量的な評価としてSSD*7を用いて元画像と文字領域を削除した画像で検出精度を検証している.

f:id:dr_takuya:20181015142730p:plain

F-Score自体が70%程度ほど低下しており,消去後の画像は検出するのが難しいと言える.

今後の課題として,Data Augumentationや精度向上があげられるものの,単純な構造である一定の性能を出すことができていて,深層学習がドンピシャでハマった例といえる.

*1:W. Huang, Y. Qiao, and X. Tang, ”Robust scene text detection with convolution neural network induced mser trees,” in European Conference on Computer Vision. Springer, 2014, pp. 497-511

*2:B. Epshtein, E. Ofek, and Y. Wexler, ”Detecting text in natural scenes with stroke width transform,” in Computer Vision and Pattern Recogni- tion (CVPR), 2010 IEEE Conference on. IEEE, 2010, pp. 2963-2970.

*3:T. Wang, D. J. Wu, A. Coates, and A. Y. Ng, ”End-to-end text recognition with convolutional neural networks,” in Pattern Recognition (ICPR), 2012 21st International Conference on. IEEE, 2012, pp. 3304- 3308.

*4:L. Neumann and J. Matas, ”Scene text localization and recognition with oriented stroke detection,” in Proceedings of the IEEE International Conference on Computer Vision, 2013, pp. 97-104.

*5:J.Johnson,A.Alahi,andL.Fei-Fei,”Perceptual losses for realtime style transfer and super-resolution,” in European Conference on Computer Vision. Springer, 2016, pp. 694-711.

*6:J. Long, E. Shelhamer, and T. Darrell, ”Fully convolutional networks for semantic segmentation,” in Proceedings of the IEEE Conference on Computer Vision and Pattern Recognition, 2015, pp. 3431-3440.

*7:W. Liu, D. Anguelov, D. Erhan, C. Szegedy, S. Reed, C.-Y. Fu, and A. C. Berg, ”Ssd: Single shot multibox detector,” in European Conference on Computer Vision. Springer, 2016, pp. 21-37.

superpixelの代表的なアルゴリズムと実装について

superpixel(スーパーピクセル)とは,色やテクスチャが類似するピクセルをグルーピングした小領域のことである.

入力画像をsuperpixelに分割することで,色の類似画素の位置関係を反映した小領域に分割することが可能になる.

類似度に基づくピクセルの集合体であるため,それぞれのセグメントは物体認識や画像加工などの前処理に用いるのに適する.

superpixelには以下の四種類がある。

Felzenszwalb の手法 *1

Vedaldi の手法 (Quickshift 法) *2

Achanta の手法 (SLIC 法) *3

Neubert の手法 (Watershed 法) *4

これらを簡単に説明する。

Felzenszwalb の手法
画像中のある二つの隣り合う分割領域間の相違度を計算し,それぞれの領域内の相違度より大きい場合,二つを異なる領域として扱う.逐次的に計算していくことで,全領域を分割する手法.

Vedaldi の手法
カーネル密度推定の極値として定義されるクラスタ中心を探索する手法であり,3 つのステップで領域を分割する手法.

Achanta の手法
原画像をLab 表色系に変換し,色の類似度とその位置関係に基づいたクラスタリングをおこなう.分水線の距離に基づいたエネルギー最小化法によるセグメンテーションをおこなう手法.

Neubert の手法
画像の輝度勾配を山と谷の地形図に見立て、そこに水を流すイメージをした時に、水を貯める分水嶺(壁)を"輪郭"として判定する手法.

Pythonにおいて,scikit-imageにて上記四つのアルゴリズムは実装されている.
これを試してみる.

from skimage import io
from skimage.segmentation import felzenszwalb, quickshift, slic, watershed, mark_boundaries
from skimage.filters import sobel
from skimage.color import rgb2gray
import matplotlib.pyplot as plt

img=io.imread("kumamon.jpg")#RGBの順番

#セグメント
felzen_segments = felzenszwalb(img)
quick_segments = quickshift(img)
slic_segments = slic(img)
water_segments = watershed(sobel(rgb2gray(img)), markers=250) 

#描画
plt.figure(figsize=(10, 10))
plt.rcParams["font.size"] = 15

plt.subplot(2, 2, 1)
plt.title("Felzenszwalb")
plt.imshow(mark_boundaries(img,felzen_segments))

plt.subplot(2, 2, 2)
plt.title("quickshift")
plt.imshow(mark_boundaries(img,quick_segments))

plt.subplot(2, 2, 3)
plt.title("slic")
plt.imshow(mark_boundaries(img,slic_segments))

plt.subplot(2, 2, 4)
plt.title("watershed")
plt.imshow(mark_boundaries(img,water_segments))


結果
f:id:dr_takuya:20180828152744p:plain

パラメータのチューニング次第ではあるが,①・②・④の手法は全体的に複雑に状態を捉えすぎる傾向がある.
そのため,情景内画像から物体を絞り込みたいようなシチュエーションにおいてはSLIC法を用いるのが適切である.

この方法では,色やテクスチャ特徴の類似度をもつ領域に画素を分類していき,統合していくためある程度ラフに領域分割をおこなってくれる.

さまざまなパラメータを設定することができる.
SLIC法
slic(image, n_segments=100, compactness=10.0, max_iter=10, sigma=0, spacing=None, multichannel=True, convert2lab=None, enforce_connectivity=True, min_size_factor=0.5, max_size_factor=3, slic_zero=False)

試しにセグメント数を変えてみる.

slic_segments1 = slic(img,n_segments=20)
slic_segments2 = slic(img,n_segments=50)
slic_segments3 = slic(img,n_segments=80)
slic_segments4 = slic(img,n_segments=100)


f:id:dr_takuya:20180828153750p:plain
結果

傾向としてセグメント数を少なくすると,前景領域と背景の大雑把な分離は可能で,
逆にセグメント数が多ければ同一物体におけるシェーディングや模様の違いも違うセグメントとして分離することができるようだ.

SLIC法は非常に便利な手法ではあるが,k平均法におけるパラメータを設定しないといけないので経験値が求められる.

パラメータを自動で推定するような研究もあるようだが*5,決定的な手法はまだないと思われる.
(知ってる方いれば教えてください_| ̄|○)

とにかく,スーパーピクセル使ってみましょう!!

*1:P. F. Felzenszwalb and D. P. Huttenlocher, “Efficient Graph-Based Image Segmentation,” International Journal of Computer Vision, Vol. 59, No. 2,2004.

*2:A. Vedaldi and S. Soatto, “Quick Shift and Kernel Methods for Mode Seeking,” European Conference on Computer Vision (ECCV), pp. 705– 718, 2008.

*3:R. Achanta, A. Shaji, K. Smith, A. Lucchi, P. Fua, and S.Süsstrunk, “SLIC Superpixels Compared to State-of-the-art Superpixel Methods,” IEEE Transactions on Pattern Analysis and Machine Intelligence, Vol. 34, pp. 2274–2282, 2012.

*4:P. Neubert and P. Protzel, “Compact Watershed and Preemptive SLIC : On Improving Trade-offs of Superpixel Segmentation Algorithms,” Inter- national Conference on Pattern Recognition (ICPR), pp. 996–1001, 2014.

*5:Parameter-Free Image Segmentation with SLIC

scikit-image における Thresholdingについて

おはこんばんちは!

早速ですが、みなさんはscikit-image使っていますか?
画像処理を行うとなると、どうしてもOpenCV一強になりがちですが、
実はscikit-imageも特徴量や認識に関するライブラリが多数あるので、ぜひ活用してみてください。

その中でも今回は、閾値処理に焦点を当てていきたいと思います。

scikit-imageの閾値処理は10個の手法が用意されています。
(Module: filters — skimage v0.15.dev0 docs)

  • Otsu

  • Yen

  (最大相関値に基づいた二値化)

  • Isodata

  • Local

  (ローカルピクセル近傍に基づいて閾値マスク画像を計算)

  • Li

  (元画像と2値化画像間の交差エントロピーが最小となるように,2値化値を選択する)

  • Minimum

  (入力画像のヒストグラムは、2つの最大値が得られるまで計算され、平滑化される。 そのときの最小値が閾値となる)

  • Mean

  (グレースケール値の平均に基づいて閾値を計算する)

  • Niblack

  • Sauvola

  • Triangle

メジャーなものからマイナーなものまで用意されていますが、何を使ったらいいかわからない人におすすめなのが try_all_threshold です。
これは、先ほどの閾値手法のうち、

  • Isodata
  • Li
  • Mean
  • Minimum
  • Otsu
  • Triangle
  • Yen


の処理をまとめておこない、結果を見ることができるメソッドです。

from skimage.filters import try_all_threshold
from skimage import io
img = io.imread('lena.png',True)#read grayScale
fig, ax = try_all_threshold(img, figsize=(10,8), verbose=False)

f:id:dr_takuya:20180819204355p:plain

個別に行いたい場合は、

from skimage import io
import matplotlib.pyplot as plt
from skimage.filters import threshold_isodata
img = io.imread('lena.png',True)
isodata_thresh =threshold_isodata(img)#Return thresh
binary = img > isodata_thresh
plt.imshow(binary,cmap=plt.cm.gray)

これらの処理は閾値を値として返すので、それらをヒストグラムにプロットしてあげると

from skimage import io
import matplotlib.pyplot as plt
from skimage.filters import threshold_isodata
from skimage.filters import threshold_minimum
from skimage.filters import threshold_yen

img = io.imread('lena.png',True)
isodata_thresh =threshold_isodata(img)#isodata method
minimum_thresh =threshold_minimum(img)#minimum method
yen_thresh =threshold_yen(img)#minimum method

plt.hist(img.ravel()*255,range(0,255))
plt.axvline(x=isodata_thresh*255,c='r',label="isodata")
plt.axvline(x=minimum_thresh*255,c='k',label="minimum")
plt.axvline(x=yen_thresh*255,c='b',label="yen")
plt.legend()

f:id:dr_takuya:20180819211503p:plain

閾値手法の比較が行えますね。

PageSpeed Insights APIを用いて、複数のサイトのスコアを一括取得する(Python)

みなさん、PageSpeed Insightsをご存知だろうか?

このサイトは、ウェブページのコンテンツを解析し、ページの読み込み時間を短くするための方法を提案してくれるwebサイトを作成していく上では欠かせないサイトである。

このサイトは、通常フォームに対してURLを入力することが可能だが、複数サイトまたは複数ページを解析することはできない。
そのため、Google Cloud Platform からAPIを用いることで複数のサイトを一括して計測できるようになる。

Google Cloud PlatformAPIを発行後、以下のソースコードを用いることでデータを取得可能である。

import requests

#指定したいURLをベタ書き or 読み込み
urlList=['http://abehiroshi.la.coocan.jp',
         'https://sakuraihinako.futureartist.net/',
         'http://kaela-web.com/',
         'http://keisuke-honda.com/',
         'http://www.genkisudo.net/',
         'http://www.becky.ne.jp/']

#GETメソッド
get_url='https://www.googleapis.com/pagespeedonline/v4/runPagespeed'

strategy_param='desktop'#モバイルサイト か #PC を指定(mobile or desktop)

api_key='ここにAPIを記述' #api key を指定

payload = {'strategy': strategy_param,'api_key': api_key} #GETメソッドに付帯するパラメータ

for url in urlList:
    urlName=get_url+"?url="+url
    
    result=requests.get(urlName,params=payload)

    result=result.json()#jsonに変換
    resultScore=result['ruleGroups']['SPEED']['score']#Scoreを取り出す
    resultTitile=result['title']#タイトルを取り出す
    
    print(resultTitile,resultScore)

このソースコードでは、サイトのタイトルと点数を出力している。

阿部寛のホームページ  93
桜井日奈子 Official Fanclub 7
木村カエラ | KAELAWEB 0
本田圭佑オフィシャルWEBサイト - Keisuke Honda Official Website 23
不要な食器がお金に変わりました|テーブルウェアショッピング 90
ベッキーオフィシャルウェブサイト 14

どうでもいいけど、やっぱ阿部寛のホームページの速度は異常だね。