[opencv] Image rotate

spring·2020년 11월 9일
0

1. 90도 회전

cv::rotate(img, img, cv::ROTATE_90_CLOCKWISE);

cv::ROTATE_90_CLOCKWISE 는 시계방향 회전.
cv::ROTATE_90_COUNTERCLOCKWISE 는 반시계방향 회전.

2. 내부 회전

cv::Mat ImageRotateInner(const cv::Mat src, double degree
	, cv::Point2f base=cv::Point2f(std::numeric_limits<float>::infinity())) {
	if (base.x == std::numeric_limits<float>::infinity()) {
		base.x = src.cols / 2;
		base.y = src.rows / 2;
	}
	cv::Mat dst = src.clone();
	cv::Mat rot = cv::getRotationMatrix2D(base, degree, 1.0);
	cv::warpAffine(src, dst, rot, src.size());
	return std::move(dst);
}


내부 회전은 창의 크기가 고정된채(원래 이미지의 크기) 이미지가 중심축을 기준으로 회전한다.

3. 외부 회전

cv::Mat ImageRotateOuter(const cv::Mat src, double degree, cv::Point* out = nullptr) {
	cv::Point2d base(src.cols / 2.0, src.rows / 2.0);
	cv::Mat rot = cv::getRotationMatrix2D(base, degree, 1.0);
	cv::Rect bbox = cv::RotatedRect(base, src.size(), degree).boundingRect();
	rot.at<double>(0, 2) += bbox.width / 2.0 - base.x;
	rot.at<double>(1, 2) += bbox.height / 2.0 - base.y;
	if (out != nullptr){
		out->x = bbox.width / 2.0 - base.x;
		out->y = bbox.height / 2.0 - base.y;
	}
	cv::Mat dst;
	cv::warpAffine(src, dst, rot, bbox.size());
	return std::move(dst);
}


외부 회전은 일단 회전을 하고, 그 회전된 이미지에 Fitting 된 이미지가 생성된다.

내부 회전의 경우 간단하게 회전 공식을 쓰면 부가적인 정보도 같이 회전이 가능하지만,

외부 회전은 내부 변수의 값이 필요하다. (아래 소스코드에서 cv::Point* out)

[100,100] 을 같이 회전시키면 아래와 같이 나온다.

#define IMSHOW(IMG)	cv::imshow(#IMG,IMG)
int main() {
	double angle = 30;
	cv::Mat img = cv::imread("SeoYuri.jpg");
	cv::Point2d mid(img.cols / 2.0, img.rows / 2.0);
	//============
	cv::Point pt(100, 100);
	cv::Point adding;

	cv::Mat inner = ImageRotateInner(img, angle, mid);
	cv::Mat outer = ImageRotateOuter(img, angle, &adding);

	cv::circle(img, pt, 3, cv::Scalar(255, 0, 255));
	cv::Point after;
	double rad = -angle*CV_PI / 180.0;
	after.x = (pt.x - mid.x)*cos(rad) - (pt.y - mid.y)*sin(rad) + mid.x;
	after.y = (pt.x - mid.x)*sin(rad) + (pt.y - mid.y)*cos(rad) + mid.y;
	cv::circle(inner, after, 3, cv::Scalar(255, 0, 255));
	after.x += adding.x;
	after.y += adding.y;
	cv::circle(outer, after, 3, cv::Scalar(255, 0, 255));

	IMSHOW(img);
	IMSHOW(inner);
	IMSHOW(outer);
	cv::waitKey();
	cv::destroyAllWindows();
	return 0;
}
profile
Researcher & Developer @ NAVER Corp | Designer @ HONGIK Univ.

0개의 댓글