opencv图片的任意角度旋转实现示例

目录
  • 一 旋转角度坐标的计算
  • 二 旋转任意角度的步骤
  • 三 实现

一 旋转角度坐标的计算

1.如果O点为圆心,则点P绕点O旋转redian弧度之后,点P的坐标变换为点Q的计算公式为:

Q.x=P.x*cos(redian)-P.y*sin(redian)

Q.y=P.x*sin(redian)+P.y*cos(redian)

redian表示的为弧度

弧度与角度的变换公式为:

redian=pi*180/angle

2. 如果O点不是圆心,则点P绕点O旋转redian弧度之后,点P的坐标变换为Q的计算公式如下:

Q.x=(P.x-O.x)*cos(redian)-(P.y-O.y)*sin(redian)+O.x

Q.y=(P.x-O.x)*sin(redian)+(P.y-O.y)*cos(redian)+O.y

二 旋转任意角度的步骤

1.首先默认旋转45度时,所扩展的图像最大,即为根号2倍的长或宽的最大值,将图像填充到可能达到的最大

2 使用getRotationMatrix2D函数求取旋转矩阵,使用warpAffine函数旋转矩阵

3 求旋转之后包括图像的最大的矩形

4 删除多余的黑色边框

三 实现

#include <iostream>
#include<opencv2/opencv.hpp>

using namespace cv;

void rotate_arbitrarily_angle(Mat &src,Mat &dst,float angle)
{
    float radian = (float) (angle /180.0 * CV_PI);

    //填充图像
    int maxBorder =(int) (max(src.cols, src.rows)* 1.414 ); //即为sqrt(2)*max
    int dx = (maxBorder - src.cols)/2;
    int dy = (maxBorder - src.rows)/2;
    copyMakeBorder(src, dst, dy, dy, dx, dx, BORDER_CONSTANT);

    //旋转
    Point2f center( (float)(dst.cols/2) , (float) (dst.rows/2));
    Mat affine_matrix = getRotationMatrix2D( center, angle, 1.0 );//求得旋转矩阵
    warpAffine(dst, dst, affine_matrix, dst.size());

    //计算图像旋转之后包含图像的最大的矩形
    float sinVal = abs(sin(radian));
    float cosVal = abs(cos(radian));
    Size targetSize( (int)(src.cols * cosVal +src.rows * sinVal),
                     (int)(src.cols * sinVal + src.rows * cosVal) );

    //剪掉多余边框
    int x = (dst.cols - targetSize.width) / 2;
    int y = (dst.rows - targetSize.height) / 2;
    Rect rect(x, y, targetSize.width, targetSize.height);
    dst = Mat(dst,rect);
}

int main() {
    cv::Mat src=cv::imread("../3.png");
    cv::Mat dst;
    rotate_arbitrarily_angle(src,dst,30);
    cv::imshow("src",src);
    cv::imshow("dst",dst);
    cv::waitKey(0);
    return 0;
}

原图

绕中心点旋转30度的结果

需要注意的是该方法仅适用于水平图像旋转到有角度的图像,至于可以随意旋转角度的方法我现在还不知道如何完成,以后有机会再做.

以上做法还有个最大的缺点是在旋转之后像素大小发生了变化,如果你要对像素操作就会产生很多问题,接下来的代码会将像素固定下来,不过也是针对旋转到一定角度之后再返回到水平位置的代码,具有很大的局限性,研究明白之后再更新其他情况

cv::Mat rotate_arbitrarily_angle1(cv::Mat matSrc, float angle, bool direction,int height,int width) {
    float theta = angle * CV_PI / 180.0;
    int nRowsSrc = matSrc.rows;
    int nColsSrc = matSrc.cols; // 如果是顺时针旋转
    if (!direction) theta = 2 * CV_PI - theta; // 全部以逆时针旋转来计算
    // 逆时针旋转矩阵
    float matRotate[3][3]{ {
                                   std::cos(theta), -std::sin(theta), 0},
                           {std::sin(theta), std::cos(theta), 0 },
                           {0, 0, 1} };

    float pt[3][2]{
            { 0, nRowsSrc },
            {nColsSrc, nRowsSrc},
            {nColsSrc, 0} };

    for (int i = 0; i < 3; i++) {
        float x = pt[i][0] * matRotate[0][0] + pt[i][1] * matRotate[1][0];
        float y = pt[i][0] * matRotate[0][1] + pt[i][1] * matRotate[1][1];
        pt[i][0] = x; pt[i][1] = y;
    }
    // 计算出旋转后图像的极值点和尺寸
    float fMin_x = std::min(std::min(std::min(pt[0][0], pt[1][0]), pt[2][0]), (float)0.0);
    float fMin_y = std::min(std::min(std::min(pt[0][1], pt[1][1]), pt[2][1]), (float)0.0);
    float fMax_x = std::max(std::max(std::max(pt[0][0], pt[1][0]), pt[2][0]), (float)0.0);
    float fMax_y = std::max(std::max(std::max(pt[0][1], pt[1][1]), pt[2][1]), (float)0.0);
    int nRows = cvRound(fMax_y - fMin_y + 0.5) + 1;
    int nCols = cvRound(fMax_x - fMin_x + 0.5) + 1;
    int nMin_x = cvRound(fMin_x + 0.5);
    int nMin_y = cvRound(fMin_y + 0.5);
    // 拷贝输出图像
    cv::Mat matRet(nRows, nCols, matSrc.type(), cv::Scalar(0));
    for (int j = 0; j < nRows; j++) {
        for (int i = 0; i < nCols; i++) {
            // 计算出输出图像在原图像中的对应点的坐标,然后复制该坐标的灰度值
            // 因为是逆时针转换,所以这里映射到原图像的时候可以看成是,输出图像
            // 到顺时针旋转到原图像的,而顺时针旋转矩阵刚好是逆时针旋转矩阵的转置
            // 同时还要考虑到要把旋转后的图像的左上角移动到坐标原点。
            int x = (i + nMin_x) * matRotate[0][0] + (j + nMin_y) * matRotate[0][1];
            int y = (i + nMin_x) * matRotate[1][0] + (j + nMin_y) * matRotate[1][1];
            if (x >= 0 && x < nColsSrc && y >= 0 && y < nRowsSrc) {
                matRet.at<uchar>(j, i) = matSrc.at<uchar>(y, x);
            }
        }
    }
    if(direction== false){//当需要顺时针旋转回水平位置时
        int x = (matRet.cols -width) / 2;
        int y = (matRet.rows -height) / 2;

        //width和height是水平条件下图像的宽高
        cv::Rect rect(x, y, width, height);
        matRet = cv::Mat(matRet,rect);
    }
    return matRet;
}

到此这篇关于opencv图片的任意角度旋转实现示例的文章就介绍到这了,更多相关opencv图片任意角度旋转内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • python opencv对图像进行旋转且不裁剪图片的实现方法

    最近在做深度学习时需要用到图像处理相关的操作,在度娘上找到的图片旋转方法千篇一律,旋转完成的图片都不是原始大小,很苦恼,于是google到歪果仁的网站扒拉了一个方法,亲测好用,再次嫌弃天下文章一大抄的现象,虽然我也是抄歪果仁的. 废话不多说了,直接贴代码了. def rotate_bound(image, angle): # grab the dimensions of the image and then determine the # center (h, w) = image.shape[

  • python opencv旋转图片的使用方法

    背景 在图像处理中,有的时候会有对图片进行角度旋转的处理,尤其是在计算机视觉中对于图像扩充,旋转角度扩充图片是一种常见的处理.这种旋转图片的应用场景也比较多,比如用户上传图片是竖着的时候,不好进行处理,也需要对其进行旋转,以便后续算法处理.常见的旋转处理有两种方式,一种是转化为numpy矩阵后,对numpy矩阵进行处理,另外一种是使用opencv自带的函数进行各种变换处理,以实现旋转角度的结果. 原始图像: opencv函数 旋转中常用的函数有以下几个函数 cv2.transpose: 对图像矩

  • Python+OpenCV+图片旋转并用原底色填充新四角的例子

    我就废话不多说了,直接上代码吧! import cv2 from math import fabs, sin, cos, radians import numpy as np from scipy.stats import mode def get_img_rot_broa(img, degree=45, filled_color=-1): """ Desciption: Get img rotated a certain degree, and use some color

  • Python+OpenCV 实现图片无损旋转90°且无黑边

    0. 引言 有如上一张图片,在以往的图像旋转处理中,往往得到如图所示的图片. 然而,在进行一些其他图像处理或者图像展示时,黑边带来了一些不便.本文解决图片旋转后出现黑边的问题,实现了图片尺寸不变的旋转(以上提到的黑边是图片的一部分). 1. 方法流程 (1)旋转图片,得到有黑边的旋转图片. (2)找出图片区域(不含黑边)的位置. (3)创建一个空图片(其实是矩阵). (4)将图片区域搬到此空图片. 2. 程序 #!/usr/bin/python # -*- coding: UTF-8 -*- "

  • python opencv实现图片旋转矩形分割

    有时候需要对有角度的矩形框内图像从原图片中分割出来.这里的程序思想是,先将图片进行矩形角度的旋转,使有角度的矩形处于水平状态后,根据原来坐标分割图片. 参考:python opencv实现旋转矩形框裁减功能 修改原来的程序: 1.旋转函数的输入仅为矩形的四点坐标 2.角度由公式计算出来 3.矩形四点pt1,pt2,pt3,pt4由txt文件读入 4.在旋转程序中还处理了顺时针和逆时针及出现矩形框翻转的问题. 代码: # -*- coding:utf-8 -*- import cv2 from m

  • 基于OpenCV和C++ 实现图片旋转

    图片旋转,本质上是对旋转后的图片中每个像素点计算在原图的位置.然后照搬过来就好. (多说一句,如果计算出来在原图中的位置不是整数而是小数,因为像素点个数都是整数,就需要小数到整数的转换.这个转换过程是有讲究的,需要用到插值:最近邻插值.双线性插值等等.这里我使用的是最简单的最近邻插值,即对小数四舍五入成整数,C/C++ 实现四舍五入见 这里 ) 图形图像课上一般会介绍旋转变换矩阵,其中 t 为需要旋转的角度,[x'; y']是变换后坐标(其中分号表示上下关系): 即表示为:[x'; y'] =

  • opencv图片的任意角度旋转实现示例

    目录 一 旋转角度坐标的计算 二 旋转任意角度的步骤 三 实现 一 旋转角度坐标的计算 1.如果O点为圆心,则点P绕点O旋转redian弧度之后,点P的坐标变换为点Q的计算公式为: Q.x=P.x*cos(redian)-P.y*sin(redian) Q.y=P.x*sin(redian)+P.y*cos(redian) redian表示的为弧度 弧度与角度的变换公式为: redian=pi*180/angle 2. 如果O点不是圆心,则点P绕点O旋转redian弧度之后,点P的坐标变换为Q的

  • java实现图片无损任意角度旋转

    前言 在做项目的时候遇到一个业务需要对图片进行旋转,于是找到一个工具类,亲测有效:在此与大家共享,需要用时可以直接用哈! 实战 一.旋转工具类代码: package zh.test.utils; import java.awt.*; import java.awt.image.BufferedImage; /** * 图片旋转工具类 */ public class RotateImage { /** * 对图片进行旋转 * * @param src 被旋转图片 * @param angel 旋转

  • Java实现图片翻转以及任意角度旋转

    最近几天在做一个项目,因为涉及到了图片(绝大部分都不是整图,是把一张张的大图切成小图,也就是Title)的翻转以及90°旋转,弄得焦头烂额.在网上搜索好几天,发现用到的方法都是比较公式化的,对于只是在绘图的时候需要显示翻转而不需要另外生成图片的情况,这些代码用起来非常的麻烦.最后仔细的研究了一下JDK文档,用Graphics2D很简单的就实现了以下功能: 1.图片的翻转,包括水平翻转以及垂直翻转 2.图片的任意角度旋转.因为工程需要,代码里面都直接写成了+90,根据需要,可以对这个值进行改动,以

  • Android中imageView图片放大缩小及旋转功能示例代码

    一.简介 二.方法 1)设置图片放大缩小效果 第一步:将<ImageView>标签中的android:scaleType设置为"fitCenter" android:scaleType="fitCenter" 第二步:获取屏幕的宽度 DisplayMetrics dm=new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(dm); dm.widthPixels 第三

  • Unity实现绕任意轴任意角度旋转向量

    本文实例为大家分享了Unity实现绕任意轴任意角度旋转向量的具体代码,供大家参考,具体内容如下 游戏中有一需求,就是一个矩形或者Cube绕着某一点旋转任意角度,现在给出下面算法. public static Vector3 RotateRound(Vector3 position, Vector3 center, Vector3 axis, float angle) { Vector3 point = Quaternion.AngleAxis(angle, axis) * (position -

  • Opencv 图片的OCR识别的实战示例

    一.图片变换 0.导入模块 导入相关函数,遇到报错的话,直接pip install 函数名. import numpy as np import argparse import cv2 参数初始化 ap = argparse.ArgumentParser() ap.add_argument("-i", "--image", required = True, help = "Path to the image to be scanned") arg

  • iOS中实现imageView任意角度旋转的方法

    前言 在实际的开发中我们可能会遇到这种情况: 需要对图片进行一定角度的旋转.对于这种需要,我们可能会用UIView的transform进行旋转,但是这样做其实只是对承载imageView的view进行了一定角度的旋转,而imageView并没有旋转.所有这样的做法并不好. 如果需要实现对imageView实现一定角度的旋转,具体步骤是: 1.将image转成context. 2.对context进行一定角度的旋转. 3.将旋转后的context 转化成image. 经过这三个步骤,我们就能够实现

  • java实现图片任意角度旋转

    本文实例为大家分享了Java实现图片旋转,供大家参考,具体内容如下 方法一:普通方法实现图片旋转 /** * 图像旋转 * @param src * @param angel * @return */ public static BufferedImage Rotate(Image src, double angel) { int src_width = src.getWidth(null); int src_height = src.getHeight(null); // calculate

  • C# 使用 GDI+ 实现添加中心旋转(任意角度)的文字

    前言 这篇文章是 GDI+ 总结系列的第三篇,如果对 GDI+ 的基础使用不熟悉的朋友可以先看第一篇文章<C# 使用 GDI+ 画图>. 需求 需求是要实现给图片添加任意角度旋转的文字,文字的旋转中心要是在文字区域中央,就像 CSS 的 rotate 函数一样的效果.如下: 分析&思路 Graphics 类有个 RotateTransform 方法,可以传入任意角度的值来旋转画板.但是这个方法的旋转中心是画板的左上角,所以直接单单用这个方法不能满足我们的需求.此外, Graphics

  • 让图片旋转任意角度及JQuery插件使用介绍

    引入下方的jquery.rotate.js文件,然后通过$("选择器").rotate(角度);可以旋转任意角度, 例如$("#rotate-image").rotate(45);把这句放在$(document).ready(function(){ });中 就是将id为rotate-image的图片旋转45度. 不过,貌似在Chrome中总是不显示. 唉,找了两个小时,才发现Chrome太坑爹了,没法获取图片的长宽. 解决办法是,把$("#rotate-

随机推荐