LoginSignup
12
7

More than 5 years have passed since last update.

OpenCV小ネタ:画像の回転と切り出しを同時にやる(切り出されて不要になる部分の不要な回転計算をせずに)

Posted at

動機

タイル地図を使ってなんやかんやしようとしています。進行方向を上向きにしたり、特定の土地領域にフィットさせたり、特定の道路を垂直・水平に表示したりするために回転させてから矩形切り出しの処理があります。はじめは元画像(連結タイル)全体を回転させてから必要な矩形を切り出していたのですが、不要な部分まで回転計算しているのがマジで不要なのでなんとかしようとしたらなんとかなりました。地図に限らずこういう処理はあるでしょうし、ザっとググってみても同じようなことがズバリ書いてあるようなのは見つからなかったので紹介してみます。

pythonコード

opencv回転切り出し説明1.png

元画像src_imgの座標(center[0],center[1])を中心とし、deg度回転させた画像からsize[0]×size[1]の大きさの矩形を切り出したい。centerとsizeはタプルに入っている等とする。

全体を回転させてから切り出すコード

import cv2

#元画像全体を回転させてから切り出す
def cut_after_rot(src_img, deg, center, size):
    rot_mat = cv2.getRotationMatrix2D(center, deg, 1.0)
    src_h,src_w,_ = src_img.shape
    rot_img = cv2.warpAffine(src_img, rot_mat, (src_w,src_h))
    #スライスによって領域を切り出す
    return rot_img[center[1]-size[1]//2:center[1]+size[1]//2, \
                   center[0]-size[0]//2:center[0]+size[0]//2, :]

切り出しと回転が同時なコード

#欲しい領域のみ回転させる。切り出しと回転が同時なイメージ。
def rot_cut(src_img, deg, center, size):
    rot_mat = cv2.getRotationMatrix2D(center, deg, 1.0)
    rot_mat[0][2] += -center[0]+size[0]/2 # -(元画像内での中心位置)+(切り抜きたいサイズの中心)
    rot_mat[1][2] += -center[1]+size[1]/2 # 同上
    return cv2.warpAffine(src_img, rot_mat, size)

cv2.getRotationMatrix2D()で得られるrot_matは2x3の行列です。左の2x2部はふつうのdeg°の回転行列です。右の2x1部は平行移動量です。原点中心にdeg°回転させた画像を右の2x1部の値で平行移動すると、(center[0],center[1])を中心に回転したかのようになるようです。この平行移動量を操作して、切り出したいサイズの中心に来るようにしているのが上記関数内でコメントがついている箇所です。cv2.warpAffine()の第3引数でもsizeを指定してやって余計な部分の取り出し・回転をしないようにしています。説明不足感ありありですが、こんなもんで勘弁してください。

性能比

試しに640x640のカラー画像を45°回転させて切り出す処理時間を、切り出す大きさを変えて計ってみました。

切り出しサイズ160x160 切り出しサイズ320x320
全体回転させた後で切り出す cut_after_rot() 1000回 3.41秒 3.61秒
切り出しと回転が同時 rot_cut() 1000回 0.34秒 0.72秒

cut_after_rot()では切り出しサイズによる影響が少ないです。おそらく全体回転にほとんどの処理時間がかかっています。
rot_cut()では切り出しサイズに応じた時間を要し、cut_after_rot()に比べて高速です。160x160→320x320で処理時間が4倍になりそうなところが2倍くらいで済んでいますが、そこのところはよく分かりません…

Qiita投稿前はこんな検証してなくて「処理が速い(たぶん)」くらいに思ってましたが、計ったみたら思ったより効果があってまあよかったです。

12
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
7