42

次の写真は、私が欲しいものを教えてくれます。

画像内の長方形の情報(幅、高さ、中心点、回転度)があります。今、それらを切り取って画像として保存するスクリプトを書きたいと思いますが、まっすぐにすることもできます。のように、画像の内側に表示されている長方形から外側に表示されている長方形に移動したいと考えています。

OpenCV Python を使用しています。これを実現する方法を教えてください。

OpenCV Python の例は見つけにくいので、いくつかのコードを示してください。

サンプル画像

4

5 に答える 5

60

この関数を使用してwarpAffine、定義された中心点を中心に画像を回転できます。getRotationMatrix2D適切な回転行列は(ここthetaで、 は度数)を使用して生成できます。

開始イメージ 目的の長方形を見つけた後

その後、Numpy slicingを使用して画像を切り取ることができます。

回転した画像 結果

import cv2
import numpy as np

def subimage(image, center, theta, width, height):

   ''' 
   Rotates OpenCV image around center with angle theta (in deg)
   then crops the image according to width and height.
   '''

   # Uncomment for theta in radians
   #theta *= 180/np.pi

   shape = ( image.shape[1], image.shape[0] ) # cv2.warpAffine expects shape in (length, height)

   matrix = cv2.getRotationMatrix2D( center=center, angle=theta, scale=1 )
   image = cv2.warpAffine( src=image, M=matrix, dsize=shape )

   x = int( center[0] - width/2  )
   y = int( center[1] - height/2 )

   image = image[ y:y+height, x:x+width ]

   return image

出力画像dsizeの形状であることに注意してください。パッチ/角度が十分に大きい場合、単純化のために上記のように元の形状を使用すると、エッジが切り取られます (上の画像を比較)。この場合、(出力イメージを拡大するため) にスケーリング係数を導入し、スライスの基準点 (ここでは) を導入できます。shapecenter

上記の関数は次のように使用できます。

image = cv2.imread('owl.jpg')
image = subimage(image, center=(110, 125), theta=30, width=100, height=200)
cv2.imwrite('patch.jpg', image)
于 2012-07-24T09:26:42.853 に答える
3

これは、同じタスクを実行する私の C++ バージョンです。少し遅いことに気付きました。この機能のパフォーマンスを向上させる何かを誰かが見つけたら、私に知らせてください。:)

bool extractPatchFromOpenCVImage( cv::Mat& src, cv::Mat& dest, int x, int y, double angle, int width, int height) {

  // obtain the bounding box of the desired patch
  cv::RotatedRect patchROI(cv::Point2f(x,y), cv::Size2i(width,height), angle);
  cv::Rect boundingRect = patchROI.boundingRect();

  // check if the bounding box fits inside the image
  if ( boundingRect.x >= 0 && boundingRect.y >= 0 &&
       (boundingRect.x+boundingRect.width) < src.cols &&  
       (boundingRect.y+boundingRect.height) < src.rows ) { 

    // crop out the bounding rectangle from the source image
    cv::Mat preCropImg = src(boundingRect);

    // the rotational center relative tot he pre-cropped image
    int cropMidX, cropMidY;
    cropMidX = boundingRect.width/2;
    cropMidY = boundingRect.height/2;

    // obtain the affine transform that maps the patch ROI in the image to the
    // dest patch image. The dest image will be an upright version.
    cv::Mat map_mat = cv::getRotationMatrix2D(cv::Point2f(cropMidX, cropMidY), angle, 1.0f);
    map_mat.at<double>(0,2) += static_cast<double>(width/2 - cropMidX);
    map_mat.at<double>(1,2) += static_cast<double>(height/2 - cropMidY);

    // rotate the pre-cropped image. The destination image will be
    // allocated by warpAffine()
    cv::warpAffine(preCropImg, dest, map_mat, cv::Size2i(width,height)); 

    return true;
  } // if
  else {
    return false;
  } // else
} // extractPatch
于 2013-09-23T07:49:49.317 に答える