Каков наилучший способ (в c/С++) повернуть IplImage/cv:: Mat на 90 градусов? Я бы предположил, что должно быть что-то лучше, чем преобразовать его с помощью матрицы, но я не могу найти ничего, кроме этого в API и онлайн.
Самый простой способ повернуть на 90 градусов изображение с помощью OpenCV?
Ответ 1
Начиная с OpenCV3.2, жизнь стала немного легче, теперь вы можете поворачивать изображение в одной строке кода:
cv::rotate(image, image, cv::ROTATE_90_CLOCKWISE);
Для направления вы можете выбрать любое из следующего:
ROTATE_90_CLOCKWISE
ROTATE_180
ROTATE_90_COUNTERCLOCKWISE
Ответ 2
Вращение - это композиция транспонирования и флип.
Что в OpenCV можно написать так (пример Python ниже):
img = cv.LoadImage("path_to_image.jpg")
timg = cv.CreateImage((img.height,img.width), img.depth, img.channels) # transposed image
# rotate counter-clockwise
cv.Transpose(img,timg)
cv.Flip(timg,timg,flipMode=0)
cv.SaveImage("rotated_counter_clockwise.jpg", timg)
# rotate clockwise
cv.Transpose(img,timg)
cv.Flip(timg,timg,flipMode=1)
cv.SaveImage("rotated_clockwise.jpg", timg)
Ответ 3
Обновление для транспонирования:
Вы должны использовать cvTranspose()
или cv::transpose()
, потому что (как вы правильно указали) это более эффективно. Опять же, я рекомендую перейти на OpenCV2.0, так как большинство функций cvXXX
просто преобразуют структуры IplImage*
в объекты Mat
(без глубоких копий). Если вы сохранили изображение в объекте Mat
, Mat.t()
вернет транспонирование.
Любое вращение:
Вы должны использовать cvWarpAffine, определив матрицу вращения в общей структуре матрицы преобразования. Я настоятельно рекомендую обновить до OpenCV2.0, который имеет несколько функций, а также класс Mat
, который инкапсулирует матрицы и изображения. С помощью 2.0 вы можете использовать warpAffine выше.
Ответ 4
Это пример без нового интерфейса С++ (работает для 90, 180 и 270 градусов, используя param = 1, 2 и 3). Не забудьте вызвать cvReleaseImage
на возвращенное изображение после его использования.
IplImage *rotate_image(IplImage *image, int _90_degrees_steps_anti_clockwise)
{
IplImage *rotated;
if(_90_degrees_steps_anti_clockwise != 2)
rotated = cvCreateImage(cvSize(image->height, image->width), image->depth, image->nChannels);
else
rotated = cvCloneImage(image);
if(_90_degrees_steps_anti_clockwise != 2)
cvTranspose(image, rotated);
if(_90_degrees_steps_anti_clockwise == 3)
cvFlip(rotated, NULL, 1);
else if(_90_degrees_steps_anti_clockwise == 1)
cvFlip(rotated, NULL, 0);
else if(_90_degrees_steps_anti_clockwise == 2)
cvFlip(rotated, NULL, -1);
return rotated;
}
Ответ 5
Вот моя реализация python cv2
:
import cv2
img=cv2.imread("path_to_image.jpg")
# rotate ccw
out=cv2.transpose(img)
out=cv2.flip(out,flipCode=0)
# rotate cw
out=cv2.transpose(img)
out=cv2.flip(out,flipCode=1)
cv2.imwrite("rotated.jpg", out)
Ответ 6
Здесь мое решение EmguCV (С# порт OpenCV):
public static Image<TColor, TDepth> Rotate90<TColor, TDepth>(this Image<TColor, TDepth> img)
where TColor : struct, IColor
where TDepth : new()
{
var rot = new Image<TColor, TDepth>(img.Height, img.Width);
CvInvoke.cvTranspose(img.Ptr, rot.Ptr);
rot._Flip(FLIP.HORIZONTAL);
return rot;
}
public static Image<TColor, TDepth> Rotate180<TColor, TDepth>(this Image<TColor, TDepth> img)
where TColor : struct, IColor
where TDepth : new()
{
var rot = img.CopyBlank();
rot = img.Flip(FLIP.VERTICAL);
rot._Flip(FLIP.HORIZONTAL);
return rot;
}
public static void _Rotate180<TColor, TDepth>(this Image<TColor, TDepth> img)
where TColor : struct, IColor
where TDepth : new()
{
img._Flip(FLIP.VERTICAL);
img._Flip(FLIP.HORIZONTAL);
}
public static Image<TColor, TDepth> Rotate270<TColor, TDepth>(this Image<TColor, TDepth> img)
where TColor : struct, IColor
where TDepth : new()
{
var rot = new Image<TColor, TDepth>(img.Height, img.Width);
CvInvoke.cvTranspose(img.Ptr, rot.Ptr);
rot._Flip(FLIP.VERTICAL);
return rot;
}
Не нужно слишком сложно перевести его обратно на С++.
Ответ 7
Ну, я искал некоторые подробности и не нашел никакого примера. Поэтому я размещаю функцию transposeImage
, которая, я надеюсь, поможет другим, которые ищут прямой способ поворота на 90 ° без потери данных:
IplImage* transposeImage(IplImage* image) {
IplImage *rotated = cvCreateImage(cvSize(image->height,image->width),
IPL_DEPTH_8U,image->nChannels);
CvPoint2D32f center;
float center_val = (float)((image->width)-1) / 2;
center.x = center_val;
center.y = center_val;
CvMat *mapMatrix = cvCreateMat( 2, 3, CV_32FC1 );
cv2DRotationMatrix(center, 90, 1.0, mapMatrix);
cvWarpAffine(image, rotated, mapMatrix,
CV_INTER_LINEAR + CV_WARP_FILL_OUTLIERS,
cvScalarAll(0));
cvReleaseMat(&mapMatrix);
return rotated;
}
Вопрос: Почему это?
float center_val = (float)((image->width)-1) / 2;
Ответ: Потому что он работает:) Единственный найденный мной центр, который не переводит изображение. Хотя, если у кого-то есть объяснение, мне было бы интересно.