opencv实现坐标旋转(教你框住小姐姐)

 一、项目背景

最近在做一个人脸检测项目,需要接入百度AI的系统进行识别和检测。主要流程就是往指定的URL上post图片上去,之后接收检测结果就好了。

百度的检测结果包含这样的信息:

  left - 人脸区域离左边界的距离

  top - 人脸区域离上边界的距离

  width - 人脸区域的宽度

  height - 人脸区域的高度

  ratation 人脸框相对于竖直方向的顺时针旋转角[-180, 180].

如果我想把人脸框出来,很容易想到的是以(left, top)为左上顶点,以width 为宽,height为高,画一个矩形就好了。但其实这样是不合理的,如果人头是倒着的,这样画出来是不合理的。就像下面这样:

所以必须考虑把旋转角加上去。于是我想的策略是先把框画出来,再逆时针旋转ratation 就可以了。

二、如何旋转

大致策略就是:先算出四个点的左标,再以左上角的点为原点,逆时针旋转ratation 就ok了。四个点的左标比较容易确定,利用起点左标加宽高就能算出来。

这里主要讲解如何算旋转后的左标,如下图:

已知x1,x2,y1,y2和∠a,求x’,和y’。这时候就需要用到高中的三角函数的知识了。

假设,(x1, y1) 到 (x2, y2)的长度为r,再画一个∠b。

x’ = x1 + r * cos(a + b);

x’ = x1 + r * cos(a) * cos(b) - r * sin(a) * sin(b);

又因为:

r * cos(b) = x2 - x1;

r * sin(b) = (y2 - y1);

最终可以求出:

x’ = x1 + cos(a) * (x2 - x1) - sin(a) * (y2 - y1);

同理求出:

y’ = y1 + sin(a) * (x2 - x1) - cos(a) * (y2 - y1);

啊,这真是用了我毕生所学的数学知识,真没想到工作后还会用到三角函数的知识。还是要多学点数学知识才好啊。

三、源码

下面就是真正画图的东西了,为了测试这个公式是否可行,我用opencv画了一个四根线(其实就是一个方形),然后以左上角为顶点旋转。

下面的具体的代码,比较简单,主要是那个公式,所以也没什么注释。需要包含opencv头文件,以及链接opencv的库。

/*
 * @author:xcywt
 * @date:2018-08-10
 * @contact me: https://www.cnblogs.com/xcywt/
 */
#include<iostream>
#include "opencv2/highgui/highgui.hpp"

using namespace cv;
#define PI 3.14159265

#define ROTATE_COUNT 180
int RotateTest2()
{
    if (ROTATE_COUNT > 360)
    {
        return -1;
    }
    int x1 = 200, y1 = 200;
    int x2 = 300, y2 = 200;
    int x3 = 300, y3 = 300;
    int x4 = 200, y4 = 300;

    int arrX1[ROTATE_COUNT], arrY1[ROTATE_COUNT];
    int arrX2[ROTATE_COUNT], arrY2[ROTATE_COUNT];
    int arrX3[ROTATE_COUNT], arrY3[ROTATE_COUNT];
    int arrX4[ROTATE_COUNT], arrY4[ROTATE_COUNT];

    int nAgree = 0;
    for (int i = 0; i < ROTATE_COUNT; i++)
    {
        nAgree = i * (360 / ROTATE_COUNT);
        double dRot = nAgree * PI / 180;
        double dSinRot = sin(dRot), dCosRot = cos(dRot);

        arrX1[i] = x1;
        arrY1[i] = y1;

        arrX2[i] = x1 + dCosRot * (x2 - x1) - dSinRot * (y2 - y1); 
        arrY2[i] = y1 + dSinRot * (x2 - x1) + dCosRot * (y2 - y1);

        arrX3[i] = x1 + dCosRot * (x3 - x1) - dSinRot * (y3 - y1); 
        arrY3[i] = y1 + dSinRot * (x3 - x1) + dCosRot * (y3 - y1);

        arrX4[i] = x1 + dCosRot * (x4 - x1) - dSinRot * (y4 - y1); 
        arrY4[i] = y1 + dSinRot * (x4 - x1) + dCosRot * (y4 - y1);
    }

    Mat im(800, 480, CV_8UC3);
    line(im, Point(x1, y1), Point(x2, y2), Scalar(89, 90, 90), 3);
    line(im, Point(x1, y1), Point(x4, y4), Scalar(89, 90, 90), 3);
    line(im, Point(x3, y3), Point(x2, y2), Scalar(89, 90, 90), 3);
    line(im, Point(x4, y4), Point(x3, y3), Scalar(89, 90, 90), 3);

    for (int i = 1; i < ROTATE_COUNT; i++)
    {
        line(im, Point(arrX1[i], arrY1[i]), Point(arrX2[i], arrY2[i]), Scalar(189, 255, 0), 1);
        line(im, Point(arrX1[i], arrY1[i]), Point(arrX4[i], arrY4[i]), Scalar(189, 255, 0), 1);
        line(im, Point(arrX3[i], arrY3[i]), Point(arrX2[i], arrY2[i]), Scalar(189, 255, 0), 1);
        line(im, Point(arrX4[i], arrY4[i]), Point(arrX3[i], arrY3[i]), Scalar(189, 255, 0), 1);
    }
    imshow("Is ok", im);
    cvWaitKey(0);

    return 0;
}

int RotateTest()
{
    int nAgree = 170; 
    double dRot = nAgree * PI / 180;
    double dSinRot = sin(dRot), dCosRot = cos(dRot);

    int x1 = 200, y1 = 200;
    int x2 = 300, y2 = 200;
    int x3 = 300, y3 = 300;
    int x4 = 200, y4 = 300;

    int x1_1 = x1, y1_1 = y1;
    int x2_1 = x1 + dCosRot * (x2 - x1) - dSinRot * (y2 - y1), y2_1 = y1 + dSinRot * (x2 - x1) + dCosRot * (y2 - y1);
    int x3_1 = x1 + dCosRot * (x3 - x1) - dSinRot * (y3 - y1), y3_1 = y1 + dSinRot * (x3 - x1) + dCosRot * (y3 - y1);
    int x4_1 = x1 + dCosRot * (x4 - x1) - dSinRot * (y4 - y1), y4_1 = y1 + dSinRot * (x4 - x1) + dCosRot * (y4 - y1);

    std::cout << "P1:(" << x1 << " , " << y1 << ") --> (" << x1_1 << ", " << y1_1 << ")" << std::endl;
    std::cout << "P2:(" << x2 << " , " << y2 << ") --> (" << x2_1 << ", " << y2_1 << ")" << std::endl;
    std::cout << "P3:(" << x3 << " , " << y3 << ") --> (" << x3_1 << ", " << y3_1 << ")" << std::endl;
    std::cout << "P4:(" << x4 << " , " << y4 << ") --> (" << x4_1 << ", " << y4_1 << ")" << std::endl;

    Mat im(800, 480, CV_8UC3);
    line(im, Point(x1, y1), Point(x2, y2), Scalar(89, 90, 90), 2);
    line(im, Point(x1, y1), Point(x4, y4), Scalar(89, 90, 90), 2);
    line(im, Point(x3, y3), Point(x2, y2), Scalar(89, 90, 90), 2);
    line(im, Point(x4, y4), Point(x3, y3), Scalar(89, 90, 90), 2);

    line(im, Point(x1_1, y1_1), Point(x2_1, y2_1), Scalar(189, 0, 0), 2);
    line(im, Point(x1_1, y1_1), Point(x4_1, y4_1), Scalar(189, 0, 0), 2);
    line(im, Point(x3_1, y3_1), Point(x2_1, y2_1), Scalar(189, 0, 0), 2);
    line(im, Point(x4_1, y4_1), Point(x3_1, y3_1), Scalar(189, 0, 0), 2);

    imshow("Is ok", im);
    cvWaitKey(0);
    return 0;

}

int main()
{
    //RotateTest();
    RotateTest2();
    return 0;
}

其中RotateTest2()实现了在一个Mat上,画出了旋转各个角度的样子,具体把360分成 ROTATE_COUNT这么多份。可以看到效果还是很好看的。

ROTATE_COUNT为10时:

ROTATE_COUNT为60时:

ROTATE_COUNT为180时:

ROTATE_COUNT为360时:

旋转之后的神仙姐姐就框的比较准确了。这样就能正确的框住小姐姐了。

四、总结

数学还是很有用的。人工智能、深度学习还是需要具备数学知识的。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏书山有路勤为径

颜色转换,利用HSV颜色空间检测

绘制出这些通道的灰度版本 以便观察各通道的强度,像素越亮 代表的红色、绿色或蓝色值就越高。我们可以看到 粉色气球的红色值很高 蓝色值也相对比较高,但值大小不一 ...

931
来自专栏PPV课数据科学社区

R语言建立回归分析,并利用VIF查看共线性问题的例子

使用R对内置longley数据集进行回归分析,如果以GNP.deflator作为因变量y,问这个数据集是否存在多重共线性问题?应该选择哪些变量参与回归? 答: ...

5298
来自专栏专知

SIGIR 2018 信息检索领域顶级学术会议接受论文列表

5593
来自专栏专知

【最新】机器学习顶会 NIPS 2017 Pre-Proceedings 论文列表(附pdf下载链接)

【导读】机器学习领域顶尖学术会议——神经信息处理系统进展大会(Advances in NeuralInformation Processing Systems,...

5769
来自专栏AI科技大本营的专栏

ICLR vs arxiv-sanity

我觉得交叉对比 ICLR 2017(一个备受欢迎的深度学习大会)的论文决策(分为四类:Oral、Poster、Workshop 和 Reject)与所有论文在 ...

4055
来自专栏LhWorld哥陪你聊算法

Python可视化库Matplotlib的使用

2273
来自专栏机器学习算法工程师

OpenCV从零基础---检测及分割图像的目标区域

作者:王抒伟 编辑:王抒伟 算了 爱看多久看多久 零 参考目录: 1.获取图片 2.转换灰度并去噪声 3.提取图像的梯度 4.我们继续去噪声 5.图像形态学...

4K10
来自专栏专知

【论文推荐】最新5篇网络节点表示(Network Embedding)相关论文—高阶网络、矩阵分解、多视角、虚拟网络、云计算

【导读】专知内容组整理了最近五篇网络节点表示(Network Embedding)相关文章,为大家进行介绍,欢迎查看! 1. HONE: Higher-Orde...

1.6K7
来自专栏专知

【论文推荐】最新六篇图像描述生成相关论文—视频摘要、注意力张量积、非自回归神经序列模型、副词识别、多主体、多样性度量

【导读】专知内容组整理了最近六篇图像描述生成(Image Caption)相关文章,为大家进行介绍,欢迎查看! 1. Textually Customized ...

3977
来自专栏机器之心

ACL 2017接受了哪些论文?这份可视化分析让你轻松看懂(附论文列表)

选自ACL 2017 机器之心报道 参与:蒋思源 国际计算语言学协会 (ACL,The Association for Computational Lingui...

3859

扫码关注云+社区

领取腾讯云代金券