2013-04-28 36 views
20

画像を90度、180度または270度回転する必要があります。 OpenCV4Androidでは、私は以下を使用できます:画像を90度、180度または270度回転する

Imgproc.getRotationMatrix2D(new Point(center, center), degrees, 1); 
Imgproc.warpAffine(src, dst, rotationMatrix, dst.size()); 

しかし、これは私の画像処理アルゴリズムの大きなボトルネックです。もちろん、90度の倍数による単純な回転は、最も一般的な場合のwarpAffineよりはるかに簡単であり、はるかに効率的に行うことができます。たとえば、180度の場合、次のように指定できます。

ここで、-1は水平軸と垂直軸の両方を反転することを意味します。 90度または270度の回転に使用できる同様の最適化はありますか?

+0

あなたはJavaソリューションを締結しましたか、あなたは同じものを投稿できますか? –

答えて

2

これは、あなたがそれをGoogleとこれらのソリューションのどれもが本当に質問に答えるないか、正しいか、簡潔で最初の結果です。

Core.rotate(Mat dst, Mat src, Core.ROTATE_90_CLOCKWISE); //ROTATE_180 or ROTATE_90_COUNTERCLOCKWISE 
43

私はJava APIをよく知らないので、このコードはC++によって開発されています。 ロジックは同じである必要があります。 90n(nはN = int、.....、-3、-2、-1、0,1、 int型の2、3、...、最大値)

/* 
*@brief rotate image by multiple of 90 degrees 
* 
*@param source : input image 
*@param dst : output image 
*@param angle : factor of 90, even it is not factor of 90, the angle 
* will be mapped to the range of [-360, 360]. 
* {angle = 90n; n = {-4, -3, -2, -1, 0, 1, 2, 3, 4} } 
* if angle bigger than 360 or smaller than -360, the angle will 
* be map to -360 ~ 360. 
* mapping rule is : angle = ((angle/90) % 4) * 90; 
* 
* ex : 89 will map to 0, 98 to 90, 179 to 90, 270 to 3, 360 to 0. 
* 
*/ 
void rotate_image_90n(cv::Mat &src, cv::Mat &dst, int angle) 
{ 
    if(src.data != dst.data){ 
     src.copyTo(dst); 
    } 

    angle = ((angle/90) % 4) * 90; 

    //0 : flip vertical; 1 flip horizontal 
    bool const flip_horizontal_or_vertical = angle > 0 ? 1 : 0; 
    int const number = std::abs(angle/90);   

    for(int i = 0; i != number; ++i){ 
     cv::transpose(dst, dst); 
     cv::flip(dst, dst, flip_horizontal_or_vertical); 
    } 
} 

編集:改善、パフォーマンス、TimZamanのコメントと1の実装 '' ここで

void rotate_90n(cv::Mat const &src, cv::Mat &dst, int angle) 
{   
    CV_Assert(angle % 90 == 0 && angle <= 360 && angle >= -360); 
    if(angle == 270 || angle == -90){ 
     // Rotate clockwise 270 degrees 
     cv::transpose(src, dst); 
     cv::flip(dst, dst, 0); 
    }else if(angle == 180 || angle == -180){ 
     // Rotate clockwise 180 degrees 
     cv::flip(src, dst, -1); 
    }else if(angle == 90 || angle == -270){ 
     // Rotate clockwise 90 degrees 
     cv::transpose(src, dst); 
     cv::flip(dst, dst, 1); 
    }else if(angle == 360 || angle == 0 || angle == -360){ 
     if(src.data != dst.data){ 
      src.copyTo(dst); 
     } 
    } 
} 
+2

あなたのループは、必要な仲間よりも高価になります。 – TimZaman

+0

私は 'src.t()'によって作成された一時的なイメージが好きではありません。特に、Androidで特に高価になる可能性がある割り当てが発生します。 – Antonio

+0

@Antonio create関数は必要なときだけ新しいバッファを割り当てます。言い換えれば、dstの次元と型がsrcと同じであれば、何も割り当てません。 – StereoMatching

6

があるために感謝Android APIを使用したソリューションここでは、さまざまな向きでマウントできるカメラから画像を回転させるために使用しています。

if (mCameraOrientation == 270) { 
    // Rotate clockwise 270 degrees 
    Core.flip(src.t(), dst, 0); 
} else if (mCameraOrientation == 180) { 
    // Rotate clockwise 180 degrees 
    Core.flip(src, dst, -1); 
} else if (mCameraOrientation == 90) { 
    // Rotate clockwise 90 degrees 
    Core.flip(src.t(), dst, 1); 
} else if (mCameraOrientation == 0) { 
    // No rotation 
    dst = src; 
} 
9

この画像に任意の度数を回転させる、90

void 
    rotate_cw(const cv::Mat& image, cv::Mat& dest, int degrees) 
    { 
     switch (degrees % 360) { 
      case 0: 
       dest = image.clone(); 
       break; 
      case 90: 
       cv::flip(image.t(), dest, 1); 
       break; 
      case 180: 
       cv::flip(image, dest, -1); 
       break; 
      case 270: 
       cv::flip(image.t(), dest, 0); 
       break; 
      default: 
       cv::Mat r = cv::getRotationMatrix2D({image.cols/2.0F, image.rows/2.0F}, degrees, 1.0); 
       int len = std::max(image.cols, image.rows); 
       cv::warpAffine(image, dest, r, cv::Size(len, len)); 
       break; //image size will change 
     } 
    } 

しかし、OpenCVの3.0の倍数のための最も効率的な手段を用いて、これはちょうどcv::rotateコマンド経由で行われます。

ここで
cv::rotate(image, dest, e.g. cv::ROTATE_90_COUNTERCLOCKWISE); 
+0

通常、出力イメージはパラメータとして渡す必要があります。そうでなければ、各呼び出しで割り当てが行われます。 (あなたの実装では回転= 0の場合にのみ利点があります) – Antonio

+0

Pffこのコードは危険です。ローテーションがデフォルトでない限り、 'image'で渡されるのと同じ基礎データを返します。さらに、 'cv :: Size(len、len)'のために生成されるキャンバスが大きすぎます。 – TimZaman

+0

ありがとう!あなたの最初のソリューション[0,90,180,270]を編集し、OpenCVアプリを持っていたアンドロイドのために移植し、正しい方法でJavaCameraViewを表示することができました。良い一日を過ごしてください! – Antonino

2

私のPythonの翻訳(およびすべてのポスターのおかげで)です:

import cv2 
def rot90(img, rotflag): 
    """ rotFlag 1=CW, 2=CCW, 3=180""" 
if rotflag == 1: 
    img = cv2.transpose(img) 
    img = cv2.flip(img, 1) # transpose+flip(1)=CW 
elif rotflag == 2: 
    img = cv2.transpose(img) 
    img = cv2.flip(img, 0) # transpose+flip(0)=CCW 
elif rotflag ==3: 
    img = cv2.flip(img, -1) # transpose+flip(-1)=180 
elif rotflag != 0: # if not 0,1,2,3 
    raise Exception("Unknown rotation flag({})".format(rotflag)) 
return img 
2

Numpyのみを使用してこのPythonバージョンを書きましたが、cv2.transpose()cv2.flip()を使用するよりもはるかに高速です。

def rotate_image_90(im, angle): 
    if angle % 90 == 0: 
     angle = angle % 360 
     if angle == 0: 
      return im 
     elif angle == 90: 
      return im.transpose((1,0, 2))[:,::-1,:] 
     elif angle == 180: 
      return im[::-1,::-1,:] 
     elif angle == 270: 
      return im.transpose((1,0, 2))[::-1,:,:] 

    else: 
     raise Exception('Error') 
0

numpy.rot90を使用します。180度にしたい場合は、2度だけ行います。 Pythonで

import numpy as np 
import cv2 

img = cv2.imread('img.png',1) 
cv2.imshow('',img) 
cv2.waitKey(0) 

img90 = np.rot90(img) 
cv2.imshow('',img90) 
cv2.waitKey(0) 
0

# import the necessary packages 
import numpy as np 
import cv2 

# initialize the camera and grab a reference to the raw camera capture 
vs = cv2.VideoCapture(0) 
(ret, image_original) = vs.read() 
image_rotated_90 = np.rot90(image_original) 
image_rotated_180 = np.rot90(image_rotated_90) 

# show the frame and press any key to quit the image frame 
cv2.imshow("Frame", image_rotated_180) 
cv2.waitKey(0) 
関連する問題