Поверните изображение на 90, 180 или 270 градусов
Мне нужно повернуть изображение на 90, 180 или 270 градусов. В OpenCV4Android я могу использовать:
Imgproc.getRotationMatrix2D(new Point(center, center), degrees, 1);
Imgproc.warpAffine(src, dst, rotationMatrix, dst.size());
Однако это огромный недостаток в моем алгоритме обработки изображений. Конечно, простое вращение на 90 градусов намного проще, чем самый общий случай warpAffine
, и его можно сделать гораздо эффективнее. Например, для 180 градусов я мог бы использовать:
Core.flip(src, dst, -1);
где -1 означает переворачивание горизонтальной и вертикальной осей. Есть ли аналогичная оптимизация, которую я мог бы использовать для поворотов на 90 или 270 градусов?
Ответы
Ответ 1
Это первый результат, когда вы просматриваете его в Google, и ни одно из этих решений действительно не отвечает на вопрос, не является правильным или лаконичным.
Core.rotate(Mat src, Mat dst, Core.ROTATE_90_CLOCKWISE); //ROTATE_180 or ROTATE_90_COUNTERCLOCKWISE
Ответ 2
Я не очень хорошо знаю java api, эти коды разрабатываются С++.
Логика должна быть одинаковой, используйте транспонирование + флип для поворота изображения с помощью
90n (n принадлежит N = минимальное значение int,....., -3, -2, -1, 0, 1, 2, 3,..., max значение int)
/*
*@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);
}
}
}
Ответ 3
Это повернет изображение на любое число градусов, используя наиболее эффективное средство для кратных 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);
Ответ 4
Вот решение, использующее API Android. Здесь я использую его для поворота изображений с камеры, которая может быть установлена в разных направлениях.
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;
}
Ответ 5
Вот мой перевод на 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
Ответ 6
Я написал эту версию Python только с помощью Numpy
, которые намного быстрее, чем с помощью 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')
Ответ 7
Вы можете вращать изображение, используя функцию NumPy rot90
как
def rotate_image(image,deg):
if deg ==90:
return np.rot90(image)
if deg ==180:
return np.rot90(image,2)
if deg == 270:
return np.rot90(image,-1) #Reverse 90 deg rotation
Надеюсь, это поможет..
Ответ 8
Используйте numpy.rot90
, если хотите 180 градусов, просто сделайте это дважды.
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)
Ответ 9
В python:
# 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)
Ответ 10
![]()
Здесь функция для поворота на любой angular [-360 ... 360]
def rotate_image(image, angle):
# Grab the dimensions of the image and then determine the center
(h, w) = image.shape[:2]
(cX, cY) = (w / 2, h / 2)
# Grab the rotation matrix (applying the negative of the
# angle to rotate clockwise), then grab the sine and cosine
# (i.e., the rotation components of the matrix)
M = cv2.getRotationMatrix2D((cX, cY), -angle, 1.0)
cos = np.abs(M[0, 0])
sin = np.abs(M[0, 1])
# Compute the new bounding dimensions of the image
nW = int((h * sin) + (w * cos))
nH = int((h * cos) + (w * sin))
# Adjust the rotation matrix to take into account translation
M[0, 2] += (nW / 2) - cX
M[1, 2] += (nH / 2) - cY
# Perform the actual rotation and return the image
return cv2.warpAffine(image, M, (nW, nH))
Использование
import cv2
import numpy as np
image = cv2.imread('1.png')
rotate = rotate_image(image, angle=90)