OpenCVでは画像内の矩形領域をcv::Rectを使うことで切り出すことができます.
cv::Mat src; // 元画像
cv::Rect roi(cv::Point(256, 156), cv::Size(50, 200));
cv::Mat subImg = src(roi); // 切り出し画像
しかし回転した矩形領域を切り出したい場合,OpenCVには回転矩形を表すcv::RotatedRectがありますが,cv::Rectのようにそのままcv::RotatedRectを指定ことはできません.
画像からcv::RotatedRectで回転矩形領域を切り出す方法についてこの記事で紹介
されていたので,こちらを参考に説明します.
画像からRotatedRectを切り出す方法
まず画像全体を一度回転してから,矩形領域を切り出すという処理が必要になります.
手順としては以下の通りです.
- 回転矩形の角度から回転行列を求める.
- 回転行列を用いて元画像全体を回転させる.
- 回転した画像から矩形領域を切り出す.
cv::Mat src; // 入力画像
cv::RotatedRect rect(cv::Point(256, 256), cv::Size(50, 200), 45); // 回転矩形
cv::Mat M; // 回転行列
cv::Mat rotated; // 回転された元画像
cv::Mat cropped; // 切り出された画像
float angle = rect.angle;
cv::Size rect_size = rect.size;
if (rect.angle < -45.) {
angle += 90.0;
std::swap(rect_size.width, rect_size.height);
}
// 回転矩形の角度から回転行列を計算する.
M = cv::getRotationMatrix2D(rect.center, angle, 1.0);
// 元画像を回転させる.
cv::warpAffine(src, rotated, M, src.size(), cv::INTER_CUBIC);
// 回転した画像から矩形領域を切り出す.
cv::getRectSubPix(rotated, rect_size, rect.center, cropped);
(おまけ) cv::RotatedRectを描画する
cv::Rectの描画はcv::rectangleでできますが,cv::RotatedRectの描画はcv::rectangleではなく,cv::polylinesやcv::fillPolyを使います.
塗りつぶさない場合 - cv::polylines()
cv::Point2f vertices2f[4];
rect.points(vertices2f);
std::vector<cv::Point> vertices;
for (int i = 0; i < 4; ++i) {
vertices.push_back(vertices2f[i]);
}
const cv::Point* pts = (const cv::Point*) cv::Mat(vertices).data;
int npts = cv::Mat(vertices).rows;
cv::polylines(src, &pts, &npts, 1, true, cv::Scalar(0, 255, 0), 3);
塗りつぶす場合 - cv::fillConvexPoly()
cv::Point2f vertices2f[4];
rect.points(vertices2f);
cv::Point vertices[4];
for (int i = 0; i < 4; ++i) {
vertices[i] = vertices2f[i];
}
cv::fillConvexPoly(src, vertices, 4, cv::Scalar(0, 255, 0));